tutorial.html 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. <html>
  2. <head>
  3. <title>Irrlicht Engine Tutorial</title>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5. </head>
  6. <body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
  7. <br>
  8. <table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
  9. <tr>
  10. <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>
  11. <td bgcolor="#666699" width="100%">
  12. <div align="center">
  13. <div align="left"><b><font color="#FFFFFF">Tutorial 10. Shaders</font></b></div>
  14. </div>
  15. </td>
  16. </tr>
  17. <tr bgcolor="#eeeeff">
  18. <td height="90" colspan="2">
  19. <div align="left">
  20. <p> This tutorial shows how to use shaders for D3D8, D3D9 and OpenGL with
  21. the engine and how to create new material types with them. It also shows
  22. how to disable the generation of mipmaps at texture loading, and how
  23. to use text scene nodes.</p>
  24. <p>This tutorial does not explain how shaders work. I would recommend
  25. to read the D3D or OpenGL documentation, to search a tutorial, or to
  26. read a book about this.</p>
  27. <p>The program which is described here will look like this:</p>
  28. <p align="center"><img src="../../media/010shot.jpg" width="260" height="203"><br>
  29. </p>
  30. </div>
  31. </td>
  32. </tr>
  33. </table>
  34. <br>
  35. <table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
  36. <tr>
  37. <td bgcolor="#666699"> <b><font color="#FFFFFF">Lets start!</font></b></td>
  38. </tr>
  39. <tr>
  40. <td height="90" bgcolor="#eeeeff" valign="top"> <div align="left">
  41. <div align="left">
  42. <p>At first, we need to include all headers and do the stuff we always
  43. do, like in nearly all other tutorials:</p>
  44. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  45. <tr>
  46. <td> <pre>#include &lt;irrlicht.h&gt;<br>#include &lt;iostream&gt;<br><br>using namespace irr;<br><br>#pragma comment(lib, &quot;Irrlicht.lib&quot;)<br></pre></td>
  47. </tr>
  48. </table>
  49. <p>Because we want to use some interesting shaders in this tutorials,
  50. we need to set some data for them to make them able to compute nice
  51. colors. In this example, we'll use a simple vertex shader which will
  52. calculate the color of the vertex based on the position of the camera.
  53. For this, the shader needs the following data: The inverted world
  54. matrix for transforming the normal, the clip matrix for transforming
  55. the position, the camera position and the world position of the object
  56. for the calculation of the angle of light, and the color of the light.
  57. To be able to tell the shader all this data every frame, we have to
  58. derive a class from the IShaderConstantSetCallBack interface and override
  59. its only method, namely OnSetConstants(). This method will be called
  60. every time the material is set. <br>
  61. The method setVertexShaderConstant() of the IMaterialRendererServices
  62. interface is used to set the data the shader needs. If the user chose
  63. to use a High Level shader language like HLSL instead of Assembler
  64. in this example, you have to set the variable name as parameter instead
  65. of the register index.</p>
  66. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  67. <tr>
  68. <td> <pre>IrrlichtDevice* device = 0;<br>bool UseHighLevelShaders = false;<br><br>class MyShaderCallBack : public video::IShaderConstantSetCallBack<br>{<br>public:
  69. <br> virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)<br> {<br> video::IVideoDriver* driver = services-&gt;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-&gt;getTransform(video::ETS_WORLD);<br> invWorld.makeInverse();<br><br> if (UseHighLevelShaders)<br> services-&gt;setVertexShaderConstant(&quot;mInvWorld&quot;, &amp;invWorld.M[0], 16);<br> else<br> services-&gt;setVertexShaderConstant(&amp;invWorld.M[0], 0, 4);<br><font color="#006600"><br> // set clip matrix<br></font> core::matrix4 worldViewProj;<br> worldViewProj = driver-&gt;getTransform(video::ETS_PROJECTION); <br> worldViewProj *= driver-&gt;getTransform(video::ETS_VIEW);<br> worldViewProj *= driver-&gt;getTransform(video::ETS_WORLD);<br><br> if (UseHighLevelShaders)<br> services-&gt;setVertexShaderConstant(&quot;mWorldViewProj&quot;, &amp;worldViewProj.M[0], 16);<br> else<br> services-&gt;setVertexShaderConstant(&amp;worldViewProj.M[0], 4, 4);<br> <br><font color="#006600"> </font><font color="#006600">// set camera position<br></font> core::vector3df pos = device-&gt;getSceneManager()-&gt;<br> getActiveCamera()-&gt;getAbsolutePosition();<br><br> if (UseHighLevelShaders)<br> services-&gt;setVertexShaderConstant(&quot;mLightPos&quot;, reinterpret_cast&lt;f32*&gt;(&amp;pos), 3);<br> else<br> services-&gt;setVertexShaderConstant(reinterpret_cast&lt;f32*&gt;(&amp;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-&gt;setVertexShaderConstant(&quot;mLightColor&quot;, reinterpret_cast&lt;f32*&gt;(&amp;col), 4);<br> else<br> services-&gt;setVertexShaderConstant(reinterpret_cast&lt;f32*&gt;(&amp;col), 9, 1);<br><br><font color="#006600"> </font><font color="#006600">// set transposed world matrix<br></font> core::matrix4 world = driver-&gt;getTransform(video::ETS_WORLD);<br> world = world.getTransposed();<br><br> if (UseHighLevelShaders)<br> services-&gt;setVertexShaderConstant(&quot;mTransWorld&quot;, &amp;world.M[0], 16);<br> else<br> services-&gt;setVertexShaderConstant(&amp;world.M[0], 10, 4);<br> }<br>};</pre></td>
  70. </tr>
  71. </table>
  72. <p> The next few lines start up the engine. Just like in most other
  73. tutorials before. But in addition, we ask the user if he wants this
  74. example to use high level shaders if he selected a driver which is
  75. capable of doing so.</p>
  76. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  77. <tr>
  78. <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(&quot;Please select the driver you want for this example:\n&quot;\<br> &quot; (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n&quot;\<br> &quot; (d) Software Renderer\n (e) Apfelbaum Software Renderer\n&quot;\<br> &quot; (f) NullDevice\n (otherKey) exit\n\n&quot;);<br><br> char i;<br> std::cin &gt;&gt; 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)
  79. {<br> printf(&quot;<font color="#CC0000">Please press 'y' if you want to use high level shaders.\n</font>&quot;);<br> std::cin &gt;&gt; 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&lt;s32&gt;(640, 480));<br><br> if (device == 0)<br> {<br> printf(<font color="#CC0000">&quot;\nWas not able to create driver.\n&quot;\<br> &quot;Please restart and select another driver.\n&quot;</font>);<br> getch();<br> return 1;<br> } <br><br> video::IVideoDriver* driver = device-&gt;getVideoDriver();<br> scene::ISceneManager* smgr = device-&gt;getSceneManager();<br> gui::IGUIEnvironment* gui = device-&gt;getGUIEnvironment();</pre></td>
  80. </tr>
  81. </table>
  82. <p> Now for the more interesting parts. If we are using Direct3D, we
  83. want to load vertex and pixel shader programs, if we have<br>
  84. OpenGL, we want to use ARB fragment and vertex programs. I wrote the
  85. corresponding programs down into the files d3d8.ps, d3d8.vs, d3d9.ps,
  86. d3d9.vs, opengl.ps and opengl.vs. We only need the right filenames
  87. now. This is done in the following switch. Note, that it is not necessary
  88. to write the shaders into text files, like in this example. You can
  89. even write the shaders directly as strings into the cpp source file,
  90. and use later addShaderMaterial() instead of addShaderMaterialFromFiles().</p>
  91. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  92. <tr>
  93. <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 = &quot;../../media/d3d8.psh&quot;;<br> vsFileName = &quot;../../media/d3d8.vsh&quot;;<br> break;<br> case video::EDT_DIRECT3D9:<br> if (UseHighLevelShaders)<br> {<br> psFileName = &quot;../../media/d3d9.hlsl&quot;;<br> vsFileName = psFileName; <font color="#006600">// both shaders are in the same file</font><br> }<br> else<br> {<br> psFileName = &quot;../../media/d3d9.psh&quot;;<br> vsFileName = &quot;../../media/d3d9.vsh&quot;;<br> }<br> break;<br> case video::EDT_OPENGL:<br> if (UseHighLevelShaders)<br> {<br> psFileName = &quot;../../media/opengl.frag&quot;;<br> vsFileName = &quot;../../media/opengl.vert&quot;;<br> }<br> else<br> {<br> psFileName = &quot;../../media/opengl.psh&quot;;<br> vsFileName = &quot;../../media/opengl.vsh&quot;;<br> }<br> break;<br> }<br></pre>
  94. </td>
  95. </tr>
  96. </table>
  97. <p> In addition, we check if the hardware and the selected renderer
  98. is capable of executing the shaders we want. If not, we simply set
  99. the filename string to 0. This is not necessary, but useful in this
  100. example: For example, if the hardware is able to execute vertex shaders
  101. but not pixel shaders, we create a new material which only uses the
  102. vertex shader, and no pixel shader. Otherwise, if we would tell the
  103. engine to create this material and the engine sees that the hardware
  104. wouldn't be able to fullfill the request completely,<br>
  105. it would not create any new material at all. So in this example you
  106. would see at least the vertex shader in action, without the pixel
  107. shader.</p>
  108. </div>
  109. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  110. <tr>
  111. <td> <pre> if (!driver-&gt;queryFeature(video::EVDF_PIXEL_SHADER_1_1) &amp;&amp;<br> !driver-&gt;queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1))<br> {<br> device-&gt;getLogger()-&gt;log(&quot;WARNING: Pixel shaders disabled &quot;\<br> &quot;because of missing driver/hardware support.&quot;);<br> psFileName = 0;<br> }<br> <br> if (!driver-&gt;queryFeature(video::EVDF_VERTEX_SHADER_1_1) &amp;&amp;<br> !driver-&gt;queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))<br> {<br> device-&gt;getLogger()-&gt;log(&quot;WARNING: Vertex shaders disabled &quot;\<br> &quot;because of missing driver/hardware support.&quot;);<br> vsFileName = 0;<br> }</pre></td>
  112. </tr>
  113. </table>
  114. <p> Now lets create the new materials.<br>
  115. As you maybe know from previous examples, a material type in the Irrlicht
  116. engine is set by simply changing the MaterialType value in the SMaterial
  117. struct. And this value is just a simple 32 bit value, like video::EMT_SOLID.
  118. So we only need the engine to create a new value for us which we can
  119. set there. To do this, we get a pointer to the IGPUProgrammingServices
  120. and call addShaderMaterialFromFiles(), which returns such a new 32 bit
  121. value. That's all.<br>
  122. The parameters to this method are the following: First, the names of
  123. the files containing the code of the vertex and the pixel shader.<br>
  124. If you would use addShaderMaterial() instead, you would not need file
  125. names, then you could write the code of the shader directly as string.
  126. The following parameter is a pointer to the IShaderConstantSetCallBack
  127. class we wrote at the beginning of this tutorial. If you don't want
  128. to set constants, set this to 0. The last paramter tells the engine
  129. which material it should use as base material. <br>
  130. To demonstrate this, we create two materials with a different base material,
  131. one with EMT_SOLID and one with EMT_TRANSPARENT_ADD_COLOR.</p>
  132. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  133. <tr>
  134. <td><pre> <font color="#006600">// create materials</font><br><br> video::IGPUProgrammingServices* gpu = driver-&gt;getGPUProgrammingServices();<br><br> s32 newMaterialType1 = 0;<br> s32 newMaterialType2 = 0;<br><br> if (gpu)<br> {<br> MyShaderCallBack* mc = new MyShaderCallBack();<br> <font color="#006600">
  135. // 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-&gt;addHighLevelShaderMaterialFromFiles(<br> vsFileName, &quot;vertexMain&quot;, video::EVST_VS_1_1,<br> psFileName, &quot;pixelMain&quot;, video::EPST_PS_1_1,<br> mc, video::EMT_SOLID);<br><br> newMaterialType2 = gpu-&gt;addHighLevelShaderMaterialFromFiles(<br> vsFileName, &quot;vertexMain&quot;, video::EVST_VS_1_1,<br> psFileName, &quot;pixelMain&quot;, 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-&gt;addShaderMaterialFromFiles(vsFileName,<br> psFileName, mc, video::EMT_SOLID);<br><br> newMaterialType2 = gpu-&gt;addShaderMaterialFromFiles(vsFileName,<br> psFileName, mc, video::EMT_TRANSPARENT_ADD_COLOR);<br> }<br><br> mc-&gt;drop();<br> }<br></pre></td>
  136. </tr>
  137. </table>
  138. <p> Now its time for testing out the materials. We create a test cube
  139. and set the material we created. In addition, we add a text scene node
  140. to the cube and a rotatation animator, to make it look more interesting
  141. and important. </p>
  142. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  143. <tr>
  144. <td><pre><font color="#006600">
  145. // create test scene node 1, with the new created material type 1</font>
  146. scene::ISceneNode* node = smgr-&gt;addCubeSceneNode(50);
  147. node-&gt;setPosition(core::vector3df(0,0,0));
  148. node-&gt;setMaterialTexture(0, driver-&gt;getTexture(&quot;../../media/wall.bmp&quot;));
  149. node-&gt;setMaterialFlag(video::EMF_LIGHTING, false);
  150. node-&gt;setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);
  151. smgr-&gt;addTextSceneNode(gui-&gt;getBuiltInFont(),
  152. L&quot;PS &amp; VS &amp; EMT_SOLID&quot;,
  153. video::SColor(255,255,255,255), node);
  154. scene::ISceneNodeAnimator* anim = smgr-&gt;createRotationAnimator(
  155. core::vector3df(0,0.3f,0));
  156. node-&gt;addAnimator(anim);
  157. anim-&gt;drop();</pre></td>
  158. </tr>
  159. </table>
  160. <p> Same for the second cube, but with the second material we created.</p>
  161. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  162. <tr>
  163. <td><pre> <font color="#006600">// create test scene node 2, with the new created material type 2</font>
  164. node = smgr-&gt;addCubeSceneNode(50);
  165. node-&gt;setPosition(core::vector3df(0,-10,50));
  166. node-&gt;setMaterialTexture(0, driver-&gt;getTexture(&quot;../../media/wall.bmp&quot;));
  167. node-&gt;setMaterialFlag(video::EMF_LIGHTING, false);
  168. node-&gt;setMaterialType((video::E_MATERIAL_TYPE)newMaterialType2);
  169. smgr-&gt;addTextSceneNode(gui-&gt;getBuiltInFont(),
  170. L&quot;PS &amp; VS &amp; EMT_TRANSPARENT&quot;,
  171. video::SColor(255,255,255,255), node);
  172. anim = smgr-&gt;createRotationAnimator(core::vector3df(0,0.3f,0));
  173. node-&gt;addAnimator(anim);
  174. anim-&gt;drop();</pre></td>
  175. </tr>
  176. </table>
  177. <br>
  178. Then we add a third cube without a shader on it, to be able to compare
  179. the cubes.<br>
  180. <br>
  181. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  182. <tr>
  183. <td><pre> <font color="#006600">// add a scene node with no shader </font>
  184. node = smgr-&gt;addCubeSceneNode(50);
  185. node-&gt;setPosition(core::vector3df(0,50,25));
  186. node-&gt;setMaterialTexture(0, driver-&gt;getTexture(&quot;../../media/wall.bmp&quot;));
  187. node-&gt;setMaterialFlag(video::EMF_LIGHTING, false);
  188. smgr-&gt;addTextSceneNode(gui-&gt;getBuiltInFont(), L&quot;NO SHADER&quot;,
  189. video::SColor(255,255,255,255), node);
  190. </pre></td>
  191. </tr>
  192. </table>
  193. <br>
  194. And last, we add a skybox and a user controlled camera to the scene. For
  195. the skybox textures, we disable mipmap generation, because we don't need
  196. mipmaps on it.<br>
  197. <br>
  198. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  199. <tr>
  200. <td><pre> <font color="#006600">// add a nice skybox</font><br><br> driver-&gt;setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);<br><br> smgr-&gt;addSkyBoxSceneNode(<br> driver-&gt;getTexture(&quot;../../media/irrlicht2_up.jpg&quot;),<br> driver-&gt;getTexture(&quot;../../media/irrlicht2_dn.jpg&quot;),<br> driver-&gt;getTexture(&quot;../../media/irrlicht2_lf.jpg&quot;),<br> driver-&gt;getTexture(&quot;../../media/irrlicht2_rt.jpg&quot;),<br> driver-&gt;getTexture(&quot;../../media/irrlicht2_ft.jpg&quot;),<br> driver-&gt;getTexture(&quot;../../media/irrlicht2_bk.jpg&quot;));<br><br> driver-&gt;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-&gt;addCameraSceneNodeFPS(0, 100.0f, 100.0f);<br> cam-&gt;setPosition(core::vector3df(-100,50,100));<br> cam-&gt;setTarget(core::vector3df(0,0,0));<br> device-&gt;getCursorControl()-&gt;setVisible(false);</pre></td>
  201. </tr>
  202. </table>
  203. <br>
  204. Now draw everything. That's all.<br>
  205. <br>
  206. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  207. <tr>
  208. <td><pre> int lastFPS = -1;<br><br> while(device-&gt;run())<br> if (device-&gt;isWindowActive())<br> {<br> driver-&gt;beginScene(true, true, video::SColor(255,0,0,0));<br> smgr-&gt;drawAll();<br> driver-&gt;endScene();<br><br> int fps = driver-&gt;getFPS();<br><br> if (lastFPS != fps)<br> {<br> core::stringw str = L&quot;Irrlicht Engine - Vertex and pixel shader example [&quot;;<br> str += driver-&gt;getName();<br> str += &quot;] FPS:&quot;;<br> str += fps;<br> device-&gt;setWindowCaption(str.c_str());<br> lastFPS = fps;<br> }<br> }<br><br> device-&gt;drop();<br> <br> return 0;<br></pre></td>
  209. </tr>
  210. </table>
  211. <br>
  212. Compile and run this, and I hope you have fun with your new little shader
  213. writing tool :).<br>
  214. </div>
  215. </td>
  216. </tr>
  217. </table>
  218. <br>
  219. <table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
  220. <tr>
  221. <td bgcolor="#666699"> <b><font color="#FFFFFF">Shader files</font></b></td>
  222. </tr>
  223. <tr>
  224. <td height="90" bgcolor="#eeeeff" valign="top"> <div align="left">
  225. <div align="left">
  226. <p>The files containing the shaders can be found in the media directory
  227. of the SDK. However, they look like this:</p>
  228. <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
  229. <tr>
  230. <td><strong>D3D9.HLSL</strong></td>
  231. </tr>
  232. <tr>
  233. <td>
  234. <pre>
  235. // part of the Irrlicht Engine Shader example.
  236. // These simple Direct3D9 pixel and vertex shaders will be loaded by the shaders
  237. // example. Please note that these example shaders don't do anything really useful.
  238. // They only demonstrate that shaders can be used in Irrlicht.
  239. //-----------------------------------------------------------------------------
  240. // Global variables
  241. //-----------------------------------------------------------------------------
  242. float4x4 mWorldViewProj; // World * View * Projection transformation
  243. float4x4 mInvWorld; // Inverted world matrix
  244. float4x4 mTransWorld; // Transposed world matrix
  245. float3 mLightPos; // Light position
  246. float4 mLightColor; // Light color
  247. // Vertex shader output structure
  248. struct VS_OUTPUT
  249. {
  250. float4 Position : POSITION; // vertex position
  251. float4 Diffuse : COLOR0; // vertex diffuse color
  252. float2 TexCoord : TEXCOORD0; // tex coords
  253. };
  254. VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
  255. in float3 vNormal : NORMAL,
  256. float2 texCoord : TEXCOORD0 )
  257. {
  258. VS_OUTPUT Output;
  259. // transform position to clip space
  260. Output.Position = mul(vPosition, mWorldViewProj);
  261. // transform normal
  262. float3 normal = mul(vNormal, mInvWorld);
  263. // renormalize normal
  264. normal = normalize(normal);
  265. // position in world coodinates
  266. float3 worldpos = mul(mTransWorld, vPosition);
  267. // calculate light vector, vtxpos - lightpos
  268. float3 lightVector = worldpos - mLightPos;
  269. // normalize light vector
  270. lightVector = normalize(lightVector);
  271. // calculate light color
  272. float3 tmp = dot(-lightVector, normal);
  273. tmp = lit(tmp.x, tmp.y, 1.0);
  274. tmp = mLightColor * tmp.y;
  275. Output.Diffuse = float4(tmp.x, tmp.y, tmp.z, 0);
  276. Output.TexCoord = texCoord;
  277. return Output;
  278. }
  279. // Pixel shader output structure
  280. struct PS_OUTPUT
  281. {
  282. float4 RGBColor : COLOR0; // Pixel color
  283. };
  284. sampler2D tex0;
  285. PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,
  286. float4 Position : POSITION,
  287. float4 Diffuse : COLOR0 )
  288. {
  289. PS_OUTPUT Output;
  290. float4 col = tex2D( tex0, TexCoord ); // sample color map
  291. // multiply with diffuse and do other senseless operations
  292. Output.RGBColor = Diffuse * col;
  293. Output.RGBColor *= 4.0;
  294. return Output;
  295. }</pre></td>
  296. </tr>
  297. </table>
  298. <br>
  299. <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
  300. <tr>
  301. <td><strong>D3D9.VSH</strong></td>
  302. </tr>
  303. <tr>
  304. <td> <pre>
  305. ; part of the Irrlicht Engine Shader example.
  306. ; This Direct3D9 vertex shader will be loaded by the engine.
  307. ; Please note that these example shaders don't do anything really useful.
  308. ; They only demonstrate that shaders can be used in Irrlicht.<br>
  309. vs.1.1
  310. dcl_position v0; ; declare position
  311. dcl_normal v1; ; declare normal
  312. dcl_color v2; ; declare color
  313. dcl_texcoord0 v3; ; declare texture coordinate<br>
  314. ; transpose and transform position to clip space
  315. mul r0, v0.x, c4
  316. mad r0, v0.y, c5, r0
  317. mad r0, v0.z, c6, r0
  318. add oPos, c7, r0
  319. ; transform normal
  320. dp3 r1.x, v1, c0
  321. dp3 r1.y, v1, c1
  322. dp3 r1.z, v1, c2
  323. ; renormalize normal
  324. dp3 r1.w, r1, r1
  325. rsq r1.w, r1.w
  326. mul r1, r1, r1.w
  327. ; calculate light vector
  328. m4x4 r6, v0, c10 ; vertex into world position
  329. add r2, c8, -r6 ; vtxpos - lightpos
  330. ; normalize light vector
  331. dp3 r2.w, r2, r2
  332. rsq r2.w, r2.w
  333. mul r2, r2, r2.w
  334. ; calculate light color
  335. dp3 r3, r1, r2 ; dp3 with negative light vector
  336. lit r5, r3 ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y
  337. mul oD0, r5.y, c9 ; ouput diffuse color
  338. mov oT0, v3 ; store texture coordinates </pre> </td>
  339. </tr>
  340. </table>
  341. <br>
  342. <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
  343. <tr>
  344. <td><strong>D3D9.PSH</strong></td>
  345. </tr>
  346. <tr>
  347. <td> <pre>
  348. ; part of the Irrlicht Engine Shader example.
  349. ; This simple Direct3D9 pixel shader will be loaded by the engine.
  350. ; Please note that these example shaders don't do anything really useful.
  351. ; They only demonstrate that shaders can be used in Irrlicht.<br>
  352. ps.1.1
  353. tex t0 ; sample color map
  354. add r0, v0, v0 ; mulitply with color
  355. mul t0, t0, r0 ; mulitply with color
  356. add r0, t0, t0 ; make it brighter and store result
  357. </pre> </td>
  358. </tr>
  359. </table>
  360. <br>
  361. <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
  362. <tr>
  363. <td><strong>D3D8.VSH</strong></td>
  364. </tr>
  365. <tr>
  366. <td> <pre>
  367. ; part of the Irrlicht Engine Shader example.
  368. ; This Direct3D9 vertex shader will be loaded by the engine.
  369. ; Please note that these example shaders don't do anything really useful.
  370. ; They only demonstrate that shaders can be used in Irrlicht.<br>
  371. vs.1.1
  372. ; transpose and transform position to clip space
  373. mul r0, v0.x, c4
  374. mad r0, v0.y, c5, r0
  375. mad r0, v0.z, c6, r0
  376. add oPos, c7, r0
  377. ; transform normal
  378. dp3 r1.x, v1, c0
  379. dp3 r1.y, v1, c1
  380. dp3 r1.z, v1, c2
  381. ; renormalize normal
  382. dp3 r1.w, r1, r1
  383. rsq r1.w, r1.w
  384. mul r1, r1, r1.w
  385. ; calculate light vector
  386. m4x4 r6, v0, c10 ; vertex into world position
  387. add r2, c8, -r6 ; vtxpos - lightpos
  388. ; normalize light vector
  389. dp3 r2.w, r2, r2
  390. rsq r2.w, r2.w
  391. mul r2, r2, r2.w
  392. ; calculate light color
  393. dp3 r3, r1, r2 ; dp3 with negative light vector
  394. lit r5, r3 ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y
  395. mul oD0, r5.y, c9 ; ouput diffuse color
  396. mov oT0, v3 ; store texture coordinates </pre> </td>
  397. </tr>
  398. </table>
  399. <br>
  400. <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
  401. <tr>
  402. <td><strong>D3D8.PSH</strong></td>
  403. </tr>
  404. <tr>
  405. <td> <pre>
  406. ; part of the Irrlicht Engine Shader example.
  407. ; This simple Direct3D9 pixel shader will be loaded by the engine.
  408. ; Please note that these example shaders don't do anything really useful.
  409. ; They only demonstrate that shaders can be used in Irrlicht.<br>
  410. ps.1.1
  411. tex t0 ; sample color map
  412. mul_x2 t0, t0, v0 ; mulitply with color
  413. add r0, t0, t0 ; make it brighter and store result </pre> </td>
  414. </tr>
  415. </table>
  416. <br>
  417. <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
  418. <tr>
  419. <td><strong>OPENGL.VSH</strong></td>
  420. </tr>
  421. <tr>
  422. <td> <pre>
  423. !!ARBvp1.0
  424. # part of the Irrlicht Engine Shader example.
  425. # Please note that these example shaders don't do anything really useful.
  426. # They only demonstrate that shaders can be used in Irrlicht.<br>
  427. #input
  428. ATTRIB InPos = vertex.position;
  429. ATTRIB InColor = vertex.color;
  430. ATTRIB InNormal = vertex.normal;
  431. ATTRIB InTexCoord = vertex.texcoord;
  432. #output
  433. OUTPUT OutPos = result.position;
  434. OUTPUT OutColor = result.color;
  435. OUTPUT OutTexCoord = result.texcoord;
  436. PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.
  437. TEMP Temp;
  438. TEMP TempColor;
  439. TEMP TempNormal;
  440. TEMP TempPos;
  441. #transform position to clip space
  442. DP4 Temp.x, MVP[0], InPos;
  443. DP4 Temp.y, MVP[1], InPos;
  444. DP4 Temp.z, MVP[2], InPos;
  445. DP4 Temp.w, MVP[3], InPos;
  446. #transform normal
  447. DP3 TempNormal.x, InNormal.x, program.local[0];
  448. DP3 TempNormal.y, InNormal.y, program.local[1];
  449. DP3 TempNormal.z, InNormal.z, program.local[2];
  450. #renormalize normal
  451. DP3 TempNormal.w, TempNormal, TempNormal;
  452. RSQ TempNormal.w, TempNormal.w;
  453. MUL TempNormal, TempNormal, TempNormal.w;
  454. # calculate light vector
  455. DP4 TempPos.x, InPos, program.local[10]; # vertex into world position
  456. DP4 TempPos.y, InPos, program.local[11];
  457. DP4 TempPos.z, InPos, program.local[12];
  458. DP4 TempPos.w, InPos, program.local[13];
  459. ADD TempPos, program.local[8], -TempPos; # vtxpos - lightpos
  460. # normalize light vector
  461. DP3 TempPos.w, TempPos, TempPos;
  462. RSQ TempPos.w, TempPos.w;
  463. MUL TempPos, TempPos, TempPos.w;
  464. # calculate light color
  465. DP3 TempColor, TempNormal, TempPos; # dp3 with negative light vector
  466. LIT OutColor, TempColor; # clamp to zero if r3 < 0, r5 has diffuce component in r5.y
  467. MUL OutColor, TempColor.y, program.local[9]; # ouput diffuse color
  468. MOV OutColor.w, 1.0; # we want alpha to be always 1
  469. MOV OutTexCoord, InTexCoord; # store texture coordinate
  470. MOV OutPos, Temp;
  471. END</pre> </td>
  472. </tr>
  473. </table>
  474. <br>
  475. <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
  476. <tr>
  477. <td><strong>OPENGL.PSH</strong></td>
  478. </tr>
  479. <tr>
  480. <td> <pre>
  481. !!ARBfp1.0
  482. # part of the Irrlicht Engine Shader example.
  483. # Please note that these example shaders don't do anything really useful.
  484. # They only demonstrate that shaders can be used in Irrlicht.<br>
  485. #Input
  486. ATTRIB inTexCoord = fragment.texcoord; # texture coordinates
  487. ATTRIB inColor = fragment.color.primary; # interpolated diffuse color
  488. #Output
  489. OUTPUT outColor = result.color;
  490. TEMP texelColor;
  491. TEMP tmp;
  492. TXP texelColor, inTexCoord, texture, 2D;
  493. ADD tmp, inColor, inColor; # mulitply with color
  494. MUL texelColor, texelColor, tmp; # mulitply with color
  495. ADD outColor, texelColor, texelColor; # make it brighter and store result
  496. END </pre> </td>
  497. </tr>
  498. </table>
  499. <p>&nbsp; </p>
  500. </div>
  501. </div></td>
  502. </tr>
  503. </table>
  504. <p>&nbsp;</p>
  505. <p>&nbsp;</p>
  506. </body>
  507. </html>