GLES drivers adapted, but only did make compile-tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			567 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			567 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<html>
 | 
						|
<head>
 | 
						|
<title>Irrlicht Engine Tutorial</title>
 | 
						|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
						|
</head>
 | 
						|
 | 
						|
<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
 | 
						|
<br>
 | 
						|
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
 | 
						|
  <tr> 
 | 
						|
    <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>
 | 
						|
    <td bgcolor="#666699" width="100%">
 | 
						|
<div align="center">
 | 
						|
        <div align="left"><b><font color="#FFFFFF">Tutorial 10. Shaders</font></b></div>
 | 
						|
      </div>
 | 
						|
      </td>
 | 
						|
  </tr>
 | 
						|
  <tr bgcolor="#eeeeff"> 
 | 
						|
    <td height="90" colspan="2"> 
 | 
						|
      <div align="left"> 
 | 
						|
        <p> This tutorial shows how to use shaders for D3D8, D3D9 and OpenGL 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 or OpenGL documentation, to search a tutorial, or to 
 | 
						|
          read a book about this.</p>
 | 
						|
        <p>The program which is described here will look like this:</p>
 | 
						|
        <p align="center"><img src="../../media/010shot.jpg" width="260" height="203"><br>
 | 
						|
        </p>
 | 
						|
      </div>
 | 
						|
    </td>
 | 
						|
  </tr>
 | 
						|
</table>
 | 
						|
