rendered paste bodyIndex: media/d3d9Shader.xml
===================================================================
--- media/d3d9Shader.xml (revision 0)
+++ media/d3d9Shader.xml (revision 0)
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<irrlichtShader>
+ <shaderCode Type="HLSL" vsFile="../../media/d3d9.hlsl" vsTarget="vs_1_1" psTarget="ps_1_1" vsEntryPoint="vertexMain" psEntryPoint="pixelMain" fixedFunctionFallBack="solid" /> <!-- psFile is ignored when HLSL, if gsFile not present/empty then geometry shader is not created -->
+ <shaderCodeFallBack Type="DXASM" vsFile="../../media/d3d9.vsh" psFile="../../media/d3d9.psh" /> <!-- FallBack shaders for older HW if possible, if node not present then not considered -->
+ <passParameters> <!-- We specify which built in params we want passed. If any of the parameter node not present, it is not passed... -->
+ <!-- Depending on using high level shaders or not the register or name is ignored accordingly, glsl shaders can pass to any shader type regardless of pixel, vertex or geom -->
+ <worldTransInv shader="vertex" register="0" name="mInvWorld">
+ <worldViewProjTrans shader="vertex" register="4" name="mWorldViewProj">
+ <worldTransposed shader="vertex" register="10" name="mTransWorld">
+ </passParameters>
+</irrlichtShader>
Index: media/glShader.xml
===================================================================
--- media/glShader.xml (revision 0)
+++ media/glShader.xml (revision 0)
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<irrlichtShader>
+ <shaderCode Type="GLSL" vsFile="../../media/opengl.vert" psFile="../../media/opengl.frag" gsFile="" vsTarget="vs_1_1" psTarget="ps_1_1" gsTarget="" /> <!-- Second File is ignored when HLSL, if gsFile not present/empty then geometry shader is not created -->
+ <shaderCodeFallBack Type="ARB" vsFile="../../media/opengl.vsh" psFile="../../media/opengl.psh" fixedFunctionFallBack="solid" /> <!-- FallBack shaders for older HW if possible, if node not present then not considered -->
+ <passParameters> <!-- We specify which built in params we want passed. If any of the parameter node not present, it is not passed... -->
+ <!-- Depending on using high level shaders or not the register or name is ignored accordingly, glsl shaders can pass to any shader type regardless of pixel, vertex or geom -->
+ <worldTransInv shader="vertex" register="0" name="mInvWorld">
+ <worldViewProjTrans shader="vertex" register="4" name="mWorldViewProj">
+ <worldTransposed shader="vertex" register="10" name="mTransWorld">
+ </passParameters>
+</irrlichtShader>
Index: media/d3d8Shader.xml
===================================================================
--- media/d3d8Shader.xml (revision 0)
+++ media/d3d8Shader.xml (revision 0)
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<irrlichtShader>
+ <shaderCodeFallBack Type="DXASM" vsFile="../../media/d3d8.vsh" psFile="../../media/d3d8.psh" fixedFunctionFallBack="solid" /> <!-- d3d8 only supports assembly shaders, so we only specify these -->
+ <passParameters> <!-- We specify which built in params we want passed. If any of the parameter node not present, it is not passed... -->
+ <!-- Depending on using high level shaders or not the register or name is ignored accordingly, glsl shaders can pass to any shader type regardless of pixel, vertex or geom -->
+ <worldTransInv shader="vertex" register="0" name="mInvWorld">
+ <worldViewProjTrans shader="vertex" register="4" name="mWorldViewProj">
+ <worldTransposed shader="vertex" register="10" name="mTransWorld">
+ </passParameters>
+</irrlichtShader>
Index: source/Irrlicht/CNullDriver.h
===================================================================
--- source/Irrlicht/CNullDriver.h (revision 3488)
+++ source/Irrlicht/CNullDriver.h (working copy)
@@ -21,6 +21,7 @@
#include "SVertexIndex.h"
#include "SLight.h"
#include "SExposedVideoData.h"
+#include "SUniqueXmlShader.h"
namespace irr
{
@@ -569,6 +570,34 @@
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
s32 userData=0);
+ //! Reads all required shaders from an xml file which references shader files.
+ virtual s32 getXMLMaterialType(io::IXMLReaderUTF8* xmlShaderFile,
+ const io::path& xmlShaderFileName,
+ bool& ForceHighLevelShaders,
+ s32 baseMaterial,
+ IShaderConstantSetCallBack* callback,
+ s32 userData);
+
+ //! Reads all required shaders from an xml file which references shader files.
+ virtual s32 getXMLMaterialType(const io::path& xmlShaderFileName,
+ bool& ForceHighLevelShaders,
+ s32 baseMaterial = -1,
+ IShaderConstantSetCallBack* callback = 0,
+ s32 userData = 0);
+
+ //! clears the cache of xmlShaders, doesnt delete the shaders and callbacks though
+ virtual void clearXMLShaderCache();
+
+ //! Returns how many XML shaders there are
+ //! \return xml shader count
+ virtual u32 getXMLShaderCount() const;
+
+ //! Returns an XML shader material type.
+ //! \param idx: Zero based index of the light. Note: first indices correspond
+ //! to EMT enums
+ //! \return Material Type.
+ virtual s32 getXMLShaderByIndex(u32 idx) const;
+
//! Returns a pointer to the mesh manipulator.
virtual scene::IMeshManipulator* getMeshManipulator();
@@ -596,6 +625,10 @@
//! looks if the image is already loaded
virtual video::ITexture* findTexture(const io::path& filename);
+ //! looks if the image is already loaded
+ virtual s32 findXMLShader(const io::path& filename, s32 baseMaterial, bool highLevel,
+ video::IShaderConstantSetCallBack* callback = 0, bool uniqueCallBack = false);
+
//! Set/unset a clipping plane.
//! There are at least 6 clipping planes available for the user to set at will.
//! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
@@ -793,6 +826,7 @@
core::array<video::IImageWriter*> SurfaceWriter;
core::array<SLight> Lights;
core::array<SMaterialRenderer> MaterialRenderers;
+ core::array<SUniqueXmlShader> xmlShaderCache;
//core::array<SHWBufferLink*> HWBufferLinks;
core::map< const scene::IMeshBuffer* , SHWBufferLink* > HWBufferMap;
Index: source/Irrlicht/Irrlicht-gcc.cbp
===================================================================
--- source/Irrlicht/Irrlicht-gcc.cbp (revision 3488)
+++ source/Irrlicht/Irrlicht-gcc.cbp (working copy)
@@ -430,6 +430,7 @@
<Unit filename="../../include/EAttributes.h" />
<Unit filename="../../include/ECullingTypes.h" />
<Unit filename="../../include/EDebugSceneTypes.h" />
+ <Unit filename="../../include/EDefaultShaderConstants.h" />
<Unit filename="../../include/EDeviceTypes.h" />
<Unit filename="../../include/EDriverFeatures.h" />
<Unit filename="../../include/EDriverTypes.h" />
@@ -456,6 +457,7 @@
<Unit filename="../../include/IBoneSceneNode.h" />
<Unit filename="../../include/ICameraSceneNode.h" />
<Unit filename="../../include/ICursorControl.h" />
+ <Unit filename="../../include/IDefaultShaderCallBack.h" />
<Unit filename="../../include/IDummyTransformationSceneNode.h" />
<Unit filename="../../include/IDynamicMeshBuffer.h" />
<Unit filename="../../include/IEventReceiver.h" />
@@ -570,6 +572,7 @@
<Unit filename="../../include/SParticle.h" />
<Unit filename="../../include/SSharedMeshBuffer.h" />
<Unit filename="../../include/SSkinMeshBuffer.h" />
+ <Unit filename="../../include/SUniqueXmlShader.h" />
<Unit filename="../../include/SVertexIndex.h" />
<Unit filename="../../include/SVertexManipulator.h" />
<Unit filename="../../include/SViewFrustum.h" />
@@ -667,6 +670,7 @@
<Unit filename="CDefaultSceneNodeAnimatorFactory.h" />
<Unit filename="CDefaultSceneNodeFactory.cpp" />
<Unit filename="CDefaultSceneNodeFactory.h" />
+ <Unit filename="CDefaultShaderCallBack.cpp" />
<Unit filename="CDepthBuffer.cpp" />
<Unit filename="CDepthBuffer.h" />
<Unit filename="CDummyTransformationSceneNode.cpp" />
Index: source/Irrlicht/CNullDriver.cpp
===================================================================
--- source/Irrlicht/CNullDriver.cpp (revision 3488)
+++ source/Irrlicht/CNullDriver.cpp (working copy)
@@ -14,6 +14,8 @@
#include "IAnimatedMeshSceneNode.h"
#include "CMeshManipulator.h"
#include "CColorConverter.h"
+#include "EDefaultShaderConstants.h"
+#include "IDefaultShaderCallBack.h"
namespace irr
@@ -197,6 +199,8 @@
InitMaterial2D.TextureLayer[i].TextureWrapV=video::ETC_REPEAT;
}
OverrideMaterial2D=InitMaterial2D;
+
+ clearXMLShaderCache();
}
@@ -2269,7 +2273,387 @@
return result;
}
+//! clears the cache of xmlShaders, doesnt delete the shaders and callbacks though
+void CNullDriver::clearXMLShaderCache()
+{
+ xmlShaderCache.set_used(0);
+ SUniqueXmlShader temp;
+ temp.highLevel = false;
+ temp.cb = 0;
+ for (u32 i=0; i<EMT_COUNT; i++)
+ {
+ temp.filename = sBuiltInMaterialTypeNames[i];
+ temp.baseMaterial = (E_MATERIAL_TYPE)i;
+ xmlShaderCache.push_back(temp);
+ }
+}
+//! Returns how many XML shaders there are
+//! \return xml shader count
+u32 CNullDriver::getXMLShaderCount() const
+{
+ return xmlShaderCache.size();
+}
+
+//! Returns an XML shader material type.
+//! \param idx: Zero based index of the light. Note: first indices correspond
+//! to EMT enums
+//! \return Material Type.
+s32 CNullDriver::getXMLShaderByIndex(u32 idx) const
+{
+ if ( idx < EMT_COUNT )
+ return idx;
+ else if ( idx < xmlShaderCache.size() )
+ return xmlShaderCache[idx].MaterialType;
+ else
+ return -1;
+}
+
+//! looks if the image is already loaded
+s32 CNullDriver::findXMLShader(const io::path& filename, s32 baseMaterial, bool highLevel,
+ IShaderConstantSetCallBack* callback, bool uniqueCallBack)
+{
+ for (s32 i=0; i<EMT_COUNT; i++)
+ {
+ if (filename==sBuiltInMaterialTypeNames[i])
+ {
+ return i;
+ }
+ }
+
+ io::path tempPath = FileSystem->getAbsolutePath(filename);
+ if (baseMaterial!=-1)
+ {
+ if (uniqueCallBack)
+ {
+ for (u32 i=EMT_COUNT; i<xmlShaderCache.size(); i++)
+ {
+ if (xmlShaderCache[i].filename==tempPath&&xmlShaderCache[i].baseMaterial==baseMaterial&&xmlShaderCache[i].highLevel==highLevel&&xmlShaderCache[i].cb==callback)
+ {
+ return xmlShaderCache[i].MaterialType;
+ }
+ }
+ }
+ else
+ {
+ for (u32 i=EMT_COUNT; i<xmlShaderCache.size(); i++)
+ {
+ if (xmlShaderCache[i].filename==tempPath&&xmlShaderCache[i].baseMaterial==baseMaterial&&xmlShaderCache[i].highLevel==highLevel)
+ {
+ return xmlShaderCache[i].MaterialType;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (uniqueCallBack)
+ {
+ for (u32 i=EMT_COUNT; i<xmlShaderCache.size(); i++)
+ {
+ if (xmlShaderCache[i].filename==tempPath&&xmlShaderCache[i].highLevel==highLevel&&xmlShaderCache[i].cb==callback)
+ {
+ return xmlShaderCache[i].MaterialType;
+ }
+ }
+ }
+ else
+ {
+ for (u32 i=EMT_COUNT; i<xmlShaderCache.size(); i++)
+ {
+ if (xmlShaderCache[i].filename==tempPath&&xmlShaderCache[i].highLevel==highLevel)
+ {
+ return xmlShaderCache[i].MaterialType;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+//! Reads all required shaders from an xml file which references shader files.
+s32 CNullDriver::getXMLMaterialType(const io::path& xmlShaderFileName,
+ bool& ForceHighLevelShaders,
+ s32 baseMaterial,
+ IShaderConstantSetCallBack* callback,
+ s32 userData)
+{
+ s32 result = findXMLShader(xmlShaderFileName,baseMaterial,ForceHighLevelShaders,callback,true);
+ if (result!=-1)
+ {
+ return result;
+ }
+
+ io::IXMLReaderUTF8* xmlShaderFile = 0;
+
+ if (xmlShaderFileName.size() )
+ {
+ xmlShaderFile = FileSystem->createXMLReaderUTF8(xmlShaderFileName);
+ if (!xmlShaderFile)
+ {
+ os::Printer::log("Could not open shader xml file",
+ xmlShaderFileName, ELL_WARNING);
+ }
+ }
+
+ result = getXMLMaterialType(
+ xmlShaderFile, xmlShaderFileName, ForceHighLevelShaders,
+ baseMaterial, callback, userData);
+
+ if (xmlShaderFile)
+ xmlShaderFile->drop();
+
+ return result;
+}
+
+void readXMLUntilElement(io::IXMLReaderUTF8* xml) {
+ bool notEnd;
+ do
+ {
+ notEnd = xml->read();
+ }
+ while (xml->getNodeType()!=io::EXN_ELEMENT&¬End);
+}
+
+//! Reads all required shaders from an xml file which references shader files.
+s32 CNullDriver::getXMLMaterialType(io::IXMLReaderUTF8* xmlShaderFile,
+ const io::path& xmlShaderFileName,
+ bool& ForceHighLevelShaders,
+ s32 baseMaterial,
+ IShaderConstantSetCallBack* callback,
+ s32 userData)
+{
+ if (!queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
+ !queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))
+ {
+ os::Printer::log("WARNING: Vertex shaders disabled "\
+ "because of missing driver/hardware support.", ELL_WARNING);
+ return -1;
+ }
+ if (!queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
+ !queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1))
+ {
+ os::Printer::log("WARNING: Pixel shaders disabled "\
+ "because of missing driver/hardware support.", ELL_WARNING);
+ return -1;
+ }
+
+ if (!xmlShaderFile)
+ {
+ return -1;
+ }
+
+ readXMLUntilElement(xmlShaderFile);
+ if (core::stringc(xmlShaderFile->getNodeName())!="irrlichtShader")
+ {
+ return -1;
+ }
+
+ core::stringc temp;
+ core::stringc vsFile = "";
+ core::stringc psFile = "";
+ core::stringc gsFile = "";
+ core::stringc vsFileLow = "";
+ core::stringc psFileLow = "";
+ E_VERTEX_SHADER_TYPE vst = EVST_VS_1_1;
+ E_PIXEL_SHADER_TYPE pst = EPST_PS_1_1;
+ E_GEOMETRY_SHADER_TYPE gst = EGST_GS_4_0;
+ core::stringc vsEntry = "";
+ core::stringc psEntry = "";
+ s32 fixedFnFallBack = -1;
+ E_MATERIAL_TYPE baseMaterialXmlH;
+ E_MATERIAL_TYPE baseMaterialXmlL;
+
+ readXMLUntilElement(xmlShaderFile);
+ // No matter if <shaderCode> or fallback there are at least 3 attributes
+ if (xmlShaderFile->getAttributeCount()<4)
+ {
+ return -1;
+ }
+ bool failAtHighLevel = false;
+ if (core::stringc(xmlShaderFile->getNodeName())=="shaderCode"&&ForceHighLevelShaders)
+ {
+ if (!((core::stringc(xmlShaderFile->getAttributeValueSafe("Type"))=="GLSL"&&getDriverType()==EDT_OPENGL)||
+ (core::stringc(xmlShaderFile->getAttributeValueSafe("Type"))=="HLSL"&&getDriverType()==EDT_DIRECT3D9)))
+ {
+ os::Printer::log("The driver is not appropriate for shader type ",
+ core::stringc(xmlShaderFile->getAttributeValueSafe("Type")), ELL_WARNING);
+ return -1;
+ }
+ vsFile = xmlShaderFile->getAttributeValueSafe("vsFile");
+ psFile = xmlShaderFile->getAttributeValueSafe("psFile");
+ gsFile = xmlShaderFile->getAttributeValueSafe("gsFile");
+ vsEntry = xmlShaderFile->getAttributeValueSafe("vsEntryPoint");
+ psEntry = xmlShaderFile->getAttributeValueSafe("psEntryPoint");
+ temp = xmlShaderFile->getAttributeValueSafe("vsTarget");
+ for (u32 i=0; i<EVST_COUNT; i++)
+ {
+ if (temp==VERTEX_SHADER_TYPE_NAMES[i])
+ vst = (E_VERTEX_SHADER_TYPE)i;
+ }
+ temp = xmlShaderFile->getAttributeValueSafe("psTarget");
+ for (u32 i=0; i<EPST_COUNT; i++)
+ {
+ if (temp==PIXEL_SHADER_TYPE_NAMES[i])
+ pst = (E_PIXEL_SHADER_TYPE)i;
+ }
+ temp = xmlShaderFile->getAttributeValueSafe("gsTarget");
+ for (u32 i=0; i<EGST_COUNT; i++)
+ {
+ if (temp==GEOMETRY_SHADER_TYPE_NAMES[i])
+ gst = (E_GEOMETRY_SHADER_TYPE)i;
+ }
+ temp = xmlShaderFile->getAttributeValueSafe("fixedFnFallBack");
+ for (u32 i=0; i<EMT_COUNT; i++)
+ {
+ if (temp==sBuiltInMaterialTypeNames[i])
+ fixedFnFallBack=i;
+ }
+ temp = xmlShaderFile->getAttributeValueSafe("baseMaterial");
+ for (u32 i=0; i<EMT_COUNT; i++)
+ {
+ if (temp==sBuiltInMaterialTypeNames[i])
+ baseMaterialXmlH = (E_MATERIAL_TYPE)i;
+ }
+ }
+ else if (core::stringc(xmlShaderFile->getNodeName())=="shaderCodeFallBack")
+ {
+ if (!((core::stringc(xmlShaderFile->getAttributeValueSafe("Type"))=="ARB"&&getDriverType()==EDT_OPENGL)||
+ (core::stringc(xmlShaderFile->getAttributeValueSafe("Type"))=="DXASM"&&(getDriverType()==EDT_DIRECT3D9||getDriverType()==EDT_DIRECT3D8))))
+ {
+ os::Printer::log("The driver is not appropriate for shader type ",
+ core::stringc(xmlShaderFile->getAttributeValueSafe("Type")), ELL_WARNING);
+ return -1;
+ }
+ vsFileLow = xmlShaderFile->getAttributeValueSafe("vsFile");
+ psFileLow = xmlShaderFile->getAttributeValueSafe("psFile");
+ ForceHighLevelShaders = false; //! make sure
+ temp = xmlShaderFile->getAttributeValueSafe("fixedFnFallBack");
+ for (u32 i=0; i<EMT_COUNT; i++)
+ {
+ if (temp==sBuiltInMaterialTypeNames[i])
+ fixedFnFallBack=i;
+ }
+ temp = xmlShaderFile->getAttributeValueSafe("baseMaterial");
+ for (u32 i=0; i<EMT_COUNT; i++)
+ {
+ if (temp==sBuiltInMaterialTypeNames[i])
+ baseMaterialXmlL = (E_MATERIAL_TYPE)i;
+ }
+ }
+ else
+ {
+ failAtHighLevel = true;
+ }
+
+ if (failAtHighLevel) {
+ readXMLUntilElement(xmlShaderFile);
+ if (core::stringc(xmlShaderFile->getNodeName())=="shaderCodeFallBack")
+ {
+ if (!((core::stringc(xmlShaderFile->getAttributeValueSafe("Type"))=="ARB"&&getDriverType()==EDT_OPENGL)||
+ (core::stringc(xmlShaderFile->getAttributeValueSafe("Type"))=="DXASM"&&(getDriverType()==EDT_DIRECT3D9||getDriverType()==EDT_DIRECT3D8))))
+ {
+ os::Printer::log("The driver is not appropriate for shader type ",
+ core::stringc(xmlShaderFile->getAttributeValueSafe("Type")), ELL_WARNING);
+ return -1;
+ }
+ vsFileLow = xmlShaderFile->getAttributeValueSafe("vsFile");
+ psFileLow = xmlShaderFile->getAttributeValueSafe("psFile");
+ temp = xmlShaderFile->getAttributeValueSafe("fixedFnFallBack");
+ for (u32 i=0; i<EMT_COUNT; i++)
+ {
+ if (temp==sBuiltInMaterialTypeNames[i])
+ fixedFnFallBack=i;
+ }
+ temp = xmlShaderFile->getAttributeValueSafe("baseMaterial");
+ for (u32 i=0; i<EMT_COUNT; i++)
+ {
+ if (temp==sBuiltInMaterialTypeNames[i])
+ baseMaterialXmlL = (E_MATERIAL_TYPE)i;
+ }
+ }
+ else
+ {
+ os::Printer::log("<shaderCode> node blocks are missing in the shader xml.", ELL_WARNING);
+ return -1;
+ }
+ ForceHighLevelShaders = false;
+ }
+
+ readXMLUntilElement(xmlShaderFile);
+ if (core::stringc(xmlShaderFile->getNodeName())!="passParameters") {
+ readXMLUntilElement(xmlShaderFile);
+ if (core::stringc(xmlShaderFile->getNodeName())!="passParameters")
+ return -1;
+ }
+
+ u32 edscFlags = 0;
+ core::array<SDefaultShaderConstantRegisters> registers;
+ SDefaultShaderConstantRegisters tempReg;
+ for (u32 i=0; i<EDSC_COUNT; i++)
+ registers.push_back(tempReg);
+ while (xmlShaderFile->read()) {
+ if (xmlShaderFile->getNodeType()==io::EXN_ELEMENT)
+ {
+ for (u32 i=0; i<EDSC_COUNT; i++)
+ {
+ if (core::stringc(xmlShaderFile->getNodeName())==DEFAULT_SHADER_CONSTANTS_NAMES[i])
+ {
+ edscFlags |= (1 << i);
+ registers[i].Name = xmlShaderFile->getAttributeValueSafe("name");
+ registers[i].Register = xmlShaderFile->getAttributeValueAsInt("register");
+ if (core::stringc(xmlShaderFile->getAttributeValueSafe("shader"))=="vertex")
+ registers[i].pixelOrVertex = false;
+ else
+ registers[i].pixelOrVertex = true;
+ break;
+ }
+ }
+ }
+ }
+ IDefaultShaderCallBack* cb = new IDefaultShaderCallBack(edscFlags,registers,callback);
+ s32 newMaterialType = 0;
+ if (ForceHighLevelShaders)
+ {
+ newMaterialType = addHighLevelShaderMaterialFromFiles(vsFile,vsEntry.c_str(),vst,psFile,psEntry.c_str(),pst,
+ gsFile,"geomMain",gst,scene::EPT_TRIANGLES,scene::EPT_TRIANGLE_STRIP,0,
+ cb,baseMaterial!=-1 ? ((E_MATERIAL_TYPE)baseMaterial):baseMaterialXmlH,userData);
+ if (newMaterialType==-1)
+ ForceHighLevelShaders=false;
+ else
+ {
+ cb->setHighorLowLevel(ForceHighLevelShaders);
+ SUniqueXmlShader tempSUXS;
+ tempSUXS.filename = FileSystem->getAbsolutePath(xmlShaderFileName);
+ tempSUXS.baseMaterial = baseMaterial!=-1 ? ((E_MATERIAL_TYPE)baseMaterial):baseMaterialXmlH;
+ tempSUXS.cb = callback;
+ tempSUXS.highLevel = true;
+ tempSUXS.MaterialType = newMaterialType;
+ xmlShaderCache.push_back(tempSUXS);
+ cb->drop();
+ return newMaterialType;
+ }
+ }
+ if (!ForceHighLevelShaders) //! DO NOT change into an "else"
+ {
+ newMaterialType = addShaderMaterialFromFiles(vsFileLow,psFileLow,cb,baseMaterial!=-1 ? ((E_MATERIAL_TYPE)baseMaterial):baseMaterialXmlL,userData);
+ cb->setHighorLowLevel(ForceHighLevelShaders);
+ if (newMaterialType!=-1) {
+ SUniqueXmlShader tempSUXS;
+ tempSUXS.filename = FileSystem->getAbsolutePath(xmlShaderFileName);
+ tempSUXS.baseMaterial = baseMaterial!=-1 ? ((E_MATERIAL_TYPE)baseMaterial):baseMaterialXmlL;
+ tempSUXS.cb = callback;
+ tempSUXS.highLevel = false;
+ tempSUXS.MaterialType = newMaterialType;
+ xmlShaderCache.push_back(tempSUXS);
+ cb->drop();
+ return newMaterialType;
+ }
+ }
+
+ return fixedFnFallBack;
+}
+
//! Creates a render target texture.
ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d<u32>& size,
const io::path&name, const ECOLOR_FORMAT format)
Index: source/Irrlicht/CDefaultShaderCallBack.cpp
===================================================================
--- source/Irrlicht/CDefaultShaderCallBack.cpp (revision 0)
+++ source/Irrlicht/CDefaultShaderCallBack.cpp (revision 0)
@@ -0,0 +1,273 @@
+#include "SMaterial.h"
+#include "IDefaultShaderCallBack.h"
+#include "IMaterialRendererServices.h"
+#include "IVideoDriver.h"
+#include "matrix4.h"
+#include "ICameraSceneNode.h"
+
+namespace irr
+{
+namespace video
+{
+
+
+IDefaultShaderCallBack::IDefaultShaderCallBack(u32 flags, core::array<SDefaultShaderConstantRegisters> registers, IShaderConstantSetCallBack* callback)
+ : edscFlags(flags), Registers(registers), callBack(callback), highOrLowLevel(true)
+{
+ if (callBack)
+ callBack->grab();
+}
+
+IDefaultShaderCallBack::~IDefaultShaderCallBack()
+{
+ if (callBack)
+ callBack->drop();
+}
+
+void IDefaultShaderCallBack::OnSetMaterial(const SMaterial& material)
+{
+ if (callBack)
+ callBack->OnSetMaterial(material);
+}
+
+void setConstant(bool highOrLowLevel,video::IMaterialRendererServices* services,float* pointer,u32 size,SDefaultShaderConstantRegisters Register) {
+ if (highOrLowLevel)
+ {
+ if (Register.pixelOrVertex)
+ services->setPixelShaderConstant(Register.Name.c_str(),pointer,size);
+ else
+ services->setVertexShaderConstant(Register.Name.c_str(),pointer,size);
+ }
+ else
+ {
+ if (Register.pixelOrVertex)
+ services->setPixelShaderConstant(pointer,Register.Register,size/4);
+ else
+ services->setVertexShaderConstant(pointer,Register.Register,size/4);
+ }
+}
+
+void IDefaultShaderCallBack::OnSetConstants(video::IMaterialRendererServices* services,
+ s32 userData)
+{
+ video::IVideoDriver* driver = services->getVideoDriver();
+
+ for (u32 i=0; i<EDSC_COUNT; i++)
+ {
+ if (edscFlags & (1 << EDSC_WORLD_TFORM)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_WORLD);
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_TFORM)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_VIEW);
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_PROJ_TFORM)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_PROJ_TFORM)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_WORLD_VIEW_PROJ_TFORM)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ mat *= driver->getTransform(video::ETS_WORLD);
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_WORLD_TFORM_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_WORLD);
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_TFORM_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_VIEW);
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_PROJ_TFORM_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_PROJ_TFORM_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_WORLD_VIEW_PROJ_TFORM_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ mat *= driver->getTransform(video::ETS_WORLD);
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_WORLD_TRANSPOSED)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_WORLD);
+ mat = mat.getTransposed();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_TRANSPOSED)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_VIEW);
+ mat = mat.getTransposed();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_PROJ_TRANSPOSED)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat = mat.getTransposed();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_PROJ_TRANSPOSED)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ mat = mat.getTransposed();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_WORLD_VIEW_PROJ_TRANSPOSED)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ mat *= driver->getTransform(video::ETS_WORLD);
+ mat = mat.getTransposed();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_WORLD_TRANSPOSED_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_WORLD);
+ mat = mat.getTransposed();
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_TRANSPOSED_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_VIEW);
+ mat = mat.getTransposed();
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_PROJ_TRANSPOSED_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat = mat.getTransposed();
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_VIEW_PROJ_TRANSPOSED_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ mat = mat.getTransposed();
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ else if (edscFlags & (1 << EDSC_WORLD_VIEW_PROJ_TRANSPOSED_INV)) {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ mat *= driver->getTransform(video::ETS_VIEW);
+ mat *= driver->getTransform(video::ETS_WORLD);
+ mat = mat.getTransposed();
+ mat.makeInverse();
+ setConstant(highOrLowLevel,services,mat.pointer(),16,Registers[i]);
+ }
+ //! HighLevel only
+ else if (edscFlags & (1 << EDSC_FRAME_BUFFER_SIZE))
+ {
+ core::dimension2df fbSize = core::dimension2df(driver->getCurrentRenderTargetSize().Width,driver->getCurrentRenderTargetSize().Height);
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),&fbSize.Width,2);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),&fbSize.Width,2);
+ }
+ else if (edscFlags & (1 << EDSC_CAMERA_FAR_DISTANCE))
+ {
+ core::matrix4 mat = driver->getTransform(video::ETS_PROJECTION);
+ f32 farDist;
+ if (mat.isOrthogonal())
+ {
+ if (mat[10]>0.f) // Left Handed
+ farDist = 1.f/mat[10]-mat[14]/mat[10];
+ else // Right Handed
+ farDist = mat[14]/mat[10]-1.f/mat[10];
+ }
+ else
+ {
+ if (mat[10]>0.f) // Left Handed
+ farDist = -mat[14]/(mat[10]-1.f);
+ else // Right Handed
+ farDist = mat[14]/(mat[10]+1.f);
+ }
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),&farDist,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),&farDist,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX0))
+ {
+ s32 texIdx = 0;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX1))
+ {
+ s32 texIdx = 1;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX2))
+ {
+ s32 texIdx = 2;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX3))
+ {
+ s32 texIdx = 3;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX4))
+ {
+ s32 texIdx = 4;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX5))
+ {
+ s32 texIdx = 5;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX6))
+ {
+ s32 texIdx = 6;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ else if (edscFlags & (1 << EDSC_TEX7))
+ {
+ s32 texIdx = 7;
+ if (Registers[i].pixelOrVertex)
+ services->setPixelShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ else
+ services->setVertexShaderConstant(Registers[i].Name.c_str(),(f32*)&texIdx,1);
+ }
+ }
+
+ if (callBack)
+ callBack->OnSetConstants(services,userData);
+}
+
+
+} // end namespace video
+} // end namespace irr
Index: include/SUniqueXmlShader.h
===================================================================
--- include/SUniqueXmlShader.h (revision 0)
+++ include/SUniqueXmlShader.h (revision 0)
@@ -0,0 +1,24 @@
+#ifndef __S_UNIQUE_XML_SHADER_H_INCLUDED__
+#define __S_UNIQUE_XML_SHADER_H_INCLUDED__
+
+#include "irrTypes.h"
+//#include "irrString.h"
+
+namespace irr
+{
+namespace video
+{
+
+struct SUniqueXmlShader
+{
+ io::path filename;
+ video::E_MATERIAL_TYPE baseMaterial;
+ video::IShaderConstantSetCallBack* cb;
+ bool highLevel;
+ s32 MaterialType;
+};
+
+} // end namespace video
+} // end namespace irr
+
+#endif // __S_UNIQUE_XML_SHADER_H_INCLUDED__
Index: include/IGPUProgrammingServices.h
===================================================================
--- include/IGPUProgrammingServices.h (revision 3488)
+++ include/IGPUProgrammingServices.h (working copy)
@@ -9,6 +9,7 @@
#include "EMaterialTypes.h"
#include "EPrimitiveTypes.h"
#include "path.h"
+#include "IFileSystem.h"
namespace irr
{
@@ -357,6 +358,47 @@
IShaderConstantSetCallBack* callback = 0,
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
s32 userData = 0) = 0;
+
+ //! Reads all required shaders from an xml file which references shader files.
+ /** \param xmlShaderFileName: XML file name containing the parameters to
+ set up shader programs. Set to 0 if no shader shall be created.
+ \param baseMaterial: baseMaterial
+ \param IShaderConstantSetCallBack: A callback will be created by irrlicht
+ anyway, but the user specified callback will be called after that. Set to 0
+ if you do not wish for an extra custom callback.
+ \param ForceHighLevelShaders: if true AND the xml file specifies a high level
+ shader AND the hardware allows, a high level shader will be created. If false
+ AND the xml file defines a low level shader, a low level shader will be created.
+ The reference is used to return whether a high level shader has been created
+ \param userData: a user data int. This int can be set to any value and
+ will be set as parameter in the callback method when calling
+ OnSetConstants(). In this way it is easily possible to use the same
+ callback method for multiple materials and distinguish between them
+ during the call.
+ \return Returns the number of the material type which can be set in
+ SMaterial::MaterialType to use the renderer. -1 is returned if an
+ error occured. -1 is returned for example if a vertex or pixel shader
+ program could not be compiled, the error strings are then printed out
+ into the error log, and can be catched with a custom event receiver. */
+ virtual s32 getXMLMaterialType(const io::path& xmlShaderFileName,
+ bool& ForceHighLevelShaders,
+ s32 baseMaterial = -1,
+ IShaderConstantSetCallBack* callback = 0,
+ s32 userData = 0) = 0;
+
+
+ //! clears the cache of xmlShaders, doesnt delete the shaders and callbacks though
+ virtual void clearXMLShaderCache() = 0;
+
+ //! Returns how many XML shaders there are
+ //! \return xml shader count
+ virtual u32 getXMLShaderCount() const = 0;
+
+ //! Returns an XML shader material type.
+ //! \param idx: Zero based index of the light. Note: first indices correspond
+ //! to EMT enums
+ //! \return Material Type.
+ virtual s32 getXMLShaderByIndex(u32 idx) const = 0;
};
Index: include/irrlicht.h
===================================================================
--- include/irrlicht.h (revision 3488)
+++ include/irrlicht.h (working copy)
@@ -39,6 +39,7 @@
#include "dimension2d.h"
#include "ECullingTypes.h"
#include "EDebugSceneTypes.h"
+#include "EDefaultShaderConstants.h"
#include "EDriverFeatures.h"
#include "EDriverTypes.h"
#include "EGUIAlignment.h"
@@ -64,6 +65,7 @@
#include "IBoneSceneNode.h"
#include "ICameraSceneNode.h"
#include "ICursorControl.h"
+#include "IDefaultShaderCallBack.h"
#include "IDummyTransformationSceneNode.h"
#include "IDynamicMeshBuffer.h"
#include "IEventReceiver.h"
@@ -178,6 +180,7 @@
#include "SParticle.h"
#include "SSharedMeshBuffer.h"
#include "SSkinMeshBuffer.h"
+#include "SUniqueXmlShader.h"
#include "SVertexIndex.h"
#include "SViewFrustum.h"
#include "triangle3d.h"
Index: include/EMaterialTypes.h
===================================================================
--- include/EMaterialTypes.h (revision 3488)
+++ include/EMaterialTypes.h (working copy)
@@ -192,6 +192,9 @@
/** Using only first texture. Generic blending method. */
EMT_ONETEXTURE_BLEND,
+ //! Tells how many built in materials there are
+ EMT_COUNT,
+
//! This value is not used. It only forces this enumeration to compile to 32 bit.
EMT_FORCE_32BIT = 0x7fffffff
};
Index: include/IDefaultShaderCallBack.h
===================================================================
--- include/IDefaultShaderCallBack.h (revision 0)
+++ include/IDefaultShaderCallBack.h (revision 0)
@@ -0,0 +1,38 @@
+#ifndef __I_DEFAULT_SHADER_CALLBACK_H_INCLUDED__
+#define __I_DEFAULT_SHADER_CALLBACK_H_INCLUDED__
+
+#include "EDefaultShaderConstants.h"
+#include "irrArray.h"
+#include "IShaderConstantSetCallBack.h"
+#include "ISceneManager.h"
+
+namespace irr
+{
+namespace video
+{
+
+
+class IDefaultShaderCallBack : public IShaderConstantSetCallBack
+{
+private:
+
+ u32 edscFlags;
+ core::array<SDefaultShaderConstantRegisters> Registers;
+ IShaderConstantSetCallBack* callBack;
+ bool highOrLowLevel;
+
+public:
+
+ IDefaultShaderCallBack(u32 flags, core::array<SDefaultShaderConstantRegisters> registers, IShaderConstantSetCallBack* callback=0);
+ ~IDefaultShaderCallBack();
+
+ void OnSetMaterial(const SMaterial& material);
+ void OnSetConstants(video::IMaterialRendererServices* services,s32 userData);
+ void setHighorLowLevel(bool level) {highOrLowLevel=level;}
+};
+
+
+} // end namespace video
+} // end namespace irr
+
+#endif
Index: include/EDefaultShaderConstants.h
===================================================================
--- include/EDefaultShaderConstants.h (revision 0)
+++ include/EDefaultShaderConstants.h (revision 0)
@@ -0,0 +1,98 @@
+#ifndef __E_DEFAULT_SHADER_CONSTANTS_H_INCLUDED__
+#define __E_DEFAULT_SHADER_CONSTANTS_H_INCLUDED__
+
+#include "irrTypes.h"
+#include "irrString.h"
+
+namespace irr
+{
+namespace video
+{
+
+struct SDefaultShaderConstantRegisters
+{
+ int Register;
+ core::stringc Name;
+ bool pixelOrVertex;
+};
+
+//! Default Shader Constants enumeration to be passed by the IDefaultShaderCallBack
+enum E_DEFAULT_SHADER_CONSTANTS
+{
+ EDSC_WORLD_TFORM = 0,
+ EDSC_VIEW_TFORM,
+ EDSC_PROJ_TFORM,
+ EDSC_VIEW_PROJ_TFORM,
+ EDSC_WORLD_VIEW_PROJ_TFORM,
+ EDSC_WORLD_TFORM_INV,
+ EDSC_VIEW_TFORM_INV,
+ EDSC_PROJ_TFORM_INV,
+ EDSC_VIEW_PROJ_TFORM_INV,
+ EDSC_WORLD_VIEW_PROJ_TFORM_INV,
+ EDSC_WORLD_TRANSPOSED,
+ EDSC_VIEW_TRANSPOSED,
+ EDSC_PROJ_TRANSPOSED,
+ EDSC_VIEW_PROJ_TRANSPOSED,
+ EDSC_WORLD_VIEW_PROJ_TRANSPOSED,
+ EDSC_WORLD_TRANSPOSED_INV,
+ EDSC_VIEW_TRANSPOSED_INV,
+ EDSC_PROJ_TRANSPOSED_INV,
+ EDSC_VIEW_PROJ_TRANSPOSED_INV,
+ EDSC_WORLD_VIEW_PROJ_TRANSPOSED_INV,
+ EDSC_FRAME_BUFFER_SIZE,
+ EDSC_CAMERA_FAR_DISTANCE,
+ EDSC_TEX0,
+ EDSC_TEX1,
+ EDSC_TEX2,
+ EDSC_TEX3,
+ EDSC_TEX4,
+ EDSC_TEX5,
+ EDSC_TEX6,
+ EDSC_TEX7,
+
+ //! This is not a type, but a value indicating how many types there are.
+ EDSC_COUNT,
+ EDSC_FORCE_32BIT = 0x7fffffff
+};
+
+//! Names for all vertex shader types, each entry corresponds to a E_DEFAULT_SHADER_CONSTANTS entry.
+const c8* const DEFAULT_SHADER_CONSTANTS_NAMES[] = {
+ "worldTrans",
+ "viewTrans",
+ "projTrans",
+ "viewProjTrans",
+ "worldViewProjTrans",
+ "worldTransInv",
+ "viewTransInv",
+ "projTransInv",
+ "viewProjTransInv",
+ "worldViewProjTransInv",
+ "worldTransposed",
+ "viewTransposed",
+ "projTransposed",
+ "viewProjTransposed",
+ "worldViewProjTransposed",
+ "worldTransposedInv",
+ "viewTransposedInv",
+ "projTransposedInv",
+ "viewProjTransposedInv",
+ "worldViewProjTransposedInv",
+ "frameBufferSize",
+ "camFarDistance",
+ "tex0",
+ "tex1",
+ "tex2",
+ "tex3",
+ "tex4",
+ "tex5",
+ "tex6",
+ "tex7",
+ 0 };
+
+
+} // end namespace video
+} // end namespace irr
+
+#endif // __E_DEFAULT_SHADER_CONSTANTS_H_INCLUDED__
+
+
Index: examples/26.XMLShaders/main.cpp
===================================================================
--- examples/26.XMLShaders/main.cpp (revision 0)
+++ examples/26.XMLShaders/main.cpp (revision 0)
@@ -0,0 +1,272 @@
+/** Example 026 XML Shaders
+
+This tutorial shows how to use an XML file to load shaders for D3D8, D3D9,
+and OpenGL with the engine and use the default shader callback to pass global
+parameters such as transform matrices. It also shows how to pass your own custom
+constants on top of the default callback.
+
+This tutorial does not explain how irrlicht handles shaders, look in example 010.
+
+At first, we need to include all headers and do the stuff we always do, like in
+nearly all other tutorials:
+*/
+#include <irrlicht.h>
+#include <iostream>
+#include "driverChoice.h"
+
+using namespace irr;
+
+#ifdef _MSC_VER
+#pragma comment(lib, "Irrlicht.lib")
+#endif
+
+/*
+If you look at the code for example 010 you can see that this callback doesn't
+pass the transform matrices, irrlicht does it automatically.
+
+However in this case we need to pass some custom, non standard variables and
+constants, to do this we create a shader callback that is used on top of the
+irrlicht callback (and gets called by it).
+*/
+
+IrrlichtDevice* device = 0;
+bool UseHighLevelShaders = false;
+
+class MyShaderCallBack : public video::IShaderConstantSetCallBack
+{
+public:
+
+ virtual void OnSetConstants(video::IMaterialRendererServices* services,
+ s32 userData)
+ {
+ video::IVideoDriver* driver = services->getVideoDriver();
+
+ // set camera position
+
+ core::vector3df pos = device->getSceneManager()->
+ getActiveCamera()->getAbsolutePosition();
+
+ if (UseHighLevelShaders)
+ services->setVertexShaderConstant("mLightPos", reinterpret_cast<f32*>(&pos), 3);
+ else
+ services->setVertexShaderConstant(reinterpret_cast<f32*>(&pos), 8, 1);
+
+ // set light color
+
+ video::SColorf col(0.0f,1.0f,1.0f,0.0f);
+
+ if (UseHighLevelShaders)
+ services->setVertexShaderConstant("mLightColor",
+ reinterpret_cast<f32*>(&col), 4);
+ else
+ services->setVertexShaderConstant(reinterpret_cast<f32*>(&col), 9, 1);
+
+ }
+};
+
+
+
+int main()
+{
+ // ask user for driver
+ video::E_DRIVER_TYPE driverType=driverChoiceConsole();
+ if (driverType==video::EDT_COUNT)
+ return 1;
+
+ // ask the user if we should use high level shaders for this example
+ if (driverType == video::EDT_DIRECT3D9 ||
+ driverType == video::EDT_OPENGL)
+ {
+ char i;
+ printf("Please press 'y' if you want to use high level shaders.\n");
+ std::cin >> i;
+ if (i == 'y')
+ UseHighLevelShaders = true;
+ }
+
+ // create device
+
+ device = createDevice(driverType, core::dimension2d<u32>(640, 480));
+
+ if (device == 0)
+ return 1; // could not create selected driver.
+
+
+ video::IVideoDriver* driver = device->getVideoDriver();
+ scene::ISceneManager* smgr = device->getSceneManager();
+ gui::IGUIEnvironment* gui = device->getGUIEnvironment();
+
+ /*
+ If you notice the only consideration we must take is what driver we are using
+ as to which xml we are going to use
+ */
+
+ io::path xmlFileName; // filename for the XML shader file
+
+ switch(driverType)
+ {
+ case video::EDT_DIRECT3D8:
+ xmlFileName = "../../media/d3d8Shader.xml";
+ break;
+ case video::EDT_DIRECT3D9:
+ xmlFileName = "../../media/d3d9Shader.xml";
+ break;
+
+ case video::EDT_OPENGL:
+ xmlFileName = "../../media/glShader.xml";
+ break;
+ }
+
+ /*
+ Now lets create the new materials. 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
+ addShaderMaterialFromXML(), which returns such a new 32 bit value.
+ That's all.
+
+ However there is one more compulsory parameter, ForceHighLevelShaders
+ which you must set. It takes a reference and changes the bool if a
+ High Level Shader couldn't be created.
+
+ To demonstrate this, we create two materials with a different base
+ material, one with EMT_SOLID and one with EMT_TRANSPARENT_ADD_COLOR.
+
+ The last material is here to prove that there are fake xmlShaders
+ already created for fixed function materials
+ */
+
+ // create materials
+
+ video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
+ s32 newMaterialType1 = 0;
+ s32 newMaterialType2 = 0;
+ s32 newMaterialType3 = video::EMT_TRANSPARENT_ADD_COLOR; // will change to EMT_SOLID
+
+ if (gpu)
+ {
+ MyShaderCallBack* mc = new MyShaderCallBack();
+
+ newMaterialType1 = gpu->getXMLMaterialType(xmlFileName, UseHighLevelShaders, video::EMT_SOLID, mc);
+
+ newMaterialType2 = gpu->getXMLMaterialType(xmlFileName, UseHighLevelShaders, video::EMT_TRANSPARENT_ADD_COLOR, mc);
+
+ newMaterialType3 = gpu->getXMLMaterialType("solid", UseHighLevelShaders);
+
+ mc->drop();
+ }
+
+ /*
+ 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.
+ */
+
+ // create test scene node 1, with the new created material type 1
+
+ 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);
+
+ scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
+ core::vector3df(0,0.3f,0));
+ node->addAnimator(anim);
+ anim->drop();
+
+ /*
+ Same for the second cube, but with the second material we created.
+ */
+
+ // create test scene node 2, with the new created material type 2
+
+ 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);
+
+ anim = smgr->createRotationAnimator(core::vector3df(0,0.3f,0));
+ node->addAnimator(anim);
+ anim->drop();
+
+ /*
+ Then we add a third cube without a shader on it, to be able to compare
+ the cubes.
+ */
+
+ // add a scene node with no shader
+
+ 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);
+ node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType3);
+
+ /*
+ 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.
+ */
+
+ // add a nice skybox
+
+ driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
+
+ smgr->addSkyBoxSceneNode(
+ driver->getTexture("../../media/irrlicht2_up.jpg"),
+ driver->getTexture("../../media/irrlicht2_dn.jpg"),
+ driver->getTexture("../../media/irrlicht2_lf.jpg"),
+ driver->getTexture("../../media/irrlicht2_rt.jpg"),
+ driver->getTexture("../../media/irrlicht2_ft.jpg"),
+ driver->getTexture("../../media/irrlicht2_bk.jpg"));
+
+ driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
+
+ // add a camera and disable the mouse cursor
+
+ scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS();
+ cam->setPosition(core::vector3df(-100,50,100));
+ cam->setTarget(core::vector3df(0,0,0));
+ device->getCursorControl()->setVisible(false);
+
+ /*
+ Now draw everything. That's all.
+ */
+
+ int lastFPS = -1;
+
+ while(device->run())
+ if (device->isWindowActive())
+ {
+ driver->beginScene(true, true, video::SColor(255,0,0,0));
+ smgr->drawAll();
+ driver->endScene();
+
+ int fps = driver->getFPS();
+
+ if (lastFPS != fps)
+ {
+ core::stringw str = L"Irrlicht Engine - Vertex and pixel shader example [";
+ str += driver->getName();
+ str += "] FPS:";
+ str += fps;
+
+ device->setWindowCaption(str.c_str());
+ lastFPS = fps;
+ }
+ }
+
+ device->drop();
+
+ return 0;
+}
+
Index: examples/26.XMLShaders/XMLShaders.layout
===================================================================
--- examples/26.XMLShaders/XMLShaders.layout (revision 0)
+++ examples/26.XMLShaders/XMLShaders.layout (revision 0)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <ActiveTarget name="Linux" />
+ <File name="main.cpp" open="1" top="1" tabpos="1">
+ <Cursor position="4774" topLine="139" />
+ </File>
+</CodeBlocks_layout_file>
Index: examples/26.XMLShaders/Makefile
===================================================================
--- examples/26.XMLShaders/Makefile (revision 0)
+++ examples/26.XMLShaders/Makefile (revision 0)
@@ -0,0 +1,38 @@
+# Makefile for Irrlicht Examples
+# It's usually sufficient to change just the target name and source file list
+# and be sure that CXX is set to a valid compiler
+Target = 26.XMLShaders
+Sources = main.cpp
+
+# general compiler settings
+CPPFLAGS = -I../../include -I/usr/X11R6/include
+CXXFLAGS = -O3 -ffast-math
+#CXXFLAGS = -g -Wall
+
+#default target is Linux
+all: all_linux
+
+ifeq ($(HOSTTYPE), x86_64)
+LIBSELECT=64
+endif
+
+# target specific settings
+all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor
+all_linux clean_linux: SYSTEM=Linux
+all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm
+all_win32 clean_win32: SYSTEM=Win32-gcc
+all_win32 clean_win32: SUF=.exe
+# name of the binary - only valid for targets which set SYSTEM
+DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF)
+
+all_linux all_win32:
+ $(warning Building...)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS)
+
+clean: clean_linux clean_win32
+ $(warning Cleaning...)
+
+clean_linux clean_win32:
+ @$(RM) $(DESTPATH)
+
+.PHONY: all all_win32 clean clean_linux clean_win32
Index: examples/26.XMLShaders/XMLShaders.cbp
===================================================================
--- examples/26.XMLShaders/XMLShaders.cbp (revision 0)
+++ examples/26.XMLShaders/XMLShaders.cbp (revision 0)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="Irrlicht Example 26 XML Shaders" />
+ <Option pch_mode="0" />
+ <Option compiler="gcc" />
+ <Build>
+ <Target title="Windows">
+ <Option platforms="Windows;" />
+ <Option output="../../bin/Win32-gcc/XMLShaders" prefix_auto="0" extension_auto="1" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option projectResourceIncludeDirsRelation="1" />
+ <Compiler>
+ <Add option="-W" />
+ <Add option="-g" />
+ </Compiler>
+ <Linker>
+ <Add directory="../../lib/Win32-gcc" />
+ </Linker>
+ </Target>
+ <Target title="Linux">
+ <Option platforms="Unix;" />
+ <Option output="../../bin/Linux/XMLShaders" prefix_auto="0" extension_auto="0" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-W" />
+ <Add option="-g" />
+ <Add option="-D_IRR_STATIC_LIB_" />
+ </Compiler>
+ <Linker>
+ <Add library="Xxf86vm" />
+ <Add library="/usr/lib/libXcursor.so.1" />
+ <Add library="GL" />
+ <Add directory="../../lib/Linux" />
+ </Linker>
+ </Target>
+ </Build>
+ <VirtualTargets>
+ <Add alias="All" targets="Windows;" />
+ </VirtualTargets>
+ <Compiler>
+ <Add option="-W" />
+ <Add option="-g" />
+ <Add directory="../../include" />
+ </Compiler>
+ <Linker>
+ <Add library="Irrlicht" />
+ </Linker>
+ <Unit filename="main.cpp" />
+ <Extensions>
+ <code_completion />
+ <debugger />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>