So you're a programmer and own one of these vector computing monsters which we today still call graphic cards? Maybe you've always wanted to try out how it is to write code which runs on their pixel shader units. Because I am receiving lots of mails about this topic, and I'm tired of answering "buy and read a book about it", I've decided to write a small tutorial. And you'll see, it really is easy.
I'm using
HLSL for this tutorial - a high level shader programming language. It works with
Direct3D9, so this tutorial is windows only, but you could change this tutorial easily to OpenGL and GLSL if you like.
This tutorial also uses
Irrlicht, because this will keep the code small and easy to understand, so we can focus on the pixel shader. So just
download Irrlicht, paste this code and compile.
First, this hello world pixel shader just puts out a green pixel for every pixel drawn on the screen. The pixel shader is the red text in the beginning at the code. After you've compiled and run the program, play around with it. I'll explain things which may be unclear in the next part.
#include <irrlicht.h>
using namespace irr;
// This is our first pixel shader, written in HLSL.
// It simply puts out 'green' for every pixel drawn.
const char* pixelShader =
"sampler2D tex0; \
\
float4 pixelShader( float2 texCoord : TEXCOORD0, \
float4 color : COLOR0 ) : COLOR0 \
{ \
return float4(0,1,0,0); \
}";
// now fire up Irrlicht, create a small scene with a cube and
// controllable camera and feed the gpu with our pixel shader
int main()
{
IrrlichtDevice* device = createDevice(
video::EDT_DIRECTX9, core::dimension2d<s32>(640, 480));
if (device == 0)
return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver();
video::IGPUProgrammingServices* gpu =
driver->getGPUProgrammingServices();
s32 newMaterialType1 = 0;
if (gpu)
{
// create a new material for our pixel shader
newMaterialType1 = gpu->addHighLevelShaderMaterial(
0, 0, video::EVST_VS_1_1,
pixelShader, "pixelShader" );
}
// create a cube and set our created material with the pixel shader
scene::ISceneNode* node =
device->getSceneManager()->addTestSceneNode(50);
node->setMaterialTexture(0, driver->getTexture("data/wall.bmp"));
node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);
// add a user controlled camera and disable the mouse cursor
scene::ICameraSceneNode* cam =
device->getSceneManager()->addCameraSceneNodeFPS(0, 100.0f, 100.0f);
cam->setPosition(core::vector3df(-100,50,100));
cam->setTarget(core::vector3df(0,0,0));
device->getCursorControl()->setVisible(false);
// draw everything
while(device->run())
{
driver->beginScene(true, true, video::SColor(255,0,0,0));
device->getSceneManager()->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
The result will look like the following screenshot. Boring, right. But the green color is fully generated on the GPU (via the float4(0,1,0,0) line), a good point to start. We are going to improve the shader a bit in the next parts of the tutorial.
(Update: Follow this link directly to the
2nd part of the tutorial)
:-)