<!-- Wanted to avoid copying .css to each folder, so copied default .css from doxyen in here, kicked out most stuff we don't need for examples and modified some a little bit.
Target was having a single html in each example folder which is created from the main.cpp files and needs no files besides some images below media folder.
<p>This tutorial shows how to use shaders for D3D8, D3D9, OpenGL, and Cg with the engine and how to create new material types with them. It also shows how to disable the generation of mipmaps at texture loading, and how to use text scene nodes.</p>
<p>This tutorial does not explain how shaders work. I would recommend to read the D3D, OpenGL, or Cg documentation, to search a tutorial, or to read a book about this.</p>
<p>At first, we need to include all headers and do the stuff we always do, like in nearly all other tutorials: </p><divclass="fragment"><divclass="line"><spanclass="preprocessor">#include <irrlicht.h></span></div><divclass="line"><spanclass="preprocessor">#include <iostream></span></div><divclass="line"><spanclass="preprocessor">#include "driverChoice.h"</span></div><divclass="line"></div><divclass="line"><spanclass="keyword">using namespace </span>irr;</div><divclass="line"></div><divclass="line"><spanclass="preprocessor">#ifdef _MSC_VER</span></div><divclass="line"><spanclass="preprocessor">#pragma comment(lib, "Irrlicht.lib")</span></div><divclass="line"><spanclass="preprocessor">#endif</span></div></div><!-- fragment --><p> Because we want to use some interesting shaders in this tutorials, we need to set some data for them to make them able to compute nice colors. In this example, we'll use a simple vertex shader which will calculate the color of the vertex based on the position of the camera. For this, the shader needs the following data: The inverted world matrix for transforming the normal, the clip matrix for transforming the position, the camera position and the world position of the object for the calculation of the angle of light, and the color of the light. To be able to tell the shader all this data every frame, we have to derive a class from the IShaderConstantSetCallBack interface and override its only method, namely OnSetConstants(). This method will be called every time the material is set. The method setVertexShaderConstant() of the IMaterialRendererServices interface is used to set the data the shader needs. If the user chose to use a High Level shader language like HLSL instead of Assembler in this example, you have to set the variable name as parameter instead of the register index. </p><divclass="fragment"><divclass="line">IrrlichtDevice* device = 0;</div><divclass="line"><spanclass="keywordtype">bool</span> UseHighLevelShaders = <spanclass="keyword">false</span>;</div><divclass="line"><spanclass="keywordtype">bool</span> UseCgShaders = <spanclass="keyword">false</span>;</div><divclass="line"></div><divclass="line"><spanclass="keyword">class </span>MyShaderCallBack : <spanclass="keyword">public</span> video::IShaderConstantSetCallBack</div><divclass="line">{</div><divclass="line"><spanclass="keyword">public</span>:</div><divclass="line"></div><divclass="line"><spanclass="keyword">virtual</span><spanclass="keywordtype">void</span> OnSetConstants(video::IMaterialRendererServices* services,</div><divclass="line"> s32 userData)</div><divclass="line"> {</div><divclass="line"> video::IVideoDriver* driver = services->getVideoDriver();</div><divclass="line"></div><divclass="line"><spanclass="comment">// set inverted world matrix</span></div><divclass="line"><spanclass="comment">// if we are using highlevel shaders (the user can select this when</span></div><divclass="line"><spanclass="comment">// starting the program), we must set the constants by name.</span></div><divclass="line"></div><divclass="line"> core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);</div><divclass="line"> invWorld.makeInverse();</div><divclass="line"></div><divclass="line"><spanclass="keywordflow">if</span> (UseHighLevelShaders)</div><divclass="line"> services->setVertexShaderConstant(<spanclass="stringliteral">"mInvWorld"</span>, invWorld.pointer(), 16);</div><divclass="line"><spanclass="keywordflow">else</span></div><divclass="line"> services->setVertexShaderConstant(invWorld.pointer(), 0, 4);</div><divclass="line"></div><divclass="line"><spanclass="comment">// set clip matrix</span></div><divclass="line"></div><divclass="line"> core::matrix4 worldViewProj;</div><divclass="line"> worldViewProj = driver->getTransform(video::ETS_PROJECTION);</div><divclass="line"> worldVie
<p>The parameters to this method are the following: First, the names of the files containing the code of the vertex and the pixel shader. If you would use addShaderMaterial() instead, you would not need file names, then you could write the code of the shader directly as string. The following parameter is a pointer to the IShaderConstantSetCallBack class we wrote at the beginning of this tutorial. If you don't want to set constants, set this to 0. The last parameter tells the engine which material it should use as base material.</p>
<p>To demonstrate this, we create two materials with a different base material, one with EMT_SOLID and one with EMT_TRANSPARENT_ADD_COLOR. </p><divclass="fragment"><divclass="line"><spanclass="comment">// create materials</span></div><divclass="line"></div><divclass="line">video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();</div><divclass="line">s32 newMaterialType1 = 0;</div><divclass="line">s32 newMaterialType2 = 0;</div><divclass="line"></div><divclass="line"><spanclass="keywordflow">if</span> (gpu)</div><divclass="line">{</div><divclass="line"> MyShaderCallBack* mc = <spanclass="keyword">new</span> MyShaderCallBack();</div><divclass="line"></div><divclass="line"><spanclass="comment">// create the shaders depending on if the user wanted high level</span></div><divclass="line"><spanclass="comment">// or low level shaders:</span></div><divclass="line"></div><divclass="line"><spanclass="keywordflow">if</span> (UseHighLevelShaders)</div><divclass="line"> {</div><divclass="line"><spanclass="comment">// Choose the desired shader type. Default is the native</span></div><divclass="line"><spanclass="comment">// shader type for the driver, for Cg pass the special</span></div><divclass="line"><spanclass="comment">// enum value EGSL_CG</span></div><divclass="line"><spanclass="keyword">const</span> video::E_GPU_SHADING_LANGUAGE shadingLanguage =</div><divclass="line"> UseCgShaders ? video::EGSL_CG:video::EGSL_DEFAULT;</div><divclass="line"></div><divclass="line"><spanclass="comment">// create material from high level shaders (hlsl, glsl or cg)</span></div><divclass="line"></div><divclass="line"> newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(</div><divclass="line"> vsFileName, <spanclass="stringliteral">"vertexMain"</span>, video::EVST_VS_1_1,</div><divclass="line"> psFileName, <spanclass="stringliteral">"pixelMain"</span>, video::EPST_PS_1_1,</div><divclass="line"> mc, video::EMT_SOLID, 0, shadingLanguage);</div><divclass="line"></div><divclass="line"> newMaterialType2 = gpu->addHighLevelShaderMaterialFromFiles(</div><divclass="line"> vsFileName, <spanclass="stringliteral">"vertexMain"</span>, video::EVST_VS_1_1,</div><divclass="line"> psFileName, <spanclass="stringliteral">"pixelMain"</span>, video::EPST_PS_1_1,</div><divclass="line"> mc, video::EMT_TRANSPARENT_ADD_COLOR, 0 , shadingLanguage);</div><divclass="line"> }</div><divclass="line"><spanclass="keywordflow">else</span></div><divclass="line"> {</div><divclass="line"><spanclass="comment">// create material from low level shaders (asm or arb_asm)</span></div><divclass="line"></div><divclass="line"> newMaterialType1 = gpu->addShaderMaterialFromFiles(vsFileName,</div><divclass="line"> psFileName, mc, video::EMT_SOLID);</div><divclass="line"></div><divclass="line"> newMaterialType2 = gpu->addShaderMaterialFromFiles(vsFileName,</div><divclass="line"> psFileName, mc, video::EMT_TRANSPARENT_ADD_COLOR);</div><divclass="line"> }</div><divclass="line"></div><divclass="line"> mc->drop();</div><divclass="line">}</div></div><!-- fragment --><p> Now it's time for testing the materials. We create a test cube and set the material we created. In addition, we add a text scene node to the cube and a rotation animator to make it look more interesting and important. </p><divclass="fragment"><divclass="line"><spanclass="comment">// create test scene node 1, with the new created material type 1</span></div><divclass="line"></div><divclass="line">scene::ISceneNode* node = smgr->addCubeSceneNode(50);</div><divclass="line">node->setPosition(core::vector3df(0,0,0));</div><divclass="line">node->setMaterialTexture(0, driver->getTexture(<spanclass="stringliteral">"../../media/wall.bmp"</span>));</div><divclass="