<br>
 | 
						|
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
 | 
						|
  <tr> 
 | 
						|
    <td bgcolor="#666699"> <b><font color="#FFFFFF">Lets start!</font></b></td>
 | 
						|
  </tr>
 | 
						|
  <tr> 
 | 
						|
    <td height="90" bgcolor="#eeeeff" valign="top"> <div align="left"> 
 | 
						|
        <div align="left"> 
 | 
						|
          <p>At first, we need to include all headers and do the stuff we always 
 | 
						|
            do, like in nearly all other tutorials:</p>
 | 
						|
          <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>#include <irrlicht.h><br>#include <iostream><br><br>using namespace irr;<br><br>#pragma comment(lib, "Irrlicht.lib")<br></pre></td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <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. <br>
 | 
						|
            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>
 | 
						|
          <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>IrrlichtDevice* device = 0;<br>bool UseHighLevelShaders = false;<br><br>class MyShaderCallBack : public video::IShaderConstantSetCallBack<br>{<br>public:
 | 
						|
<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>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <p> The next few lines start up the engine. Just like in most other 
 | 
						|
            tutorials before. But in addition, we ask the user if he wants this 
 | 
						|
            example to use high level shaders if he selected a driver which is 
 | 
						|
            capable of doing so.</p>
 | 
						|
          <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <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)
 | 
						|
  {<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>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <p> Now for the more interesting parts. If we are using Direct3D, we 
 | 
						|
            want to load vertex and pixel shader programs, if we have<br>
 | 
						|
            OpenGL, we want to use ARB fragment and vertex programs. I wrote the 
 | 
						|
            corresponding programs down into the files d3d8.ps, d3d8.vs, d3d9.ps, 
 | 
						|
            d3d9.vs, opengl.ps and opengl.vs. We only need the right filenames 
 | 
						|
            now. This is done in the following switch. Note, that it is not necessary 
 | 
						|
            to write the shaders into text files, like in this example. You can 
 | 
						|
            even write the shaders directly as strings into the cpp source file, 
 | 
						|
            and use later addShaderMaterial() instead of addShaderMaterialFromFiles().</p>
 | 
						|
          <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <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> 
 | 
						|
              </td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <p> In addition, we check if the hardware and the selected renderer 
 | 
						|
            is capable of executing the shaders we want. If not, we simply set 
 | 
						|
            the filename string to 0. This is not necessary, but useful in this 
 | 
						|
            example: For example, if the hardware is able to execute vertex shaders 
 | 
						|
            but not pixel shaders, we create a new material which only uses the 
 | 
						|
            vertex shader, and no pixel shader. Otherwise, if we would tell the 
 | 
						|
            engine to create this material and the engine sees that the hardware 
 | 
						|
            wouldn't be able to fullfill the request completely,<br>
 | 
						|
            it would not create any new material at all. So in this example you 
 | 
						|
            would see at least the vertex shader in action, without the pixel 
 | 
						|
            shader.</p>
 | 
						|
          </div>
 | 
						|
        <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
          <tr> 
 | 
						|
            <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>
 | 
						|
          </tr>
 | 
						|
        </table>
 | 
						|
        <p> Now lets create the new materials.<br>
 | 
						|
          As you maybe know from previous examples, a material type in the Irrlicht 
 | 
						|
          engine is set by simply changing the MaterialType value in the SMaterial 
 | 
						|
          struct. And this value is just a simple 32 bit value, like video::EMT_SOLID. 
 | 
						|
          So we only need the engine to create a new value for us which we can 
 | 
						|
          set there. To do this, we get a pointer to the IGPUProgrammingServices 
 | 
						|
          and call addShaderMaterialFromFiles(), which returns such a new 32 bit 
 | 
						|
          value. That's all.<br>
 | 
						|
          The parameters to this method are the following: First, the names of 
 | 
						|
          the files containing the code of the vertex and the pixel shader.<br>
 | 
						|
          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 paramter tells the engine 
 | 
						|
          which material it should use as base material. <br>
 | 
						|
          To demonstrate this, we create two materials with a different base material, 
 | 
						|
          one with EMT_SOLID and one with EMT_TRANSPARENT_ADD_COLOR.</p>
 | 
						|
        <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
          <tr> 
 | 
						|
            <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">
 | 
						|
		// 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>
 | 
						|
          </tr>
 | 
						|
        </table>
 | 
						|
        <p> Now its time for testing out 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 rotatation animator, to make it look more interesting 
 | 
						|
          and important. </p>
 | 
						|
        <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
          <tr> 
 | 
						|
            <td><pre><font color="#006600">
 | 
						|
	// create test scene node 1, with the new created material type 1</font>
 | 
						|
 | 
						|
	scene::ISceneNode* node = smgr->addCubeSceneNode(50);
 | 
						|
	node->setPosition(core::vector3df(0,0,0));
 | 
						|
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
 | 
						|
	node->setMaterialFlag(video::EMF_LIGHTING, false);
 | 
						|
	node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);
 | 
						|
 | 
						|
	smgr->addTextSceneNode(gui->getBuiltInFont(),
 | 
						|
			L"PS & VS & EMT_SOLID",
 | 
						|
			video::SColor(255,255,255,255),	node);
 | 
						|
 | 
						|
	scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
 | 
						|
			core::vector3df(0,0.3f,0));
 | 
						|
	node->addAnimator(anim);
 | 
						|
	anim->drop();</pre></td>
 | 
						|
          </tr>
 | 
						|
        </table>
 | 
						|
        <p> Same for the second cube, but with the second material we created.</p>
 | 
						|
        <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
          <tr> 
 | 
						|
            <td><pre>	<font color="#006600">// create test scene node 2, with the new created material type 2</font>
 | 
						|
 | 
						|
	node = smgr->addCubeSceneNode(50);
 | 
						|
	node->setPosition(core::vector3df(0,-10,50));
 | 
						|
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
 | 
						|
	node->setMaterialFlag(video::EMF_LIGHTING, false);
 | 
						|
	node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType2);
 | 
						|
 | 
						|
	smgr->addTextSceneNode(gui->getBuiltInFont(),
 | 
						|
			L"PS & VS & EMT_TRANSPARENT",
 | 
						|
			video::SColor(255,255,255,255),	node);
 | 
						|
 | 
						|
	anim = smgr->createRotationAnimator(core::vector3df(0,0.3f,0));
 | 
						|
	node->addAnimator(anim);
 | 
						|
	anim->drop();</pre></td>
 | 
						|
          </tr>
 | 
						|
        </table>
 | 
						|
        <br>
 | 
						|
        Then we add a third cube without a shader on it, to be able to compare 
 | 
						|
        the cubes.<br>
 | 
						|
        <br>
 | 
						|
        <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
          <tr> 
 | 
						|
            <td><pre>	<font color="#006600">// add a scene node with no shader </font>
 | 
						|
 | 
						|
	node = smgr->addCubeSceneNode(50);
 | 
						|
	node->setPosition(core::vector3df(0,50,25));
 | 
						|
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
 | 
						|
	node->setMaterialFlag(video::EMF_LIGHTING, false);
 | 
						|
	smgr->addTextSceneNode(gui->getBuiltInFont(), L"NO SHADER",
 | 
						|
		video::SColor(255,255,255,255), node);
 | 
						|
            </pre></td>
 | 
						|
          </tr>
 | 
						|
        </table>
 | 
						|
        <br>
 | 
						|
        And last, we add a skybox and a user controlled camera to the scene. For 
 | 
						|
        the skybox textures, we disable mipmap generation, because we don't need 
 | 
						|
        mipmaps on it.<br>
 | 
						|
        <br>
 | 
						|
        <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
          <tr> 
 | 
						|
            <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>
 | 
						|
          </tr>
 | 
						|
        </table>
 | 
						|
        <br>
 | 
						|
        Now draw everything. That's all.<br>
 | 
						|
        <br>
 | 
						|
        <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
          <tr> 
 | 
						|
            <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>
 | 
						|
          </tr>
 | 
						|
        </table>
 | 
						|
        <br>
 | 
						|
        Compile and run this, and I hope you have fun with your new little shader 
 | 
						|
        writing tool :).<br>
 | 
						|
      </div>
 | 
						|
      </td>
 | 
						|
  </tr>
 | 
						|
