diff --git a/changes.txt b/changes.txt index eacde083..fca0528a 100644 --- a/changes.txt +++ b/changes.txt @@ -1,6 +1,8 @@ -------------------------- Changes in 1.9 (not yet released) +- Shader materials shows now how to pass material values. + In 1.8 we could still use gl_FrontMaterial, but that is no longer supported in shaders - Get IMeshBuffer::append functions working for a few more cases and adapt interface so one can prevent the BoundingBox update. - Bugfix: SMaterialLayer::operator!= no longer returns true when comparing a layer without texture matrix with one with a set identity texture matrix. Those are the same. - SMaterialLayer no longer releases allocated texture memory before destructor unless explicitly requested. diff --git a/examples/10.Shaders/main.cpp b/examples/10.Shaders/main.cpp index 7a3fffd9..98151428 100644 --- a/examples/10.Shaders/main.cpp +++ b/examples/10.Shaders/main.cpp @@ -48,8 +48,10 @@ class MyShaderCallBack : public video::IShaderConstantSetCallBack { public: MyShaderCallBack() : WorldViewProjID(-1), TransWorldID(-1), InvWorldID(-1), PositionID(-1), - ColorID(-1), TextureID(-1) + ColorID(-1), TextureID(-1), EmissiveID(-1) { + for ( int i=0; i<4; ++i ) + Emissive[i] = 0.f; } virtual void OnCreate(video::IMaterialRendererServices* services, s32 userData) @@ -57,14 +59,15 @@ public: if (UseHighLevelShaders) { // Get shader constants id. - // Constants are "uniforms" in most modern shading languages. + // Constants are "uniforms" in other shading languages. // And they are not constant at all but can be changed before every draw call - // (the naming probably has some historical reasons which got lost in time) + // (the naming probably comes from Direct3D where they are called constants) WorldViewProjID = services->getVertexShaderConstantID("mWorldViewProj"); TransWorldID = services->getVertexShaderConstantID("mTransWorld"); InvWorldID = services->getVertexShaderConstantID("mInvWorld"); PositionID = services->getVertexShaderConstantID("mLightPos"); ColorID = services->getVertexShaderConstantID("mLightColor"); + EmissiveID = services->getPixelShaderConstantID("mEmissive"); // Textures ID are important only for OpenGL interface. video::IVideoDriver* driver = services->getVideoDriver(); @@ -94,6 +97,21 @@ public: services->setVertexShaderConstant(reinterpret_cast(&col), 9, 1); } + // Called when any SMaterial value changes + virtual void OnSetMaterial(const irr::video::SMaterial& material) + { + // Remember material values to pass them on to shader in OnSetConstants + Emissive[0] = material.EmissiveColor.getRed() / 255.0f; + Emissive[1] = material.EmissiveColor.getGreen() / 255.0f; + Emissive[2] = material.EmissiveColor.getBlue() / 255.0f; + Emissive[3] = material.EmissiveColor.getAlpha() / 255.0f; + + // Note: Until Irrlicht 1.8 it was possible to use gl_FrontMaterial in glsl + // This is no longer supported since Irrlicht 1.9 + // Reason: Passing always every material value is slow, harder to port + // and generally getting deprecated in newer shader systems. + } + virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData) { @@ -148,6 +166,12 @@ public: } else services->setVertexShaderConstant(world.pointer(), 10, 4); + + // Set material values + if (UseHighLevelShaders) + { + services->setPixelShaderConstant(EmissiveID, Emissive, 4); + } } private: @@ -157,6 +181,9 @@ private: s32 PositionID; s32 ColorID; s32 TextureID; + + s32 EmissiveID; + irr::f32 Emissive[4]; }; /* @@ -393,6 +420,7 @@ int main() node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialFlag(video::EMF_BLEND_OPERATION, true); node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType2); + node->getMaterial(0).EmissiveColor = irr::video::SColor(0,50,0,50); smgr->addTextSceneNode(gui->getBuiltInFont(), L"PS & VS & EMT_TRANSPARENT", diff --git a/media/d3d9.hlsl b/media/d3d9.hlsl index ff52d6fa..11e1e079 100644 --- a/media/d3d9.hlsl +++ b/media/d3d9.hlsl @@ -11,6 +11,7 @@ float4x4 mInvWorld; // Inverted world matrix float4x4 mTransWorld; // Transposed world matrix float3 mLightPos; // Light position (actually just camera-pos in this case) float4 mLightColor; // Light color +float4 mEmissive; // Emissive material color // Vertex shader output structure @@ -83,6 +84,7 @@ PS_OUTPUT pixelMain(float2 TexCoord : TEXCOORD0, // multiply with diffuse and do other senseless operations Output.RGBColor = Diffuse * col; Output.RGBColor *= 4.0; + Output.RGBColor += mEmissive; return Output; } diff --git a/media/opengl.frag b/media/opengl.frag index 82c3d5c9..5f258ac5 100644 --- a/media/opengl.frag +++ b/media/opengl.frag @@ -1,9 +1,11 @@ uniform sampler2D myTexture; +uniform vec4 mEmissive; void main (void) { vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0])); col *= gl_Color; gl_FragColor = col * 4.0; + gl_FragColor += mEmissive; }