From 8c3237d45195791ad41bfa30b22a5fe8a6e35c2f Mon Sep 17 00:00:00 2001 From: kgv Date: Sun, 10 Sep 2017 17:06:19 +0300 Subject: [PATCH] 0028069: Visualization, TKOpenGl - handle flat shading model within GLSL programs --- src/OpenGl/OpenGl_Context.cxx | 2 ++ src/OpenGl/OpenGl_Context.hxx | 1 + src/OpenGl/OpenGl_ShaderManager.cxx | 51 ++++++++++++++++++++++++----- src/OpenGl/OpenGl_ShaderManager.hxx | 15 ++++++--- tests/v3d/glsl/flat_fuse1 | 22 +++++++++++++ 5 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 tests/v3d/glsl/flat_fuse1 diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 494ca044f5..790be6e2ce 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -152,6 +152,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) atiMem (Standard_False), nvxMem (Standard_False), oesSampleVariables (Standard_False), + oesStdDerivatives (Standard_False), mySharedResources (new OpenGl_ResourcesMap()), myDelayed (new OpenGl_DelayReleaseMap()), myUnusedResources (new OpenGl_ResourcesStack()), @@ -1412,6 +1413,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) : OpenGl_FeatureNotAvailable; oesSampleVariables = CheckExtension ("GL_OES_sample_variables"); + oesStdDerivatives = CheckExtension ("GL_OES_standard_derivatives"); hasSampleVariables = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore : oesSampleVariables ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 018fa460df..58d150f273 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -823,6 +823,7 @@ public: //! @name extensions Standard_Boolean atiMem; //!< GL_ATI_meminfo Standard_Boolean nvxMem; //!< GL_NVX_gpu_memory_info Standard_Boolean oesSampleVariables; //!< GL_OES_sample_variables + Standard_Boolean oesStdDerivatives; //!< GL_OES_standard_derivatives public: //! @name public properties tracking current state diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index e01e151343..1867cc7b1d 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -479,7 +479,14 @@ Standard_Boolean OpenGl_ShaderManager::IsEmpty() const // ======================================================================= void OpenGl_ShaderManager::switchLightPrograms() { - TCollection_AsciiString aKey (myShadingModel == Graphic3d_TOSM_FRAGMENT ? "p_" : "g_"); + TCollection_AsciiString aKey; + switch (myShadingModel) + { + case Graphic3d_TOSM_NONE: aKey = "c_"; break; + case Graphic3d_TOSM_FACET: aKey = "f_"; break; + case Graphic3d_TOSM_VERTEX: aKey = "g_"; break; + case Graphic3d_TOSM_FRAGMENT: aKey = "p_"; break; + } const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources(); if (aLights != NULL) { @@ -1847,9 +1854,17 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S // purpose : // ======================================================================= Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram, - const Standard_Integer theBits) + const Standard_Integer theBits, + const Standard_Boolean theIsFlatNormal) { #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)" +#if defined(GL_ES_VERSION_2_0) + const bool isFlatNormal = theIsFlatNormal + && (myContext->IsGlGreaterEqual (3, 0) + || myContext->oesStdDerivatives); +#else + const bool isFlatNormal = theIsFlatNormal; +#endif Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain; @@ -1920,20 +1935,22 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha } aSrcVert = TCollection_AsciiString() - + THE_FUNC_transformNormal + + (isFlatNormal ? "" : THE_FUNC_transformNormal) + EOL EOL"THE_SHADER_OUT vec4 PositionWorld;" EOL"THE_SHADER_OUT vec4 Position;" - EOL"THE_SHADER_OUT vec3 Normal;" EOL"THE_SHADER_OUT vec3 View;" - EOL + + (isFlatNormal ? "" + : EOL"THE_SHADER_OUT vec3 Normal;") + + EOL + aSrcVertExtraOut + EOL"void main()" EOL"{" EOL" PositionWorld = occModelWorldMatrix * occVertex;" EOL" Position = occWorldViewMatrix * PositionWorld;" - EOL" Normal = transformNormal (occNormal);" - EOL" View = vec3 (0.0, 0.0, 1.0);" + + (isFlatNormal ? "" + : EOL" Normal = transformNormal (occNormal);") + + EOL" View = vec3 (0.0, 0.0, 1.0);" + aSrcVertExtraMain + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;" EOL"}"; @@ -1942,8 +1959,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha aSrcFrag = TCollection_AsciiString() + EOL"THE_SHADER_IN vec4 PositionWorld;" EOL"THE_SHADER_IN vec4 Position;" - EOL"THE_SHADER_IN vec3 Normal;" EOL"THE_SHADER_IN vec3 View;" + + (isFlatNormal + ? EOL"vec3 Normal;" + : EOL"THE_SHADER_IN vec3 Normal;") + EOL + aSrcFragExtraOut + aSrcFragGetVertColor @@ -1953,6 +1972,9 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha EOL"void main()" EOL"{" + aSrcFragExtraMain + + (isFlatNormal + ? EOL" Normal = normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));" + : "") + EOL" occFragColor = getColor();" + aSrcFragWriteOit + EOL"}"; @@ -1967,6 +1989,19 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha { aProgramSrc->SetHeader ("#version 300 es"); } + else if (isFlatNormal) + { + if (myContext->oesStdDerivatives) + { + aProgramSrc->SetHeader ("#extension GL_OES_standard_derivatives : enable"); + } + else + { + myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, + GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, + "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension."); + } + } #endif aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 9e5d2f7cf2..8e68cd382a 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -423,9 +423,14 @@ protected: Standard_Boolean prepareStdProgramLight (Handle(OpenGl_ShaderProgram)& theProgram, const Standard_Integer theBits) { - return myShadingModel == Graphic3d_TOSM_FRAGMENT - ? prepareStdProgramPhong (theProgram, theBits) - : prepareStdProgramGouraud (theProgram, theBits); + switch (myShadingModel) + { + case Graphic3d_TOSM_NONE: return prepareStdProgramFlat (theProgram, theBits); + case Graphic3d_TOSM_FACET: return prepareStdProgramPhong (theProgram, theBits, true); + case Graphic3d_TOSM_VERTEX: return prepareStdProgramGouraud(theProgram, theBits); + case Graphic3d_TOSM_FRAGMENT: return prepareStdProgramPhong (theProgram, theBits, false); + } + return false; } //! Prepare standard GLSL program with per-vertex lighting. @@ -433,8 +438,10 @@ protected: const Standard_Integer theBits); //! Prepare standard GLSL program with per-pixel lighting. + //! @param theIsFlatNormal when TRUE, the Vertex normals will be ignored and Face normal will be computed instead Standard_EXPORT Standard_Boolean prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram, - const Standard_Integer theBits); + const Standard_Integer theBits, + const Standard_Boolean theIsFlatNormal = false); //! Define computeLighting GLSL function depending on current lights configuration //! @param theHasVertColor flag to use getVertColor() instead of Ambient and Diffuse components of active material diff --git a/tests/v3d/glsl/flat_fuse1 b/tests/v3d/glsl/flat_fuse1 new file mode 100644 index 0000000000..19dd37f1cf --- /dev/null +++ b/tests/v3d/glsl/flat_fuse1 @@ -0,0 +1,22 @@ +puts "========" +puts "0028069: Visualization, TKOpenGl - handle flat shading model within GLSL programs" +puts "========" + +vclear +vclose ALL +vinit View1 +vviewparams -scale 551.55 -proj 0.85 -0.16 0.51 -up -0.41 0.41 0.82 -at 0.55 0.55 0.55 + +restore [locate_data_file occ/fuse.brep] f +tclean f +vdefaults -absDefl 0.5 +vdisplay -dispMode 1 f + +# setup lights +vlight clear +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 + +vrenderparams -shadingModel flat +vdump $::imagedir/${::casename}.png -- 2.20.1