#include "ShaderMaterial.h" CShaderMaterial::CShaderMaterial(IrrlichtDevice* device, const core::stringc& name, io::path vsFile, core::stringc vsEntry, video::E_VERTEX_SHADER_TYPE vsType, io::path psFile, core::stringc psEntry, video::E_PIXEL_SHADER_TYPE psType, video::E_MATERIAL_TYPE baseMaterial) : Device(device), Name(name), PixelShaderFlags(0), VertexShaderFlags(0) { s32 userdata = 0; io::path vsPath; io::path psPath; // log action core::stringc msg = core::stringc("compiling material ") + name; Device->getLogger()->log(msg.c_str(), ELL_INFORMATION); // create destination path for (driver specific) shader files if(Device->getVideoDriver()->getDriverType() == video::EDT_OPENGL) { vsPath = core::stringc("./shaders/glsl/") + vsFile; psPath = core::stringc("./shaders/glsl/") + psFile; userdata = 1; } if(Device->getVideoDriver()->getDriverType() == video::EDT_DIRECT3D9) { vsPath=core::stringc("./shaders/hlsl/") + vsFile; psPath=core::stringc("./shaders/hlsl/") + psFile; userdata = 0; } // create shader material video::IGPUProgrammingServices* gpu = Device->getVideoDriver()->getGPUProgrammingServices(); s32 matID = gpu->addHighLevelShaderMaterialFromFiles( vsPath, vsEntry.c_str(), vsType, psPath, psEntry.c_str(), psType, this, baseMaterial, userdata); // set material type Material.MaterialType = (video::E_MATERIAL_TYPE)matID; // set the default texturenames and texture wrap // these are overridden by the effect.xml configuration for (u32 i=0; i::Iterator psParamIter = PixelShaderConstant.getIterator(); for(; !psParamIter.atEnd(); psParamIter++) { services->setPixelShaderConstant( psParamIter.getNode()->getKey().c_str(), &psParamIter.getNode()->getValue(), 1); } } if(PixelShaderUniform.size()) { core::map::Iterator psParamIter = PixelShaderUniform.getIterator(); for(; !psParamIter.atEnd(); psParamIter++) { services->setPixelShaderConstant( psParamIter.getNode()->getKey().c_str(), psParamIter.getNode()->getValue().ParamPointer, psParamIter.getNode()->getValue().ParamCount); } } // set the constants for the vertexshader if(VertexShaderConstant.size()) { core::map::Iterator vsParamIter = VertexShaderConstant.getIterator(); for(; !vsParamIter.atEnd(); vsParamIter++) { services->setVertexShaderConstant( vsParamIter.getNode()->getKey().c_str(), &vsParamIter.getNode()->getValue(), 1); } } if(VertexShaderUniform.size()) { core::map::Iterator vsParamIter = VertexShaderUniform.getIterator(); for(; !vsParamIter.atEnd(); vsParamIter++) { services->setVertexShaderConstant( vsParamIter.getNode()->getKey().c_str(), vsParamIter.getNode()->getValue().ParamPointer, vsParamIter.getNode()->getValue().ParamCount); } } // set the elapsed time if the shader wants it if (getPixelShaderFlag(ESC_TIME) || getVertexShaderFlag(ESC_TIME)) { // get the elapsed time in ms f32 elapsedTime = Device->getTimer()->getTime()* 0.001f; if(getPixelShaderFlag(ESC_TIME)) services->setPixelShaderConstant("ElapsedTime", &elapsedTime, 1); if(getVertexShaderFlag(ESC_TIME)) services->setVertexShaderConstant("ElapsedTime", &elapsedTime, 1); } // set a random value if the shader wants it if (getPixelShaderFlag(ESC_RANDOM) || getVertexShaderFlag(ESC_RANDOM)) { // create a random value in the intervall [0, 1] f32 random = (f32) rand() / (f32) RAND_MAX; if(getPixelShaderFlag(ESC_RANDOM)) services->setPixelShaderConstant("RandomValue", &random, 1); if(getVertexShaderFlag(ESC_RANDOM)) services->setVertexShaderConstant("RandomValue", &random, 1); } // set the projection matrix if the shader wants it if (getPixelShaderFlag(ESC_PROJECTION) || getVertexShaderFlag(ESC_PROJECTION)) { // get the projection matrix core::matrix4 projMatrix = Device->getVideoDriver()->getTransform(video::ETS_PROJECTION); if(getPixelShaderFlag(ESC_PROJECTION)) services->setPixelShaderConstant("ProjMatrix", projMatrix.pointer(), 16); if(getVertexShaderFlag(ESC_PROJECTION)) services->setVertexShaderConstant("ProjMatrix", projMatrix.pointer(), 16); } // set the view matrix if the shader wants it if (getPixelShaderFlag(ESC_VIEW) || getVertexShaderFlag(ESC_VIEW)) { // get the view matrix core::matrix4 viewMatrix = Device->getVideoDriver()->getTransform(video::ETS_VIEW); if(getPixelShaderFlag(ESC_VIEW)) services->setPixelShaderConstant("ViewMatrix", viewMatrix.pointer(), 16); if(getVertexShaderFlag(ESC_VIEW)) services->setVertexShaderConstant("ViewMatrix", viewMatrix.pointer(), 16); } // set the world matrix if the shader wants it if (getPixelShaderFlag(ESC_WORLD) || getVertexShaderFlag(ESC_WORLD)) { // get the world matrix core::matrix4 worldMatrix = Device->getVideoDriver()->getTransform(video::ETS_WORLD); if(getPixelShaderFlag(ESC_WORLD)) services->setPixelShaderConstant("WorldMatrix", worldMatrix.pointer(), 16); if(getVertexShaderFlag(ESC_WORLD)) services->setVertexShaderConstant("WorldMatrix", worldMatrix.pointer(), 16); } // set the world view matrix if the shader wants it if (getPixelShaderFlag(ESC_WORLDVIEW) || getVertexShaderFlag(ESC_WORLDVIEW)) { // calculate the world view matrix core::matrix4 worldViewMatrix = Device->getVideoDriver()->getTransform(video::ETS_VIEW); worldViewMatrix *= Device->getVideoDriver()->getTransform(video::ETS_WORLD); if(getPixelShaderFlag(ESC_WORLDVIEW)) services->setPixelShaderConstant("WorldViewMatrix", worldViewMatrix.pointer(), 16); if(getVertexShaderFlag(ESC_WORLDVIEW)) services->setVertexShaderConstant("WorldViewMatrix", worldViewMatrix.pointer(), 16); } // set the world view projection matrix if the shader wants it if (getPixelShaderFlag(ESC_WORLDVIEWPROJ) || getVertexShaderFlag(ESC_WORLDVIEWPROJ)) { // calculate the world view projection matrix core::matrix4 worldViewProjMatrix = Device->getVideoDriver()->getTransform(video::ETS_PROJECTION); worldViewProjMatrix *= Device->getVideoDriver()->getTransform(video::ETS_VIEW); worldViewProjMatrix *= Device->getVideoDriver()->getTransform(video::ETS_WORLD); if(getPixelShaderFlag(ESC_WORLDVIEWPROJ)) services->setPixelShaderConstant("WorldViewProjMatrix", worldViewProjMatrix.pointer(), 16); if(getVertexShaderFlag(ESC_WORLDVIEWPROJ)) services->setVertexShaderConstant("WorldViewProjMatrix", worldViewProjMatrix.pointer(), 16); } // set the camera position if the shader wants it scene::ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); if (camera && (getPixelShaderFlag(ESC_CAMERAPOSITION) || getVertexShaderFlag(ESC_CAMERAPOSITION)) ) { // get the camera position f32 cameraPosition[3]; camera->getAbsolutePosition().getAs3Values(cameraPosition); if(getPixelShaderFlag(ESC_CAMERAPOSITION)) services->setPixelShaderConstant("CameraPosition", &cameraPosition[0], 3); if(getVertexShaderFlag(ESC_CAMERAPOSITION)) services->setVertexShaderConstant("CameraPosition", &cameraPosition[0], 3); } // set buffer dimensions if(Material.TextureLayer[0].Texture != NULL) { // set buffer width if the shader wants it if (getPixelShaderFlag(ESC_BUFFERWIDTH) || getVertexShaderFlag(ESC_BUFFERWIDTH)) { // get the texture width f32 width = (f32) Material.TextureLayer[0].Texture->getSize().Width; if(getPixelShaderFlag(ESC_BUFFERWIDTH)) services->setPixelShaderConstant("BufferWidth", &width, 1); if(getVertexShaderFlag(ESC_BUFFERWIDTH)) services->setVertexShaderConstant("BufferWidth", &width, 1); } // set buffer height if the shader wants it if (getPixelShaderFlag(ESC_BUFFERHEIGHT) || getVertexShaderFlag(ESC_BUFFERHEIGHT)) { // get the texture height f32 height = (f32) Material.TextureLayer[0].Texture->getSize().Height; if(getPixelShaderFlag(ESC_BUFFERHEIGHT)) services->setPixelShaderConstant("BufferHeight", &height, 1); if(getVertexShaderFlag(ESC_BUFFERHEIGHT)) services->setVertexShaderConstant("BufferHeight", &height, 1); } } // set texture names for OpenGL Shaders // (this is not necessary for DirectX) if(userdata == 1) { for (u32 i=0; isetPixelShaderConstant(TextureName[i].c_str(), (f32*) &i, 1); } } }