mirror of
https://github.com/minetest/irrlicht.git
synced 2024-12-27 11:10:31 +01:00
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>
|