</table>
 | 
						|
<br>
 | 
						|
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
 | 
						|
  <tr> 
 | 
						|
    <td bgcolor="#666699"> <b><font color="#FFFFFF">Shader files</font></b></td>
 | 
						|
  </tr>
 | 
						|
  <tr> 
 | 
						|
    <td height="90" bgcolor="#eeeeff" valign="top"> <div align="left"> 
 | 
						|
        <div align="left"> 
 | 
						|
          <p>The files containing the shaders can be found in the media directory 
 | 
						|
            of the SDK. However, they look like this:</p>
 | 
						|
          <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td><strong>D3D9.HLSL</strong></td>
 | 
						|
            </tr>
 | 
						|
            <tr> 
 | 
						|
              <td>
 | 
						|
<pre>
 | 
						|
// part of the Irrlicht Engine Shader example.
 | 
						|
// These simple Direct3D9 pixel and vertex shaders will be loaded by the shaders
 | 
						|
// example. Please note that these example shaders don't do anything really useful. 
 | 
						|
// They only demonstrate that shaders can be used in Irrlicht.
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// Global variables
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
float4x4 mWorldViewProj;  // World * View * Projection transformation
 | 
						|
float4x4 mInvWorld;       // Inverted world matrix
 | 
						|
float4x4 mTransWorld;     // Transposed world matrix
 | 
						|
float3 mLightPos;         // Light position
 | 
						|
float4 mLightColor;       // Light color
 | 
						|
 | 
						|
 | 
						|
// Vertex shader output structure
 | 
						|
