3
<title>Irrlicht Engine Tutorial</title>
4
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
7
<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
9
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
11
<td bgcolor="#666699" width="10"><b><a href="http://irrlicht.sourceforge.net" target="_blank"><img src="../../media/irrlichtlogo.jpg" width="88" height="31" border="0"></a></b></td>
12
<td bgcolor="#666699" width="100%">
14
<div align="left"><b><font color="#FFFFFF">Tutorial 10. Shaders</font></b></div>
18
<tr bgcolor="#eeeeff">
19
<td height="90" colspan="2">
21
<p> This tutorial shows how to use shaders for D3D8, D3D9 and OpenGL with
22
the engine and how to create new material types with them. It also shows
23
how to disable the generation of mipmaps at texture loading, and how
24
to use text scene nodes.</p>
25
<p>This tutorial does not explain how shaders work. I would recommend
26
to read the D3D or OpenGL documentation, to search a tutorial, or to
27
read a book about this.</p>
28
<p>The program which is described here will look like this:</p>
29
<p align="center"><img src="../../media/010shot.jpg" width="260" height="203"><br>
36
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
38
<td bgcolor="#666699"> <b><font color="#FFFFFF">Lets start!</font></b></td>
41
<td height="90" bgcolor="#eeeeff" valign="top"> <div align="left">
43
<p>At first, we need to include all headers and do the stuff we always
44
do, like in nearly all other tutorials:</p>
45
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
47
<td> <pre>#include <irrlicht.h><br>#include <iostream><br><br>using namespace irr;<br><br>#pragma comment(lib, "Irrlicht.lib")<br></pre></td>
50
<p>Because we want to use some interesting shaders in this tutorials,
51
we need to set some data for them to make them able to compute nice
52
colors. In this example, we'll use a simple vertex shader which will
53
calculate the color of the vertex based on the position of the camera.
54
For this, the shader needs the following data: The inverted world
55
matrix for transforming the normal, the clip matrix for transforming
56
the position, the camera position and the world position of the object
57
for the calculation of the angle of light, and the color of the light.
58
To be able to tell the shader all this data every frame, we have to
59
derive a class from the IShaderConstantSetCallBack interface and override
60
its only method, namely OnSetConstants(). This method will be called
61
every time the material is set. <br>
62
The method setVertexShaderConstant() of the IMaterialRendererServices
63
interface is used to set the data the shader needs. If the user chose
64
to use a High Level shader language like HLSL instead of Assembler
65
in this example, you have to set the variable name as parameter instead
66
of the register index.</p>
67
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
69
<td> <pre>IrrlichtDevice* device = 0;<br>bool UseHighLevelShaders = false;<br><br>class MyShaderCallBack : public video::IShaderConstantSetCallBack<br>{<br>public:
70
<br> virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)<br> {<br> video::IVideoDriver* driver = services->getVideoDriver();<br><br> <font color="#006600">// set inverted world matrix<br> // if we are using highlevel shaders (the user can select this when<br> // starting the program), we must set the constants by name.</font><br> core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);<br> invWorld.makeInverse();<br><br> if (UseHighLevelShaders)<br> services->setVertexShaderConstant("mInvWorld", &invWorld.M[0], 16);<br> else<br> services->setVertexShaderConstant(&invWorld.M[0], 0, 4);<br><font color="#006600"><br> // set clip matrix<br></font> core::matrix4 worldViewProj;<br> worldViewProj = driver->getTransform(video::ETS_PROJECTION); <br> worldViewProj *= driver->getTransform(video::ETS_VIEW);<br> worldViewProj *= driver->getTransform(video::ETS_WORLD);<br><br> if (UseHighLevelShaders)<br> services->setVertexShaderConstant("mWorldViewProj", &worldViewProj.M[0], 16);<br> else<br> services->setVertexShaderConstant(&worldViewProj.M[0], 4, 4);<br> <br><font color="#006600"> </font><font color="#006600">// set camera position<br></font> core::vector3df pos = device->getSceneManager()-><br> getActiveCamera()->getAbsolutePosition();<br><br> if (UseHighLevelShaders)<br> services->setVertexShaderConstant("mLightPos", reinterpret_cast<f32*>(&pos), 3);<br> else<br> services->setVertexShaderConstant(reinterpret_cast<f32*>(&pos), 8, 1);<br><br><font color="#006600"> </font><font color="#006600">// set light color <br></font> video::SColorf col(0.0f,1.0f,1.0f,0.0f);<br><br> if (UseHighLevelShaders)<br> services->setVertexShaderConstant("mLightColor", reinterpret_cast<f32*>(&col), 4);<br> else<br> services->setVertexShaderConstant(reinterpret_cast<f32*>(&col), 9, 1);<br><br><font color="#006600"> </font><font color="#006600">// set transposed world matrix<br></font> core::matrix4 world = driver->getTransform(video::ETS_WORLD);<br> world = world.getTransposed();<br><br> if (UseHighLevelShaders)<br> services->setVertexShaderConstant("mTransWorld", &world.M[0], 16);<br> else<br> services->setVertexShaderConstant(&world.M[0], 10, 4);<br> }<br>};</pre></td>
73
<p> The next few lines start up the engine. Just like in most other
74
tutorials before. But in addition, we ask the user if he wants this
75
example to use high level shaders if he selected a driver which is
76
capable of doing so.</p>
77
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
79
<td> <pre>int main()<br>{<br><font color="#006600"> // let user select driver type</font><br><br> video::E_DRIVER_TYPE driverType = video::EDT_DIRECTX9;<br><br> printf("Please select the driver you want for this example:\n"\<br> " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\<br> " (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\<br> " (f) NullDevice\n (otherKey) exit\n\n");<br><br> char i;<br> std::cin >> i;<br><br> switch(i)<br> {<br> case 'a': driverType = video::EDT_DIRECT3D9;break;<br> case 'b': driverType = video::EDT_DIRECT3D8;break;<br> case 'c': driverType = video::EDT_OPENGL; break;<br> case 'd': driverType = video::EDT_SOFTWARE; break;<br> case 'e': driverType = video::EDT_BURNINGSVIDEO;break;<br> case 'f': driverType = video::EDT_NULL; break;<br> default: return 1;<br> } <br><br><font color="#006600"> </font> <font color="#006600">// ask the user if we should use high level shaders for this example<br> </font> if (driverType == video::EDT_DIRECT3D9 ||<br> driverType == video::EDT_OPENGL)
80
{<br> printf("<font color="#CC0000">Please press 'y' if you want to use high level shaders.\n</font>");<br> std::cin >> i;<br> if (i == 'y')<br> UseHighLevelShaders = true;<br> }<br><br><font color="#006600"> // create devic</font>e<br><br> device = createDevice(driverType, core::dimension2d<s32>(640, 480));<br><br> if (device == 0)<br> {<br> printf(<font color="#CC0000">"\nWas not able to create driver.\n"\<br> "Please restart and select another driver.\n"</font>);<br> getch();<br> return 1;<br> } <br><br> video::IVideoDriver* driver = device->getVideoDriver();<br> scene::ISceneManager* smgr = device->getSceneManager();<br> gui::IGUIEnvironment* gui = device->getGUIEnvironment();</pre></td>
83
<p> Now for the more interesting parts. If we are using Direct3D, we
84
want to load vertex and pixel shader programs, if we have<br>
85
OpenGL, we want to use ARB fragment and vertex programs. I wrote the
86
corresponding programs down into the files d3d8.ps, d3d8.vs, d3d9.ps,
87
d3d9.vs, opengl.ps and opengl.vs. We only need the right filenames
88
now. This is done in the following switch. Note, that it is not necessary
89
to write the shaders into text files, like in this example. You can
90
even write the shaders directly as strings into the cpp source file,
91
and use later addShaderMaterial() instead of addShaderMaterialFromFiles().</p>
92
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
94
<td> <pre> c8* vsFileName = 0<font color="#006600">; // filename for the vertex shader</font><br> c8* psFileName = 0<font color="#006600">; // filename for the pixel shader</font><br><br> switch(driverType)<br> {<br> case video::EDT_DIRECT3D8:<br> psFileName = "../../media/d3d8.psh";<br> vsFileName = "../../media/d3d8.vsh";<br> break;<br> case video::EDT_DIRECT3D9:<br> if (UseHighLevelShaders)<br> {<br> psFileName = "../../media/d3d9.hlsl";<br> vsFileName = psFileName; <font color="#006600">// both shaders are in the same file</font><br> }<br> else<br> {<br> psFileName = "../../media/d3d9.psh";<br> vsFileName = "../../media/d3d9.vsh";<br> }<br> break;<br> case video::EDT_OPENGL:<br> if (UseHighLevelShaders)<br> {<br> psFileName = "../../media/opengl.frag";<br> vsFileName = "../../media/opengl.vert";<br> }<br> else<br> {<br> psFileName = "../../media/opengl.psh";<br> vsFileName = "../../media/opengl.vsh";<br> }<br> break;<br> }<br></pre>
98
<p> In addition, we check if the hardware and the selected renderer
99
is capable of executing the shaders we want. If not, we simply set
100
the filename string to 0. This is not necessary, but useful in this
101
example: For example, if the hardware is able to execute vertex shaders
102
but not pixel shaders, we create a new material which only uses the
103
vertex shader, and no pixel shader. Otherwise, if we would tell the
104
engine to create this material and the engine sees that the hardware
105
wouldn't be able to fullfill the request completely,<br>
106
it would not create any new material at all. So in this example you
107
would see at least the vertex shader in action, without the pixel
110
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
112
<td> <pre> if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&<br> !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1))<br> {<br> device->getLogger()->log("WARNING: Pixel shaders disabled "\<br> "because of missing driver/hardware support.");<br> psFileName = 0;<br> }<br> <br> if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&<br> !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))<br> {<br> device->getLogger()->log("WARNING: Vertex shaders disabled "\<br> "because of missing driver/hardware support.");<br> vsFileName = 0;<br> }</pre></td>
115
<p> Now lets create the new materials.<br>
116
As you maybe know from previous examples, a material type in the Irrlicht
117
engine is set by simply changing the MaterialType value in the SMaterial
118
struct. And this value is just a simple 32 bit value, like video::EMT_SOLID.
119
So we only need the engine to create a new value for us which we can
120
set there. To do this, we get a pointer to the IGPUProgrammingServices
121
and call addShaderMaterialFromFiles(), which returns such a new 32 bit
122
value. That's all.<br>
123
The parameters to this method are the following: First, the names of
124
the files containing the code of the vertex and the pixel shader.<br>
125
If you would use addShaderMaterial() instead, you would not need file
126
names, then you could write the code of the shader directly as string.
127
The following parameter is a pointer to the IShaderConstantSetCallBack
128
class we wrote at the beginning of this tutorial. If you don't want
129
to set constants, set this to 0. The last paramter tells the engine
130
which material it should use as base material. <br>
131
To demonstrate this, we create two materials with a different base material,
132
one with EMT_SOLID and one with EMT_TRANSPARENT_ADD_COLOR.</p>
133
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
135
<td><pre> <font color="#006600">// create materials</font><br><br> video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();<br><br> s32 newMaterialType1 = 0;<br> s32 newMaterialType2 = 0;<br><br> if (gpu)<br> {<br> MyShaderCallBack* mc = new MyShaderCallBack();<br> <font color="#006600">
136
// create the shaders depending on if the user wanted high level<br> // or low level shaders:</font><br><br> if (UseHighLevelShaders)<br> {<br><font color="#006600"> // create material from high level shaders (hlsl or glsl)<br><br></font> newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(<br> vsFileName, "vertexMain", video::EVST_VS_1_1,<br> psFileName, "pixelMain", video::EPST_PS_1_1,<br> mc, video::EMT_SOLID);<br><br> newMaterialType2 = gpu->addHighLevelShaderMaterialFromFiles(<br> vsFileName, "vertexMain", video::EVST_VS_1_1,<br> psFileName, "pixelMain", video::EPST_PS_1_1,<br> mc, video::EMT_TRANSPARENT_ADD_COLOR);<br> }<br> else<br> {<br><font color="#009900"> // create material from low level shaders (asm or arb_asm)<br></font><br> newMaterialType1 = gpu->addShaderMaterialFromFiles(vsFileName,<br> psFileName, mc, video::EMT_SOLID);<br><br> newMaterialType2 = gpu->addShaderMaterialFromFiles(vsFileName,<br> psFileName, mc, video::EMT_TRANSPARENT_ADD_COLOR);<br> }<br><br> mc->drop();<br> }<br></pre></td>
139
<p> Now its time for testing out the materials. We create a test cube
140
and set the material we created. In addition, we add a text scene node
141
to the cube and a rotatation animator, to make it look more interesting
143
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
145
<td><pre><font color="#006600">
146
// create test scene node 1, with the new created material type 1</font>
148
scene::ISceneNode* node = smgr->addCubeSceneNode(50);
149
node->setPosition(core::vector3df(0,0,0));
150
node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
151
node->setMaterialFlag(video::EMF_LIGHTING, false);
152
node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);
154
smgr->addTextSceneNode(gui->getBuiltInFont(),
155
L"PS & VS & EMT_SOLID",
156
video::SColor(255,255,255,255), node);
158
scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
159
core::vector3df(0,0.3f,0));
160
node->addAnimator(anim);
161
anim->drop();</pre></td>
164
<p> Same for the second cube, but with the second material we created.</p>
165
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
167
<td><pre> <font color="#006600">// create test scene node 2, with the new created material type 2</font>
169
node = smgr->addCubeSceneNode(50);
170
node->setPosition(core::vector3df(0,-10,50));
171
node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
172
node->setMaterialFlag(video::EMF_LIGHTING, false);
173
node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType2);
175
smgr->addTextSceneNode(gui->getBuiltInFont(),
176
L"PS & VS & EMT_TRANSPARENT",
177
video::SColor(255,255,255,255), node);
179
anim = smgr->createRotationAnimator(core::vector3df(0,0.3f,0));
180
node->addAnimator(anim);
181
anim->drop();</pre></td>
185
Then we add a third cube without a shader on it, to be able to compare
188
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
190
<td><pre> <font color="#006600">// add a scene node with no shader </font>
192
node = smgr->addCubeSceneNode(50);
193
node->setPosition(core::vector3df(0,50,25));
194
node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
195
node->setMaterialFlag(video::EMF_LIGHTING, false);
196
smgr->addTextSceneNode(gui->getBuiltInFont(), L"NO SHADER",
197
video::SColor(255,255,255,255), node);
202
And last, we add a skybox and a user controlled camera to the scene. For
203
the skybox textures, we disable mipmap generation, because we don't need
206
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
208
<td><pre> <font color="#006600">// add a nice skybox</font><br><br> driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);<br><br> smgr->addSkyBoxSceneNode(<br> driver->getTexture("../../media/irrlicht2_up.jpg"),<br> driver->getTexture("../../media/irrlicht2_dn.jpg"),<br> driver->getTexture("../../media/irrlicht2_lf.jpg"),<br> driver->getTexture("../../media/irrlicht2_rt.jpg"),<br> driver->getTexture("../../media/irrlicht2_ft.jpg"),<br> driver->getTexture("../../media/irrlicht2_bk.jpg"));<br><br> driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);<br><br><font color="#006600"> // add a camera and disable the mouse curso</font>r<br><br> scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f);<br> cam->setPosition(core::vector3df(-100,50,100));<br> cam->setTarget(core::vector3df(0,0,0));<br> device->getCursorControl()->setVisible(false);</pre></td>
212
Now draw everything. That's all.<br>
214
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
216
<td><pre> int lastFPS = -1;<br><br> while(device->run())<br> if (device->isWindowActive())<br> {<br> driver->beginScene(true, true, video::SColor(255,0,0,0));<br> smgr->drawAll();<br> driver->endScene();<br><br> int fps = driver->getFPS();<br><br> if (lastFPS != fps)<br> {<br> core::stringw str = L"Irrlicht Engine - Vertex and pixel shader example [";<br> str += driver->getName();<br> str += "] FPS:";<br> str += fps;<br> device->setWindowCaption(str.c_str());<br> lastFPS = fps;<br> }<br> }<br><br> device->drop();<br> <br> return 0;<br></pre></td>
220
Compile and run this, and I hope you have fun with your new little shader
227
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
229
<td bgcolor="#666699"> <b><font color="#FFFFFF">Shader files</font></b></td>
232
<td height="90" bgcolor="#eeeeff" valign="top"> <div align="left">
234
<p>The files containing the shaders can be found in the media directory
235
of the SDK. However, they look like this:</p>
236
<table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
238
<td><strong>D3D9.HLSL</strong></td>
243
// part of the Irrlicht Engine Shader example.
244
// These simple Direct3D9 pixel and vertex shaders will be loaded by the shaders
245
// example. Please note that these example shaders don't do anything really useful.
246
// They only demonstrate that shaders can be used in Irrlicht.
248
//-----------------------------------------------------------------------------
250
//-----------------------------------------------------------------------------
251
float4x4 mWorldViewProj; // World * View * Projection transformation
252
float4x4 mInvWorld; // Inverted world matrix
253
float4x4 mTransWorld; // Transposed world matrix
254
float3 mLightPos; // Light position
255
float4 mLightColor; // Light color
258
// Vertex shader output structure
261
float4 Position : POSITION; // vertex position
262
float4 Diffuse : COLOR0; // vertex diffuse color
263
float2 TexCoord : TEXCOORD0; // tex coords
267
VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
268
in float3 vNormal : NORMAL,
269
float2 texCoord : TEXCOORD0 )
273
// transform position to clip space
274
Output.Position = mul(vPosition, mWorldViewProj);
277
float3 normal = mul(vNormal, mInvWorld);
279
// renormalize normal
280
normal = normalize(normal);
282
// position in world coodinates
283
float3 worldpos = mul(mTransWorld, vPosition);
285
// calculate light vector, vtxpos - lightpos
286
float3 lightVector = worldpos - mLightPos;
288
// normalize light vector
289
lightVector = normalize(lightVector);
291
// calculate light color
292
float3 tmp = dot(-lightVector, normal);
293
tmp = lit(tmp.x, tmp.y, 1.0);
295
tmp = mLightColor * tmp.y;
296
Output.Diffuse = float4(tmp.x, tmp.y, tmp.z, 0);
297
Output.TexCoord = texCoord;
304
// Pixel shader output structure
307
float4 RGBColor : COLOR0; // Pixel color
313
PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,
314
float4 Position : POSITION,
315
float4 Diffuse : COLOR0 )
319
float4 col = tex2D( tex0, TexCoord ); // sample color map
321
// multiply with diffuse and do other senseless operations
322
Output.RGBColor = Diffuse * col;
323
Output.RGBColor *= 4.0;
330
<table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
332
<td><strong>D3D9.VSH</strong></td>
336
; part of the Irrlicht Engine Shader example.
337
; This Direct3D9 vertex shader will be loaded by the engine.
338
; Please note that these example shaders don't do anything really useful.
339
; They only demonstrate that shaders can be used in Irrlicht.<br>
342
dcl_position v0; ; declare position
343
dcl_normal v1; ; declare normal
344
dcl_color v2; ; declare color
345
dcl_texcoord0 v3; ; declare texture coordinate<br>
346
; transpose and transform position to clip space
362
; calculate light vector
363
m4x4 r6, v0, c10 ; vertex into world position
364
add r2, c8, -r6 ; vtxpos - lightpos
366
; normalize light vector
371
; calculate light color
372
dp3 r3, r1, r2 ; dp3 with negative light vector
373
lit r5, r3 ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y
374
mul oD0, r5.y, c9 ; ouput diffuse color
375
mov oT0, v3 ; store texture coordinates </pre> </td>
379
<table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
381
<td><strong>D3D9.PSH</strong></td>
385
; part of the Irrlicht Engine Shader example.
386
; This simple Direct3D9 pixel shader will be loaded by the engine.
387
; Please note that these example shaders don't do anything really useful.
388
; They only demonstrate that shaders can be used in Irrlicht.<br>
391
tex t0 ; sample color map
392
add r0, v0, v0 ; mulitply with color
393
mul t0, t0, r0 ; mulitply with color
394
add r0, t0, t0 ; make it brighter and store result
399
<table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
401
<td><strong>D3D8.VSH</strong></td>
405
; part of the Irrlicht Engine Shader example.
406
; This Direct3D9 vertex shader will be loaded by the engine.
407
; Please note that these example shaders don't do anything really useful.
408
; They only demonstrate that shaders can be used in Irrlicht.<br>
411
; transpose and transform position to clip space
427
; calculate light vector
428
m4x4 r6, v0, c10 ; vertex into world position
429
add r2, c8, -r6 ; vtxpos - lightpos
431
; normalize light vector
436
; calculate light color
437
dp3 r3, r1, r2 ; dp3 with negative light vector
438
lit r5, r3 ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y
439
mul oD0, r5.y, c9 ; ouput diffuse color
440
mov oT0, v3 ; store texture coordinates </pre> </td>
444
<table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
446
<td><strong>D3D8.PSH</strong></td>
450
; part of the Irrlicht Engine Shader example.
451
; This simple Direct3D9 pixel shader will be loaded by the engine.
452
; Please note that these example shaders don't do anything really useful.
453
; They only demonstrate that shaders can be used in Irrlicht.<br>
456
tex t0 ; sample color map
457
mul_x2 t0, t0, v0 ; mulitply with color
458
add r0, t0, t0 ; make it brighter and store result </pre> </td>
462
<table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
464
<td><strong>OPENGL.VSH</strong></td>
469
# part of the Irrlicht Engine Shader example.
470
# Please note that these example shaders don't do anything really useful.
471
# They only demonstrate that shaders can be used in Irrlicht.<br>
473
ATTRIB InPos = vertex.position;
474
ATTRIB InColor = vertex.color;
475
ATTRIB InNormal = vertex.normal;
476
ATTRIB InTexCoord = vertex.texcoord;
479
OUTPUT OutPos = result.position;
480
OUTPUT OutColor = result.color;
481
OUTPUT OutTexCoord = result.texcoord;
483
PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.
489
#transform position to clip space
490
DP4 Temp.x, MVP[0], InPos;
491
DP4 Temp.y, MVP[1], InPos;
492
DP4 Temp.z, MVP[2], InPos;
493
DP4 Temp.w, MVP[3], InPos;
496
DP3 TempNormal.x, InNormal.x, program.local[0];
497
DP3 TempNormal.y, InNormal.y, program.local[1];
498
DP3 TempNormal.z, InNormal.z, program.local[2];
501
DP3 TempNormal.w, TempNormal, TempNormal;
502
RSQ TempNormal.w, TempNormal.w;
503
MUL TempNormal, TempNormal, TempNormal.w;
505
# calculate light vector
506
DP4 TempPos.x, InPos, program.local[10]; # vertex into world position
507
DP4 TempPos.y, InPos, program.local[11];
508
DP4 TempPos.z, InPos, program.local[12];
509
DP4 TempPos.w, InPos, program.local[13];
511
ADD TempPos, program.local[8], -TempPos; # vtxpos - lightpos
513
# normalize light vector
514
DP3 TempPos.w, TempPos, TempPos;
515
RSQ TempPos.w, TempPos.w;
516
MUL TempPos, TempPos, TempPos.w;
518
# calculate light color
519
DP3 TempColor, TempNormal, TempPos; # dp3 with negative light vector
520
LIT OutColor, TempColor; # clamp to zero if r3 < 0, r5 has diffuce component in r5.y
521
MUL OutColor, TempColor.y, program.local[9]; # ouput diffuse color
522
MOV OutColor.w, 1.0; # we want alpha to be always 1
523
MOV OutTexCoord, InTexCoord; # store texture coordinate
530
<table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
532
<td><strong>OPENGL.PSH</strong></td>
537
# part of the Irrlicht Engine Shader example.
538
# Please note that these example shaders don't do anything really useful.
539
# They only demonstrate that shaders can be used in Irrlicht.<br>
541
ATTRIB inTexCoord = fragment.texcoord; # texture coordinates
542
ATTRIB inColor = fragment.color.primary; # interpolated diffuse color
545
OUTPUT outColor = result.color;
549
TXP texelColor, inTexCoord, texture, 2D;
551
ADD tmp, inColor, inColor; # mulitply with color
552
MUL texelColor, texelColor, tmp; # mulitply with color
553
ADD outColor, texelColor, texelColor; # make it brighter and store result