From f68acbf47a35850cf89c5179c9d769ac3f028b3e Mon Sep 17 00:00:00 2001 From: kgv Date: Wed, 23 Mar 2016 12:42:17 +0300 Subject: [PATCH] 0027286: Visualization, TKOpenGl - avoid using light index within built-in GLSL programs for simplest configuration OpenGl_ShaderManager::stdComputeLighting() - handle single directional light specifically for compatibility with broken OpenGL ES drivers. Added test cases using built-in GLSL shading programs. --- src/OpenGl/OpenGl_ShaderManager.cxx | 69 ++++++++++++++++++++++------- tests/v3d/glsl/begin | 4 +- tests/v3d/glsl/gouraud_dir1 | 16 +++++++ tests/v3d/glsl/gouraud_dir2 | 24 ++++++++++ tests/v3d/glsl/phong_dir1 | 16 +++++++ tests/v3d/glsl/phong_dir2 | 24 ++++++++++ 6 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 tests/v3d/glsl/gouraud_dir1 create mode 100644 tests/v3d/glsl/gouraud_dir2 create mode 100644 tests/v3d/glsl/phong_dir1 create mode 100644 tests/v3d/glsl/phong_dir2 diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 4fa96b9268..68e1db0bdd 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -187,6 +187,35 @@ const char THE_FUNC_directionalLight[] = EOL" Specular += occLight_Specular (theId).rgb * aSpecl;" EOL"}"; +//! The same as THE_FUNC_directionalLight but for the light with zero index +//! (avoids limitations on some mobile devices). +const char THE_FUNC_directionalLightFirst[] = + EOL"void directionalLightFirst (in vec3 theNormal," + EOL" in vec3 theView," + EOL" in bool theIsFront)" + EOL"{" + EOL" vec3 aLight = normalize (occLightSources[1].xyz);" + EOL" if (occLight_IsHeadlight (0) == 0)" + EOL" {" + EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));" + EOL" }" + EOL + EOL" vec3 aHalf = normalize (aLight + theView);" + EOL + EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;" + EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));" + EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));" + EOL + EOL" float aSpecl = 0.0;" + EOL" if (aNdotL > 0.0)" + EOL" {" + EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());" + EOL" }" + EOL + EOL" Diffuse += occLightSources[0].rgb * aNdotL;" + EOL" Specular += occLightSources[0].rgb * aSpecl;" + EOL"}"; + //! Process clipping planes in Fragment Shader. //! Should be added at the beginning of the main() function. const char THE_FRAG_CLIP_PLANES[] = @@ -1354,7 +1383,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad // ======================================================================= TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor) { - bool aLightsMap[Graphic3d_TOLS_SPOT + 1] = { false, false, false, false }; + Standard_Integer aLightsMap[Graphic3d_TOLS_SPOT + 1] = { 0, 0, 0, 0 }; TCollection_AsciiString aLightsFunc, aLightsLoop; const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources(); if (aLights != NULL) @@ -1377,21 +1406,29 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; break; } - - bool& aTypeBit = aLightsMap[aLightIter.Value().Type]; - if (aTypeBit) - { - continue; - } - - aTypeBit = true; - switch (aLightIter.Value().Type) - { - case Graphic3d_TOLS_AMBIENT: break; - case Graphic3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break; - case Graphic3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break; - case Graphic3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break; - } + aLightsMap[aLightIter.Value().Type] += 1; + } + const Standard_Integer aNbLoopLights = aLightsMap[Graphic3d_TOLS_DIRECTIONAL] + + aLightsMap[Graphic3d_TOLS_POSITIONAL] + + aLightsMap[Graphic3d_TOLS_SPOT]; + if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] == 1 + && aNbLoopLights == 1) + { + // use the version with hard-coded first index + aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);"; + aLightsFunc += THE_FUNC_directionalLightFirst; + } + else if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] > 0) + { + aLightsFunc += THE_FUNC_directionalLight; + } + if (aLightsMap[Graphic3d_TOLS_POSITIONAL] > 0) + { + aLightsFunc += THE_FUNC_pointLight; + } + if (aLightsMap[Graphic3d_TOLS_SPOT] > 0) + { + aLightsFunc += THE_FUNC_spotLight; } } diff --git a/tests/v3d/glsl/begin b/tests/v3d/glsl/begin index 6cabd388d9..7b04e56f2d 100644 --- a/tests/v3d/glsl/begin +++ b/tests/v3d/glsl/begin @@ -1 +1,3 @@ -vinit View1 \ No newline at end of file +vclear +vclose ALL +vinit View1 diff --git a/tests/v3d/glsl/gouraud_dir1 b/tests/v3d/glsl/gouraud_dir1 new file mode 100644 index 0000000000..37541b0918 --- /dev/null +++ b/tests/v3d/glsl/gouraud_dir1 @@ -0,0 +1,16 @@ +puts "========" +puts "Per-vertex lighting using built-in GLSL program, one directional light source." +puts "Visual comparison with the reference snapshot should be performed for this test case." +puts "========" + +# setup viewer +vcaps -ffp 0 +vrenderparams -shadingModel vert + +# display shape +restore [locate_data_file occ/fuse.brep] f +vaxo +vdisplay f -dispmode 1 +vfit +vrotate -0.5 0.0 0.0 +vfit diff --git a/tests/v3d/glsl/gouraud_dir2 b/tests/v3d/glsl/gouraud_dir2 new file mode 100644 index 0000000000..72f3a41b9c --- /dev/null +++ b/tests/v3d/glsl/gouraud_dir2 @@ -0,0 +1,24 @@ +puts "========" +puts "Per-vertex lighting using built-in GLSL program, two directional light sources." +puts "Visual comparison with the reference snapshot should be performed for this test case." +puts "========" + +# setup viewer +vcaps -ffp 0 +vrenderparams -shadingModel vert +vlight delete 0 +vlight delete 0 +vlight delete 0 +vlight delete 0 +vlight delete 0 +vlight add ambient color WHITE +vlight add directional dir 1 0 0 color GREEN headlight 1 +vlight add directional dir -1 0 0 color RED1 headlight 1 + +# display shape +restore [locate_data_file occ/fuse.brep] f +vaxo +vdisplay f -dispmode 1 +vfit +vrotate -0.5 0.0 0.0 +vfit diff --git a/tests/v3d/glsl/phong_dir1 b/tests/v3d/glsl/phong_dir1 new file mode 100644 index 0000000000..d6b31b54d8 --- /dev/null +++ b/tests/v3d/glsl/phong_dir1 @@ -0,0 +1,16 @@ +puts "========" +puts "Per-fragment lighting using built-in GLSL program, one directional light source." +puts "Visual comparison with the reference snapshot should be performed for this test case." +puts "========" + +# setup viewer +vcaps -ffp 0 +vrenderparams -shadingModel phong + +# display shape +restore [locate_data_file occ/fuse.brep] f +vaxo +vdisplay f -dispmode 1 +vfit +vrotate -0.5 0.0 0.0 +vfit diff --git a/tests/v3d/glsl/phong_dir2 b/tests/v3d/glsl/phong_dir2 new file mode 100644 index 0000000000..4eb064b658 --- /dev/null +++ b/tests/v3d/glsl/phong_dir2 @@ -0,0 +1,24 @@ +puts "========" +puts "Per-fragment lighting using built-in GLSL program, two directional light sources." +puts "Visual comparison with the reference snapshot should be performed for this test case." +puts "========" + +# setup viewer +vcaps -ffp 0 +vrenderparams -shadingModel phong +vlight delete 0 +vlight delete 0 +vlight delete 0 +vlight delete 0 +vlight delete 0 +vlight add ambient color WHITE +vlight add directional dir 1 0 0 color GREEN headlight 1 +vlight add directional dir -1 0 0 color RED1 headlight 1 + +# display shape +restore [locate_data_file occ/fuse.brep] f +vaxo +vdisplay f -dispmode 1 +vfit +vrotate -0.5 0.0 0.0 +vfit