terrainTest/ShaderMaterial.cpp

239 lines
8.9 KiB
C++

#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<video::MATERIAL_MAX_TEXTURES; ++i)
{
TextureName[i] = core::stringc("texture") + core::stringc(i);
Material.TextureLayer[i].TextureWrapU = video::ETC_REPEAT;
Material.TextureLayer[i].TextureWrapV = video::ETC_REPEAT;
}
}
void CShaderMaterial::OnSetConstants(video::IMaterialRendererServices* services, s32 userdata)
{
// set the constants for the pixelshader
if(PixelShaderConstant.size())
{
core::map<const core::stringc, f32>::Iterator psParamIter = PixelShaderConstant.getIterator();
for(; !psParamIter.atEnd(); psParamIter++)
{
services->setPixelShaderConstant(
psParamIter.getNode()->getKey().c_str(),
&psParamIter.getNode()->getValue(),
1);
}
}
if(PixelShaderUniform.size())
{
core::map<const core::stringc, SUniformDescriptor>::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<const core::stringc, f32>::Iterator vsParamIter = VertexShaderConstant.getIterator();
for(; !vsParamIter.atEnd(); vsParamIter++)
{
services->setVertexShaderConstant(
vsParamIter.getNode()->getKey().c_str(),
&vsParamIter.getNode()->getValue(),
1);
}
}
if(VertexShaderUniform.size())
{
core::map<const core::stringc, SUniformDescriptor>::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; i<video::MATERIAL_MAX_TEXTURES; ++i)
{
if(Material.TextureLayer[i].Texture != NULL)
services->setPixelShaderConstant(TextureName[i].c_str(), (f32*) &i, 1);
}
}
}