From 35a0c4df8f82c87a62e8e02c8ab3e7103ae8ff89 Mon Sep 17 00:00:00 2001 From: cutealien Date: Sat, 24 Jun 2023 15:42:31 +0000 Subject: [PATCH] Enhance shader material to show how to pass material values Also document that gl_FrontMaterial is no longer supported in Irrlicht 1.9 (this has been the case for a few years, I just never noticed this was changed as I never even knew that was possible in the past...). Will keep it that way is it's definitely going in the right direction (getting rid of legacy support and going towards OpenGL core instead), git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6498 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 2 ++ examples/10.Shaders/main.cpp | 34 +++++++++++++++++++++++++++++++--- media/d3d9.hlsl | 2 ++ media/opengl.frag | 2 ++ 4 files changed, 37 insertions(+), 3 deletions(-) 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; }