diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.cxx b/src/Graphic3d/Graphic3d_ShaderProgram.cxx index 2d708d6737..4ed105112f 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.cxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.cxx @@ -78,7 +78,9 @@ const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder() // ======================================================================= Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() : myNbLightsMax (THE_MAX_LIGHTS_DEFAULT), - myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT) + myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT), + myNbFragOutputs (THE_NB_FRAG_OUTPUTS), + myHasWeightOitOutput (false) { myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_") + TCollection_AsciiString (Standard_Atomic_Increment (&THE_PROGRAM_OBJECT_COUNTER)); diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index b723e9db87..324465e5b8 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -43,6 +43,9 @@ public: //! Default value of THE_MAX_CLIP_PLANES macros within GLSL program (see Declarations.glsl). static const Standard_Integer THE_MAX_CLIP_PLANES_DEFAULT = 8; + //! Default value of THE_NB_FRAG_OUTPUTS macros within GLSL program (see Declarations.glsl). + static const Standard_Integer THE_NB_FRAG_OUTPUTS = 1; + public: //! Creates new empty program object. @@ -115,6 +118,21 @@ public: //! Should be done before GLSL program initialization. Standard_EXPORT void SetVertexAttributes (const Graphic3d_ShaderAttributeList& theAttributes); + //! Returns the number (1+) of Fragment Shader outputs to be written to + //! (more than 1 can be in case of multiple draw buffers); 1 by default. + Standard_Integer NbFragmentOutputs() const { return myNbFragOutputs; } + + //! Sets the number of Fragment Shader outputs to be written to. + //! Should be done before GLSL program initialization. + void SetNbFragmentOutputs (const Standard_Integer theNbOutputs) { myNbFragOutputs = theNbOutputs; } + + //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default. + Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; } + + //! Set if Fragment Shader color should output the weighted OIT coverage. + //! Note that weighted OIT also requires at least 2 Fragment Outputs (color + coverage). + void SetWeightOitOutput (Standard_Boolean theOutput) { myHasWeightOitOutput = theOutput; } + //! Pushes custom uniform variable to the program. //! The list of pushed variables is automatically cleared after applying to GLSL program. //! Thus after program recreation even unchanged uniforms should be pushed anew. @@ -164,6 +182,8 @@ private: TCollection_AsciiString myHeader; //!< GLSL header with version code and used extensions Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES) + Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) + Standard_Boolean myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage }; diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index fdafc5484d..58fbe8ec0e 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -441,18 +441,13 @@ void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standar Standard_Boolean useDefaultFbo = Standard_False; for (Standard_Integer anI = 0; anI < theNb; ++anI) { -#if !defined(GL_ES_VERSION_2_0) - const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffers[anI]) : theDrawBuffers[anI]; -#else - const Standard_Integer aDrawBuffer = theDrawBuffers[anI]; -#endif - if (aDrawBuffer < GL_COLOR_ATTACHMENT0 && aDrawBuffer != GL_NONE) + if (theDrawBuffers[anI] < GL_COLOR_ATTACHMENT0 && theDrawBuffers[anI] != GL_NONE) { useDefaultFbo = Standard_True; } - else if (aDrawBuffer != GL_NONE) + else if (theDrawBuffers[anI] != GL_NONE) { - myDrawBuffers.SetValue (anI, aDrawBuffer); + myDrawBuffers.SetValue (anI, theDrawBuffers[anI]); } } if (arbFBO != NULL && useDefaultFbo) diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index fe84caca72..a664c0751b 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -265,12 +265,6 @@ const char THE_FRAG_CLIP_PLANES_2[] = EOL" discard;" EOL" }"; -//! Output color and coverage for accumulation by OIT algorithm. -const char THE_FRAG_write_oit_buffers[] = - EOL" float aWeight = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);" - EOL" occFragCoverage.r = occFragColor.a * aWeight;" - EOL" occFragColor = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);"; - #if !defined(GL_ES_VERSION_2_0) static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -1194,7 +1188,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont() EOL" vec4 aColor = occColor;" EOL" aColor.a *= getAlpha();" EOL" if (aColor.a <= 0.285) discard;" - EOL" occFragColor = aColor;" + EOL" occSetFragColor (aColor);" EOL"}"; #if !defined(GL_ES_VERSION_2_0) @@ -1245,7 +1239,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit() EOL"void main()" EOL"{" EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;" - EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);" + EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));" EOL"}"; #if defined(GL_ES_VERSION_2_0) @@ -1268,7 +1262,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit() EOL EOL"void main()" EOL"{" - EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);" + EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));" EOL"}"; } #else @@ -1325,7 +1319,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St EOL"{" EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);" EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;" - EOL" occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);" + EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));" EOL"}"; #if !defined(GL_ES_VERSION_2_0) if (myContext->IsGlGreaterEqual (3, 2)) @@ -1352,7 +1346,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St EOL" ivec2 aTexel = ivec2 (textureSize (uAccumTexture) * TexCoord);" EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);" EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;" - EOL" occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);" + EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));" EOL"}"; #if !defined(GL_ES_VERSION_2_0) if (myContext->IsGlGreaterEqual (4, 0)) @@ -1429,7 +1423,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha; TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit; TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }"; - TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();"; + TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getColor());"; if ((theBits & OpenGl_PO_Point) != 0) { #if defined(GL_ES_VERSION_2_0) @@ -1458,14 +1452,14 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad EOL" vec4 aColor = getColor();" EOL" aColor.a = getAlpha();" EOL" if (aColor.a <= 0.1) discard;" - EOL" occFragColor = aColor;"; + EOL" occSetFragColor (aColor);"; } else { aSrcFragMainGetColor = EOL" vec4 aColor = getColor();" EOL" if (aColor.a <= 0.1) discard;" - EOL" occFragColor = aColor;"; + EOL" occSetFragColor (aColor);"; } } else @@ -1536,7 +1530,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad } if ((theBits & OpenGl_PO_WriteOit) != 0) { - aSrcFragWriteOit += THE_FRAG_write_oit_buffers; + aProgramSrc->SetNbFragmentOutputs (2); + aProgramSrc->SetWeightOitOutput (true); } TCollection_AsciiString aSrcVertEndMain; @@ -1578,7 +1573,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;" EOL" vec4 aColor = getColor();" EOL" if (aColor.a <= 0.1) discard;" - EOL" occFragColor = aColor;"; + EOL" occSetFragColor (aColor);"; } else { @@ -1888,7 +1883,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S } if ((theBits & OpenGl_PO_WriteOit) != 0) { - aSrcFragWriteOit += THE_FRAG_write_oit_buffers; + aProgramSrc->SetNbFragmentOutputs (2); + aProgramSrc->SetWeightOitOutput (true); } Standard_Integer aNbLights = 0; @@ -1923,7 +1919,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S + EOL"void main()" EOL"{" + aSrcFragExtraMain - + EOL" occFragColor = getColor();" + + EOL" occSetFragColor (getColor());" + aSrcFragWriteOit + EOL"}"; @@ -2037,7 +2033,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha } if ((theBits & OpenGl_PO_WriteOit) != 0) { - aSrcFragWriteOit += THE_FRAG_write_oit_buffers; + aProgramSrc->SetNbFragmentOutputs (2); + aProgramSrc->SetWeightOitOutput (true); } aSrcVert = TCollection_AsciiString() @@ -2082,7 +2079,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha + (isFlatNormal ? EOL" Normal = normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));" : "") - + EOL" occFragColor = getColor();" + + EOL" occSetFragColor (getColor());" + aSrcFragWriteOit + EOL"}"; @@ -2163,7 +2160,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize EOL" aColorR = pow (aColorR, THE_POW_UP);" EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;" - EOL" occFragColor = pow (aColor, THE_POW_DOWN);" + EOL" occSetFragColor (pow (aColor, THE_POW_DOWN));" EOL"}"; break; } @@ -2181,11 +2178,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)" EOL" {" - EOL" occFragColor = aColorL;" + EOL" occSetFragColor (aColorL);" EOL" }" EOL" else" EOL" {" - EOL" occFragColor = aColorR;" + EOL" occSetFragColor (aColorR);" EOL" }" EOL"}"; break; @@ -2204,11 +2201,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)" EOL" {" - EOL" occFragColor = aColorL;" + EOL" occSetFragColor (aColorL);" EOL" }" EOL" else" EOL" {" - EOL" occFragColor = aColorR;" + EOL" occSetFragColor (aColorR);" EOL" }" EOL"}"; break; @@ -2229,11 +2226,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;" EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))" EOL" {" - EOL" occFragColor = aColorL;" + EOL" occSetFragColor (aColorL);" EOL" }" EOL" else" EOL" {" - EOL" occFragColor = aColorR;" + EOL" occSetFragColor (aColorR);" EOL" }" EOL"}"; break; @@ -2257,11 +2254,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);" EOL" if (TexCoord.x <= 0.5)" EOL" {" - EOL" occFragColor = aColorL;" + EOL" occSetFragColor (aColorL);" EOL" }" EOL" else" EOL" {" - EOL" occFragColor = aColorR;" + EOL" occSetFragColor (aColorR);" EOL" }" EOL"}"; break; @@ -2285,11 +2282,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);" EOL" if (TexCoord.y <= 0.5)" EOL" {" - EOL" occFragColor = aColorL;" + EOL" occSetFragColor (aColorL);" EOL" }" EOL" else" EOL" {" - EOL" occFragColor = aColorR;" + EOL" occSetFragColor (aColorR);" EOL" }" EOL"}"; break; @@ -2316,7 +2313,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh EOL" aColorL.b = 0.0;" EOL" aColorL.g = 0.0;" EOL" aColorR.r = 0.0;" - EOL" occFragColor = aColorL + aColorR;" + EOL" occSetFragColor (aColorL + aColorR);" EOL"}"; break; } diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 17eae9c0e6..1463fee9c5 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -151,6 +151,8 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram myShareCount(1), myNbLightsMax (0), myNbClipPlanesMax (0), + myNbFragOutputs (1), + myHasWeightOitOutput (false), myHasTessShader (false) { memset (myCurrentState, 0, sizeof (myCurrentState)); @@ -180,6 +182,8 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& aShaderMask |= anIter.Value()->Type(); } myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0; + myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1; + myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1; // detect the minimum GLSL version required for defined Shader Objects #if defined(GL_ES_VERSION_2_0) @@ -275,19 +279,33 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n"; - if (theCtx->hasDrawBuffers) + if (myNbFragOutputs > 1) { - anExtensions += "#define OCC_ENABLE_draw_buffers\n"; - } - if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions) - { - if (theCtx->arbDrawBuffers) + if (theCtx->hasDrawBuffers) { - anExtensions += "#extension GL_ARB_draw_buffers : enable\n"; + anExtensions += "#define OCC_ENABLE_draw_buffers\n"; + if (myHasWeightOitOutput) + { + anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n"; + } } - else if (theCtx->extDrawBuffers) + else { - anExtensions += "#extension GL_EXT_draw_buffers : enable\n"; + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + "Error! Multiple draw buffers required by the program, but aren't supported by OpenGL"); + return Standard_False; + } + + if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions) + { + if (theCtx->arbDrawBuffers) + { + anExtensions += "#extension GL_ARB_draw_buffers : enable\n"; + } + else if (theCtx->extDrawBuffers) + { + anExtensions += "#extension GL_EXT_draw_buffers : enable\n"; + } } } @@ -334,6 +352,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0; aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n"; + aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n"; const TCollection_AsciiString aSource = aHeaderVer // #version - header defining GLSL version, should be first + (!aHeaderVer.IsEmpty() ? "\n" : "") diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 33d8e7d4be..86a239c4ea 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -226,6 +226,13 @@ public: //! to be used for initialization occClipPlaneEquations (OpenGl_OCC_CLIP_PLANE_EQUATIONS). Standard_Integer NbClipPlanesMax() const { return myNbClipPlanesMax; } + //! Return the length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS), + //! to be used for initialization occFragColorArray/occFragColorN. + Standard_Integer NbFragmentOutputs() const { return myNbFragOutputs; } + + //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default. + Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; } + private: //! Returns index of last modification of variables of specified state type. @@ -569,6 +576,8 @@ protected: Standard_Integer myShareCount; //!< program users count, initialized with 1 (already shared by one user) Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES) + Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) + Standard_Boolean myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage Standard_Boolean myHasTessShader; //!< flag indicating that program defines tessellation stage protected: diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index 929d9093d1..0f5ba703b8 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -24,6 +24,10 @@ //! Specifies the length of array of clipping planes, which is 8 by default. Defined by Shader Manager. // #define THE_MAX_CLIP_PLANES 8 +//! @def THE_NB_FRAG_OUTPUTS +//! Specifies the length of array of Fragment Shader outputs, which is 1 by default. Defined by Shader Manager. +// #define THE_NB_FRAG_OUTPUTS 1 + // compatibility macros #if (__VERSION__ >= 130) #define THE_ATTRIBUTE in @@ -58,20 +62,43 @@ #elif defined(FRAGMENT_SHADER) #if (__VERSION__ >= 130) #ifdef OCC_ENABLE_draw_buffers - out vec4 occFragColorArray[2]; - #define occFragColor occFragColorArray[0] - #define occFragCoverage occFragColorArray[1] + out vec4 occFragColorArray[THE_NB_FRAG_OUTPUTS]; + #define occFragColorArrayAlias occFragColorArray + #define occFragColor0 occFragColorArray[0] #else - out vec4 occFragColor; + out vec4 occFragColor0; #endif #else #ifdef OCC_ENABLE_draw_buffers - #define occFragColor gl_FragData[0] - #define occFragCoverage gl_FragData[1] + #define occFragColorArrayAlias gl_FragData + #define occFragColor0 gl_FragData[0] #else - #define occFragColor gl_FragColor + #define occFragColor0 gl_FragColor #endif #endif + + #if (THE_NB_FRAG_OUTPUTS >= 2) + #define occFragColor1 occFragColorArrayAlias[1] + #else + vec4 occFragColor1; + #endif + #if (THE_NB_FRAG_OUTPUTS >= 3) + #define occFragColor2 occFragColorArrayAlias[2] + #else + vec4 occFragColor2; + #endif + #if (THE_NB_FRAG_OUTPUTS >= 4) + #define occFragColor3 occFragColorArrayAlias[3] + #else + vec4 occFragColor3; + #endif + + // Built-in outputs notation + #define occFragColor occFragColor0 + #define occFragCoverage occFragColor1 + + //! Define the main Fragment Shader output - color value. + void occSetFragColor (in vec4 theColor); #endif // Matrix state diff --git a/src/Shaders/DeclarationsImpl.glsl b/src/Shaders/DeclarationsImpl.glsl index e13307e2ca..d3b16429f7 100644 --- a/src/Shaders/DeclarationsImpl.glsl +++ b/src/Shaders/DeclarationsImpl.glsl @@ -15,6 +15,21 @@ // This file includes implementation of common functions and properties accessors +#if defined(FRAGMENT_SHADER) +#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE) +//! Output color and coverage for accumulation by OIT algorithm. +void occSetFragColor (in vec4 theColor) +{ + float aWeight = theColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2); + occFragCoverage.r = theColor.a * aWeight; + occFragColor = vec4 (theColor.rgb * theColor.a * aWeight, theColor.a); +} +#else +//! Output color. +void occSetFragColor (in vec4 theColor) { occFragColor = theColor; } +#endif +#endif + #if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0) // arrays of light sources uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types diff --git a/src/Shaders/PhongShading.fs b/src/Shaders/PhongShading.fs index 15311c7446..d102812347 100755 --- a/src/Shaders/PhongShading.fs +++ b/src/Shaders/PhongShading.fs @@ -186,14 +186,6 @@ void main() } } - occFragColor = computeLighting (normalize (Normal), - normalize (View), - Position); - - if (occOitOutput != 0) - { - float aWeight = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2); - occFragCoverage.r = occFragColor.a * aWeight; - occFragColor = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a); - } + vec4 aColor = computeLighting (normalize (Normal), normalize (View), Position); + occSetFragColor (aColor); } diff --git a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx index 48e69b36b7..4ff75929a5 100644 --- a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx +++ b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx @@ -18,6 +18,21 @@ static const char Shaders_DeclarationsImpl_glsl[] = "\n" "// This file includes implementation of common functions and properties accessors\n" "\n" + "#if defined(FRAGMENT_SHADER)\n" + "#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE)\n" + "//! Output color and coverage for accumulation by OIT algorithm.\n" + "void occSetFragColor (in vec4 theColor)\n" + "{\n" + " float aWeight = theColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);\n" + " occFragCoverage.r = theColor.a * aWeight;\n" + " occFragColor = vec4 (theColor.rgb * theColor.a * aWeight, theColor.a);\n" + "}\n" + "#else\n" + "//! Output color.\n" + "void occSetFragColor (in vec4 theColor) { occFragColor = theColor; }\n" + "#endif\n" + "#endif\n" + "\n" "#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)\n" "// arrays of light sources\n" "uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types\n" diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index 46928f7e75..cec68050b4 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -27,6 +27,10 @@ static const char Shaders_Declarations_glsl[] = "//! Specifies the length of array of clipping planes, which is 8 by default. Defined by Shader Manager.\n" "// #define THE_MAX_CLIP_PLANES 8\n" "\n" + "//! @def THE_NB_FRAG_OUTPUTS\n" + "//! Specifies the length of array of Fragment Shader outputs, which is 1 by default. Defined by Shader Manager.\n" + "// #define THE_NB_FRAG_OUTPUTS 1\n" + "\n" "// compatibility macros\n" "#if (__VERSION__ >= 130)\n" " #define THE_ATTRIBUTE in\n" @@ -61,20 +65,43 @@ static const char Shaders_Declarations_glsl[] = "#elif defined(FRAGMENT_SHADER)\n" " #if (__VERSION__ >= 130)\n" " #ifdef OCC_ENABLE_draw_buffers\n" - " out vec4 occFragColorArray[2];\n" - " #define occFragColor occFragColorArray[0]\n" - " #define occFragCoverage occFragColorArray[1]\n" + " out vec4 occFragColorArray[THE_NB_FRAG_OUTPUTS];\n" + " #define occFragColorArrayAlias occFragColorArray\n" + " #define occFragColor0 occFragColorArray[0]\n" " #else\n" - " out vec4 occFragColor;\n" + " out vec4 occFragColor0;\n" " #endif\n" " #else\n" " #ifdef OCC_ENABLE_draw_buffers\n" - " #define occFragColor gl_FragData[0]\n" - " #define occFragCoverage gl_FragData[1]\n" + " #define occFragColorArrayAlias gl_FragData\n" + " #define occFragColor0 gl_FragData[0]\n" " #else\n" - " #define occFragColor gl_FragColor\n" + " #define occFragColor0 gl_FragColor\n" " #endif\n" " #endif\n" + "\n" + " #if (THE_NB_FRAG_OUTPUTS >= 2)\n" + " #define occFragColor1 occFragColorArrayAlias[1]\n" + " #else\n" + " vec4 occFragColor1;\n" + " #endif\n" + " #if (THE_NB_FRAG_OUTPUTS >= 3)\n" + " #define occFragColor2 occFragColorArrayAlias[2]\n" + " #else\n" + " vec4 occFragColor2;\n" + " #endif\n" + " #if (THE_NB_FRAG_OUTPUTS >= 4)\n" + " #define occFragColor3 occFragColorArrayAlias[3]\n" + " #else\n" + " vec4 occFragColor3;\n" + " #endif\n" + "\n" + " // Built-in outputs notation\n" + " #define occFragColor occFragColor0\n" + " #define occFragCoverage occFragColor1\n" + "\n" + " //! Define the main Fragment Shader output - color value.\n" + " void occSetFragColor (in vec4 theColor);\n" "#endif\n" "\n" "// Matrix state\n" diff --git a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx index 086ac826d8..e90d5b4b9d 100644 --- a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx +++ b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx @@ -736,7 +736,8 @@ static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/, const TCollection_AsciiString& aShaderSrc = aShader->Source(); const bool hasVertPos = aShaderSrc.Search ("gl_Position") != -1; - const bool hasFragColor = aShaderSrc.Search ("occFragColor") != -1 + const bool hasFragColor = aShaderSrc.Search ("occSetFragColor") != -1 + || aShaderSrc.Search ("occFragColor") != -1 || aShaderSrc.Search ("gl_FragColor") != -1 || aShaderSrc.Search ("gl_FragData") != -1; Graphic3d_TypeOfShaderObject aShaderType = aShaderTypeArg; @@ -768,6 +769,13 @@ static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/, } } + if (!aProgram.IsNull() + && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT) + { + aProgram->SetNbFragmentOutputs (2); + aProgram->SetWeightOitOutput (true); + } + ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS()); NCollection_Sequence::Iterator aPrsIter (aPrsList); const bool isGlobalList = aPrsList.IsEmpty();