struct VS_OUTPUT
 | 
						|
{
 | 
						|
	float4 Position   : POSITION;   // vertex position 
 | 
						|
	float4 Diffuse    : COLOR0;     // vertex diffuse color
 | 
						|
	float2 TexCoord   : TEXCOORD0;  // tex coords
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
 | 
						|
                      in float3 vNormal   : NORMAL,
 | 
						|
                      float2 texCoord     : TEXCOORD0 )
 | 
						|
{
 | 
						|
	VS_OUTPUT Output;
 | 
						|
 | 
						|
	// transform position to clip space 
 | 
						|
	Output.Position = mul(vPosition, mWorldViewProj);
 | 
						|
	
 | 
						|
	// transform normal 
 | 
						|
	float3 normal = mul(vNormal, mInvWorld);
 | 
						|
	
 | 
						|
	// renormalize normal 
 | 
						|
	normal = normalize(normal);
 | 
						|
	
 | 
						|
	// position in world coodinates
 | 
						|
	float3 worldpos = mul(mTransWorld, vPosition);
 | 
						|
	
 | 
						|
	// calculate light vector, vtxpos - lightpos
 | 
						|
	float3 lightVector = worldpos - mLightPos;
 | 
						|
	
 | 
						|
	// normalize light vector 
 | 
						|
	lightVector = normalize(lightVector);
 | 
						|
	
 | 
						|
	// calculate light color 
 | 
						|
	float3 tmp = dot(-lightVector, normal);
 | 
						|
	tmp = lit(tmp.x, tmp.y, 1.0);
 | 
						|
	
 | 
						|
	tmp = mLightColor * tmp.y;
 | 
						|
	Output.Diffuse = float4(tmp.x, tmp.y, tmp.z, 0);
 | 
						|
	Output.TexCoord = texCoord;
 | 
						|
	
 | 
						|
	return Output;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Pixel shader output structure
 | 
						|
struct PS_OUTPUT
 | 
						|
{
 | 
						|
    float4 RGBColor : COLOR0;  // Pixel color    
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
sampler2D tex0;
 | 
						|
	
 | 
						|
PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,
 | 
						|
                     float4 Position : POSITION,
 | 
						|
                     float4 Diffuse  : COLOR0 ) 
 | 
						|
{ 
 | 
						|
	PS_OUTPUT Output;
 | 
						|
 | 
						|
	float4 col = tex2D( tex0, TexCoord );  // sample color map
 | 
						|
	
 | 
						|
	// multiply with diffuse and do other senseless operations
 | 
						|
	Output.RGBColor = Diffuse * col;
 | 
						|
	Output.RGBColor *= 4.0;
 | 
						|
 | 
						|
	return Output;
 | 
						|
}</pre></td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <br>
 | 
						|
          <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td><strong>D3D9.VSH</strong></td>
 | 
						|
            </tr>
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>
 | 
						|
; part of the Irrlicht Engine Shader example.
 | 
						|
; This Direct3D9 vertex shader will be loaded by the engine.
 | 
						|
; Please note that these example shaders don't do anything really useful. 
 | 
						|
; They only demonstrate that shaders can be used in Irrlicht.<br>
 | 
						|
vs.1.1
 | 
						|
 | 
						|
dcl_position v0;    ; declare position
 | 
						|
dcl_normal v1;      ; declare normal
 | 
						|
dcl_color v2;       ; declare color
 | 
						|
dcl_texcoord0 v3;   ; declare texture coordinate<br>
 | 
						|
; transpose and transform position to clip space 
 | 
						|
mul r0, v0.x, c4      
 | 
						|
mad r0, v0.y, c5, r0   
 | 
						|
mad r0, v0.z, c6, r0   
 | 
						|
add oPos, c7, r0       
 | 
						|
 | 
						|
; transform normal 
 | 
						|
dp3 r1.x, v1, c0  
 | 
						|
dp3 r1.y, v1, c1  
 | 
						|
dp3 r1.z, v1, c2  
 | 
						|
 | 
						|
; renormalize normal 
 | 
						|
dp3 r1.w, r1, r1  
 | 
						|
rsq r1.w, r1.w    
 | 
						|
mul r1, r1, r1.w  
 | 
						|
 | 
						|
; calculate light vector 
 | 
						|
m4x4 r6, v0, c10      ; vertex into world position
 | 
						|
add r2, c8, -r6       ; vtxpos - lightpos
 | 
						|
 | 
						|
; normalize light vector 
 | 
						|
dp3 r2.w, r2, r2  
 | 
						|
rsq r2.w, r2.w    
 | 
						|
mul r2, r2, r2.w  
 | 
						|
 | 
						|
; calculate light color 
 | 
						|
dp3 r3, r1, r2       ; dp3 with negative light vector 
 | 
						|
lit r5, r3           ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y
 | 
						|
mul oD0, r5.y, c9    ; ouput diffuse color 
 | 
						|
mov oT0, v3          ; store texture coordinates     </pre> </td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <br>
 | 
						|
          <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td><strong>D3D9.PSH</strong></td>
 | 
						|
            </tr>
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>
 | 
						|
; part of the Irrlicht Engine Shader example.
 | 
						|
; This simple Direct3D9 pixel shader will be loaded by the engine.
 | 
						|
; Please note that these example shaders don't do anything really useful. 
 | 
						|
; They only demonstrate that shaders can be used in Irrlicht.<br>
 | 
						|
ps.1.1
 | 
						|
 | 
						|
tex t0          ; sample color map
 | 
						|
add r0, v0, v0  ; mulitply with color
 | 
						|
mul t0, t0, r0  ; mulitply with color
 | 
						|
add r0, t0, t0  ; make it brighter and store result              
 | 
						|
              </pre> </td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <br>
 | 
						|
          <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td><strong>D3D8.VSH</strong></td>
 | 
						|
            </tr>
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>
 | 
						|
; part of the Irrlicht Engine Shader example.
 | 
						|
; This Direct3D9 vertex shader will be loaded by the engine.
 | 
						|
; Please note that these example shaders don't do anything really useful. 
 | 
						|
; They only demonstrate that shaders can be used in Irrlicht.<br>
 | 
						|
vs.1.1
 | 
						|
 | 
						|
; transpose and transform position to clip space 
 | 
						|
mul r0, v0.x, c4      
 | 
						|
mad r0, v0.y, c5, r0   
 | 
						|
mad r0, v0.z, c6, r0   
 | 
						|
add oPos, c7, r0       
 | 
						|
 | 
						|
; transform normal 
 | 
						|
dp3 r1.x, v1, c0  
 | 
						|
dp3 r1.y, v1, c1  
 | 
						|
dp3 r1.z, v1, c2  
 | 
						|
 | 
						|
; renormalize normal 
 | 
						|
dp3 r1.w, r1, r1  
 | 
						|
rsq r1.w, r1.w    
 | 
						|
mul r1, r1, r1.w  
 | 
						|
 | 
						|
; calculate light vector 
 | 
						|
m4x4 r6, v0, c10      ; vertex into world position
 | 
						|
add r2, c8, -r6       ; vtxpos - lightpos
 | 
						|
 | 
						|
; normalize light vector 
 | 
						|
dp3 r2.w, r2, r2  
 | 
						|
rsq r2.w, r2.w    
 | 
						|
mul r2, r2, r2.w  
 | 
						|
 | 
						|
; calculate light color 
 | 
						|
dp3 r3, r1, r2       ; dp3 with negative light vector 
 | 
						|
lit r5, r3           ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y
 | 
						|
mul oD0, r5.y, c9    ; ouput diffuse color 
 | 
						|
mov oT0, v3          ; store texture coordinates             </pre> </td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <br>
 | 
						|
          <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td><strong>D3D8.PSH</strong></td>
 | 
						|
            </tr>
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>
 | 
						|
; part of the Irrlicht Engine Shader example.
 | 
						|
; This simple Direct3D9 pixel shader will be loaded by the engine.
 | 
						|
; Please note that these example shaders don't do anything really useful. 
 | 
						|
; They only demonstrate that shaders can be used in Irrlicht.<br>
 | 
						|
ps.1.1
 | 
						|
 | 
						|
tex t0             ; sample color map
 | 
						|
mul_x2 t0, t0, v0  ; mulitply with color
 | 
						|
add r0, t0, t0     ; make it brighter and store result      </pre> </td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <br>
 | 
						|
          <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td><strong>OPENGL.VSH</strong></td>
 | 
						|
            </tr>
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>
 | 
						|
!!ARBvp1.0
 | 
						|
# part of the Irrlicht Engine Shader example.
 | 
						|
# Please note that these example shaders don't do anything really useful. 
 | 
						|
# They only demonstrate that shaders can be used in Irrlicht.<br>
 | 
						|
#input
 | 
						|
ATTRIB InPos = vertex.position;
 | 
						|
ATTRIB InColor = vertex.color;
 | 
						|
ATTRIB InNormal = vertex.normal;
 | 
						|
ATTRIB InTexCoord = vertex.texcoord;
 | 
						|
 | 
						|
#output
 | 
						|
OUTPUT OutPos = result.position;
 | 
						|
OUTPUT OutColor = result.color;
 | 
						|
OUTPUT OutTexCoord = result.texcoord;
 | 
						|
 | 
						|
PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.
 | 
						|
TEMP Temp;
 | 
						|
TEMP TempColor;
 | 
						|
TEMP TempNormal;
 | 
						|
TEMP TempPos;
 | 
						|
 | 
						|
#transform position to clip space 
 | 
						|
DP4 Temp.x, MVP[0], InPos;
 | 
						|
DP4 Temp.y, MVP[1], InPos;
 | 
						|
DP4 Temp.z, MVP[2], InPos;
 | 
						|
DP4 Temp.w, MVP[3], InPos;
 | 
						|
 | 
						|
#transform normal
 | 
						|
DP3 TempNormal.x, InNormal.x, program.local[0];
 | 
						|
DP3 TempNormal.y, InNormal.y, program.local[1]; 
 | 
						|
DP3 TempNormal.z, InNormal.z, program.local[2];
 | 
						|
 | 
						|
#renormalize normal
 | 
						|
DP3 TempNormal.w, TempNormal, TempNormal;  
 | 
						|
RSQ TempNormal.w, TempNormal.w;    
 | 
						|
MUL TempNormal, TempNormal, TempNormal.w;
 | 
						|
 | 
						|
# calculate light vector 
 | 
						|
DP4 TempPos.x, InPos, program.local[10];   # vertex into world position
 | 
						|
DP4 TempPos.y, InPos, program.local[11];
 | 
						|
DP4 TempPos.z, InPos, program.local[12];
 | 
						|
DP4 TempPos.w, InPos, program.local[13];
 | 
						|
 | 
						|
ADD TempPos, program.local[8], -TempPos;    # vtxpos - lightpos
 | 
						|
 | 
						|
# normalize light vector
 | 
						|
DP3 TempPos.w, TempPos, TempPos;  
 | 
						|
RSQ TempPos.w, TempPos.w;    
 | 
						|
MUL TempPos, TempPos, TempPos.w;
 | 
						|
 | 
						|
# calculate light color
 | 
						|
DP3 TempColor, TempNormal, TempPos;    # dp3 with negative light vector 
 | 
						|
LIT OutColor, TempColor;  # clamp to zero if r3 < 0, r5 has diffuce component in r5.y
 | 
						|
MUL OutColor, TempColor.y, program.local[9]; # ouput diffuse color 
 | 
						|
MOV OutColor.w, 1.0;          # we want alpha to be always 1
 | 
						|
MOV OutTexCoord, InTexCoord; # store texture coordinate
 | 
						|
MOV OutPos, Temp;
 | 
						|
 | 
						|
END</pre> </td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <br>
 | 
						|
          <table width="95%" border="0" cellspacing="4" cellpadding="0" bgcolor="#CCCCCC" align="center">
 | 
						|
            <tr> 
 | 
						|
              <td><strong>OPENGL.PSH</strong></td>
 | 
						|
            </tr>
 | 
						|
            <tr> 
 | 
						|
              <td> <pre>
 | 
						|
!!ARBfp1.0
 | 
						|
# part of the Irrlicht Engine Shader example.
 | 
						|
# Please note that these example shaders don't do anything really useful. 
 | 
						|
# They only demonstrate that shaders can be used in Irrlicht.<br>
 | 
						|
#Input
 | 
						|
ATTRIB inTexCoord = fragment.texcoord;      # texture coordinates
 | 
						|
ATTRIB inColor = fragment.color.primary; # interpolated diffuse color
 | 
						|
 | 
						|
#Output
 | 
						|
OUTPUT outColor = result.color;
 | 
						|
 | 
						|
TEMP texelColor;
 | 
						|
TEMP tmp;
 | 
						|
TXP texelColor, inTexCoord, texture, 2D; 
 | 
						|
 | 
						|
ADD tmp, inColor, inColor; # mulitply with color
 | 
						|
MUL texelColor, texelColor, tmp;  # mulitply with color   
 | 
						|
ADD outColor, texelColor, texelColor;  # make it brighter and store result
 | 
						|
 | 
						|
END          </pre> </td>
 | 
						|
            </tr>
 | 
						|
          </table>
 | 
						|
          <p>  </p>
 | 
						|
        </div>
 | 
						|
      </div></td>
 | 
						|
  </tr>
 | 
						|
</table>
 | 
						|
<p> </p>
 | 
						|
<p> </p>
 | 
						|
      </body>
 | 
						|
</html>
 |