diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index ed74f31a63..365f97f95e 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -127,6 +127,9 @@ Graphic3d_SequenceOfHClipPlane.hxx Graphic3d_SequenceOfStructure.hxx Graphic3d_ShaderAttribute.cxx Graphic3d_ShaderAttribute.hxx +Graphic3d_ShaderFlags.hxx +Graphic3d_ShaderManager.cxx +Graphic3d_ShaderManager.hxx Graphic3d_ShaderObject.cxx Graphic3d_ShaderObject.hxx Graphic3d_ShaderProgram.cxx diff --git a/src/Graphic3d/Graphic3d_ShaderFlags.hxx b/src/Graphic3d/Graphic3d_ShaderFlags.hxx new file mode 100644 index 0000000000..125155d212 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderFlags.hxx @@ -0,0 +1,45 @@ +// Created on: 2014-10-08 +// Created by: Kirill Gavrilov +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_ShaderFlags_HeaderFile +#define _Graphic3d_ShaderFlags_HeaderFile + +//! Standard GLSL program combination bits. +enum Graphic3d_ShaderFlags +{ + Graphic3d_ShaderFlags_VertColor = 0x0001, //!< per-vertex color + Graphic3d_ShaderFlags_TextureRGB = 0x0002, //!< handle RGB texturing + Graphic3d_ShaderFlags_TextureEnv = 0x0004, //!< handle environment map (obsolete, to be removed) + Graphic3d_ShaderFlags_TextureNormal = Graphic3d_ShaderFlags_TextureRGB|Graphic3d_ShaderFlags_TextureEnv, //!< extended texture set (with normal map) + Graphic3d_ShaderFlags_PointSimple = 0x0008, //!< point marker without sprite + Graphic3d_ShaderFlags_PointSprite = 0x0010, //!< point sprite with RGB image + Graphic3d_ShaderFlags_PointSpriteA = Graphic3d_ShaderFlags_PointSimple|Graphic3d_ShaderFlags_PointSprite, //!< point sprite with Alpha image + Graphic3d_ShaderFlags_StippleLine = 0x0020, //!< stipple line + Graphic3d_ShaderFlags_ClipPlanes1 = 0x0040, //!< handle 1 clipping plane + Graphic3d_ShaderFlags_ClipPlanes2 = 0x0080, //!< handle 2 clipping planes + Graphic3d_ShaderFlags_ClipPlanesN = Graphic3d_ShaderFlags_ClipPlanes1|Graphic3d_ShaderFlags_ClipPlanes2, //!< handle N clipping planes + Graphic3d_ShaderFlags_ClipChains = 0x0100, //!< handle chains of clipping planes + Graphic3d_ShaderFlags_MeshEdges = 0x0200, //!< draw mesh edges (wireframe) + Graphic3d_ShaderFlags_AlphaTest = 0x0400, //!< discard fragment by alpha test (defined by cutoff value) + Graphic3d_ShaderFlags_WriteOit = 0x0800, //!< write coverage buffer for Blended Order-Independent Transparency + Graphic3d_ShaderFlags_OitDepthPeeling = 0x1000, //!< handle Depth Peeling OIT + // + Graphic3d_ShaderFlags_NB = 0x2000, //!< overall number of combinations + Graphic3d_ShaderFlags_IsPoint = Graphic3d_ShaderFlags_PointSimple|Graphic3d_ShaderFlags_PointSprite|Graphic3d_ShaderFlags_PointSpriteA, + Graphic3d_ShaderFlags_HasTextures = Graphic3d_ShaderFlags_TextureRGB|Graphic3d_ShaderFlags_TextureEnv, + Graphic3d_ShaderFlags_NeedsGeomShader = Graphic3d_ShaderFlags_MeshEdges, +}; + +#endif // _Graphic3d_ShaderFlags_HeaderFile diff --git a/src/Graphic3d/Graphic3d_ShaderManager.cxx b/src/Graphic3d/Graphic3d_ShaderManager.cxx new file mode 100644 index 0000000000..705d0b3122 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderManager.cxx @@ -0,0 +1,2114 @@ +// Copyright (c) 2013-2021 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +#include "../Shaders/Shaders_DirectionalLightShadow_glsl.pxx" +#include "../Shaders/Shaders_PBRDistribution_glsl.pxx" +#include "../Shaders/Shaders_PBRDirectionalLight_glsl.pxx" +#include "../Shaders/Shaders_PBRGeometry_glsl.pxx" +#include "../Shaders/Shaders_PBRFresnel_glsl.pxx" +#include "../Shaders/Shaders_PBRCookTorrance_glsl.pxx" +#include "../Shaders/Shaders_PBRIllumination_glsl.pxx" +#include "../Shaders/Shaders_PBRPointLight_glsl.pxx" +#include "../Shaders/Shaders_PBRSpotLight_glsl.pxx" +#include "../Shaders/Shaders_PBREnvBaking_fs.pxx" +#include "../Shaders/Shaders_PBREnvBaking_vs.pxx" +#include "../Shaders/Shaders_PhongDirectionalLight_glsl.pxx" +#include "../Shaders/Shaders_PhongPointLight_glsl.pxx" +#include "../Shaders/Shaders_PhongSpotLight_glsl.pxx" +#include "../Shaders/Shaders_PointLightAttenuation_glsl.pxx" +#include "../Shaders/Shaders_TangentSpaceNormal_glsl.pxx" + +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderManager, Standard_Transient) + +namespace +{ + //! Number specifying maximum number of light sources to prepare a GLSL program with unrolled loop. + const Standard_Integer THE_NB_UNROLLED_LIGHTS_MAX = 32; + + //! Compute the size of array storing holding light sources definition. + static Standard_Integer roundUpMaxLightSources (Standard_Integer theNbLights) + { + Standard_Integer aMaxLimit = THE_NB_UNROLLED_LIGHTS_MAX; + for (; aMaxLimit < theNbLights; aMaxLimit *= 2) {} + return aMaxLimit; + } + +#define EOL "\n" + +//! Compute TexCoord value in Vertex Shader +const char THE_VARY_TexCoord_Trsf[] = + EOL" float aRotSin = occTextureTrsf_RotationSin();" + EOL" float aRotCos = occTextureTrsf_RotationCos();" + EOL" vec2 aTex2 = vec2 (occTexCoord.x * aRotCos - occTexCoord.y * aRotSin," + EOL" occTexCoord.x * aRotSin + occTexCoord.y * aRotCos);" + EOL" aTex2 = (aTex2 + occTextureTrsf_Translation()) * occTextureTrsf_Scale();" + EOL" TexCoord = vec4(aTex2, occTexCoord.zw);"; + +//! Auxiliary function to flip gl_PointCoord vertically +#define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)" + +//! Auxiliary function to transform normal from model to view coordinate system. +const char THE_FUNC_transformNormal_view[] = + EOL"vec3 transformNormal (in vec3 theNormal)" + EOL"{" + EOL" vec4 aResult = occWorldViewMatrixInverseTranspose" + EOL" * occModelWorldMatrixInverseTranspose" + EOL" * vec4 (theNormal, 0.0);" + EOL" return normalize (aResult.xyz);" + EOL"}"; + +//! The same function as THE_FUNC_transformNormal but is used in PBR pipeline. +//! The normals are expected to be in world coordinate system in PBR pipeline. +const char THE_FUNC_transformNormal_world[] = + EOL"vec3 transformNormal (in vec3 theNormal)" + EOL"{" + EOL" vec4 aResult = occModelWorldMatrixInverseTranspose" + EOL" * vec4 (theNormal, 0.0);" + EOL" return normalize (aResult.xyz);" + EOL"}"; + +//! Global shader variable for color definition with lighting enabled. +const char THE_FUNC_lightDef[] = + EOL"vec3 Ambient;" //!< Ambient contribution of light sources + EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources + EOL"vec3 Specular;"; //!< Specular contribution of light sources + +//! Global shader variable for color definition with lighting enabled. +const char THE_FUNC_PBR_lightDef[] = + EOL"vec3 DirectLighting;" //!< Accumulator of direct lighting from light sources + EOL"vec4 BaseColor;" //!< Base color (albedo) of material for PBR + EOL"float Metallic;" //!< Metallic coefficient of material + EOL"float NormalizedRoughness;" //!< Normalized roughness coefficient of material + EOL"float Roughness;" //!< Roughness coefficient of material + EOL"vec3 Emission;" //!< Light intensity emitted by material + EOL"float IOR;"; //!< Material's index of refraction + +//! The same as Shaders_PhongDirectionalLight_glsl 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" in float theShadow)" + EOL"{" + EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (0), 0.0));" + 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 += occLight_Diffuse(0) * aNdotL * theShadow;" + EOL" Specular += occLight_Specular(0) * aSpecl * theShadow;" + EOL"}"; + +//! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip. +const char THE_FUNC_cubemap_vector_transform[] = + EOL"vec3 cubemapVectorTransform (in vec3 theVector," + EOL" in int theYCoeff," + EOL" in int theZCoeff)" + EOL"{" + EOL" theVector = theVector.yzx;" + EOL" theVector.y *= float(theYCoeff);" + EOL" theVector.z *= float(theZCoeff);" + EOL" return theVector;" + EOL"}"; + +//! Process clipping planes in Fragment Shader. +//! Should be added at the beginning of the main() function. +const char THE_FRAG_CLIP_PLANES_N[] = + EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)" + EOL" {" + EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];" + EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)" + EOL" {" + EOL" discard;" + EOL" }" + EOL" }"; + +//! Process chains of clipping planes in Fragment Shader. +const char THE_FRAG_CLIP_CHAINS_N[] = +EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)" +EOL" {" +EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];" +EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)" +EOL" {" +EOL" if (occClipPlaneChains[aPlaneIter] == 1)" +EOL" {" +EOL" discard;" +EOL" }" +EOL" aPlaneIter += 1;" +EOL" }" +EOL" else" +EOL" {" +EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];" +EOL" }" +EOL" }"; + +//! Process 1 clipping plane in Fragment Shader. +const char THE_FRAG_CLIP_PLANES_1[] = + EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];" + EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)" + EOL" {" + EOL" discard;" + EOL" }"; + +//! Process 2 clipping planes in Fragment Shader. +const char THE_FRAG_CLIP_PLANES_2[] = + EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];" + EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];" + EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0" + EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)" + EOL" {" + EOL" discard;" + EOL" }"; + +//! Process a chain of 2 clipping planes in Fragment Shader (3/4 section). +const char THE_FRAG_CLIP_CHAINS_2[] = +EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];" +EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];" +EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0" +EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)" +EOL" {" +EOL" discard;" +EOL" }"; + +//! Modify color for Wireframe presentation. +const char THE_FRAG_WIREFRAME_COLOR[] = +EOL"vec4 getFinalColor(void)" +EOL"{" +EOL" float aDistance = min (min (EdgeDistance[0], EdgeDistance[1]), EdgeDistance[2]);" +EOL" bool isHollow = occWireframeColor.a < 0.0;" +EOL" float aMixVal = smoothstep (occLineWidth - occLineFeather * 0.5, occLineWidth + occLineFeather * 0.5, aDistance);" +EOL" vec4 aMixColor = isHollow" +EOL" ? vec4 (getColor().rgb, 1.0 - aMixVal)" // edges only (of interior color) +EOL" : mix (occWireframeColor, getColor(), aMixVal);" // interior + edges +EOL" return aMixColor;" +EOL"}"; + +//! Compute gl_Position vertex shader output. +const char THE_VERT_gl_Position[] = +EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"; + +//! Displace gl_Position alongside vertex normal for outline rendering. +//! This code adds silhouette only for smooth surfaces of closed primitive, and produces visual artifacts on sharp edges. +const char THE_VERT_gl_Position_OUTLINE[] = +EOL" float anOutlineDisp = occOrthoScale > 0.0 ? occOrthoScale : gl_Position.w;" +EOL" vec4 anOutlinePos = occVertex + vec4 (occNormal * (occSilhouetteThickness * anOutlineDisp), 0.0);" +EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * anOutlinePos;"; + +} + +// ======================================================================= +// function : genLightKey +// purpose : +// ======================================================================= +TCollection_AsciiString Graphic3d_ShaderManager::genLightKey (const Handle(Graphic3d_LightSet)& theLights, + const bool theHasShadowMap) const +{ + if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX) + { + return theHasShadowMap + ? TCollection_AsciiString ("ls_") + theLights->KeyEnabledLong() + : TCollection_AsciiString ("l_") + theLights->KeyEnabledLong(); + } + + const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled()); + return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit; +} + +// ======================================================================= +// function : Graphic3d_ShaderManager +// purpose : +// ======================================================================= +Graphic3d_ShaderManager::Graphic3d_ShaderManager (Aspect_GraphicsLibrary theGapi) +: myGapi (theGapi), + // desktop defines a dedicated API for point size, with gl_PointSize added later to GLSL + myHasFlatShading (true), + myToReverseDFdxSign (false), + mySetPointSize (myGapi == Aspect_GraphicsLibrary_OpenGLES), + myUseRedAlpha (false), + myToEmulateDepthClamp (true), + mySRgbState (true) +{ + memset (myGlslExtensions, 0, sizeof(myGlslExtensions)); +} + +// ======================================================================= +// function : ~Graphic3d_ShaderManager +// purpose : +// ======================================================================= +Graphic3d_ShaderManager::~Graphic3d_ShaderManager() +{ + // +} + +// ======================================================================= +// function : hasGlslBitwiseOps +// purpose : +// ======================================================================= +bool Graphic3d_ShaderManager::hasGlslBitwiseOps() const +{ + switch (myGapi) + { + case Aspect_GraphicsLibrary_OpenGL: + { + return IsGapiGreaterEqual (3, 0) + || myGlslExtensions[Graphic3d_GlslExtension_GL_EXT_gpu_shader4]; + } + case Aspect_GraphicsLibrary_OpenGLES: + { + return IsGapiGreaterEqual (3, 0); + } + } + return false; +} + +// ======================================================================= +// function : defaultGlslVersion +// purpose : +// ======================================================================= +int Graphic3d_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, + const TCollection_AsciiString& theName, + int theBits, + bool theUsesDerivates) const +{ + int aBits = theBits; + const bool toUseDerivates = theUsesDerivates + || (theBits & Graphic3d_ShaderFlags_StippleLine) != 0 + || (theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureNormal; + switch (myGapi) + { + case Aspect_GraphicsLibrary_OpenGL: + { + if (IsGapiGreaterEqual (3, 2)) + { + theProgram->SetHeader ("#version 150"); + } + else + { + // TangentSpaceNormal() function uses mat2x3 type + const bool toUseMat2x3 = (theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureNormal; + // gl_PointCoord has been added since GLSL 1.2 + const bool toUsePointCoord = (theBits & Graphic3d_ShaderFlags_PointSprite) != 0; + if (toUseMat2x3 || toUsePointCoord) + { + if (IsGapiGreaterEqual (2, 1)) + { + theProgram->SetHeader ("#version 120"); + } + } + if ((theBits & Graphic3d_ShaderFlags_StippleLine) != 0 + || theProgram->IsPBR()) + { + if (IsGapiGreaterEqual (3, 0)) + { + theProgram->SetHeader ("#version 130"); + } + else if (myGlslExtensions[Graphic3d_GlslExtension_GL_EXT_gpu_shader4]) + { + // GL_EXT_gpu_shader4 defines GLSL type "unsigned int", while core GLSL specs define type "uint" + theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable\n" + "#define uint unsigned int"); + } + } + } + (void )toUseDerivates; + break; + } + case Aspect_GraphicsLibrary_OpenGLES: + { + #if defined(__EMSCRIPTEN__) + if (IsGapiGreaterEqual (3, 0)) + { + // consider this is browser responsibility to provide working WebGL 2.0 implementation + // and black-list broken drivers (there is no OpenGL ES greater than 3.0) + theProgram->SetHeader ("#version 300 es"); + } + #endif + // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es") + // and "300 es" on OpenGL ES 3.1+ devices + if (IsGapiGreaterEqual (3, 1)) + { + if ((theBits & Graphic3d_ShaderFlags_NeedsGeomShader) != 0) + { + theProgram->SetHeader (IsGapiGreaterEqual (3, 2) ? "#version 320 es" : "#version 310 es"); + } + else + { + theProgram->SetHeader ("#version 300 es"); + } + } + else + { + TCollection_AsciiString aGles2Extensions; + if (theProgram->IsPBR()) + { + if (IsGapiGreaterEqual (3, 0)) + { + theProgram->SetHeader ("#version 300 es"); + } + else if (myGlslExtensions[Graphic3d_GlslExtension_GL_EXT_shader_texture_lod]) + { + aGles2Extensions += "#extension GL_EXT_shader_texture_lod : enable\n" + "#define textureCubeLod textureCubeLodEXT\n"; + } + } + if ((theBits & Graphic3d_ShaderFlags_WriteOit) != 0 + || (theBits & Graphic3d_ShaderFlags_OitDepthPeeling) != 0 + || (theBits & Graphic3d_ShaderFlags_StippleLine) != 0) + { + if (IsGapiGreaterEqual (3, 0)) + { + theProgram->SetHeader ("#version 300 es"); + } + else + { + aBits = aBits & ~Graphic3d_ShaderFlags_WriteOit; + aBits = aBits & ~Graphic3d_ShaderFlags_OitDepthPeeling; + if (!myGlslExtensions[Graphic3d_GlslExtension_GL_OES_standard_derivatives]) + { + aBits = aBits & ~Graphic3d_ShaderFlags_StippleLine; + } + } + } + if (toUseDerivates) + { + if (IsGapiGreaterEqual (3, 0)) + { + theProgram->SetHeader ("#version 300 es"); + } + else if (myGlslExtensions[Graphic3d_GlslExtension_GL_OES_standard_derivatives]) + { + aGles2Extensions += "#extension GL_OES_standard_derivatives : enable\n"; + } + } + + if (!aGles2Extensions.IsEmpty()) + { + theProgram->SetHeader (aGles2Extensions); + } + } + break; + } + } + + // should fit Graphic3d_ShaderFlags_NB + char aBitsStr[64]; + Sprintf (aBitsStr, "%04x", aBits); + theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr); + return aBits; +} + +// ======================================================================= +// function : defaultOitGlslVersion +// purpose : +// ======================================================================= +void Graphic3d_ShaderManager::defaultOitGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, + const TCollection_AsciiString& theName, + bool theMsaa) const +{ + switch (myGapi) + { + case Aspect_GraphicsLibrary_OpenGL: + { + if (theMsaa) + { + if (IsGapiGreaterEqual (4, 0)) + { + theProgram->SetHeader ("#version 400"); + } + } + else + { + if (IsGapiGreaterEqual (3, 2)) + { + theProgram->SetHeader ("#version 150"); + } + } + break; + } + case Aspect_GraphicsLibrary_OpenGLES: + { + if (theMsaa) + { + if (IsGapiGreaterEqual (3, 2)) + { + theProgram->SetHeader ("#version 320 es"); + } + else if (IsGapiGreaterEqual (3, 0)) + { + theProgram->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension + } + } + else + { + if (IsGapiGreaterEqual (3, 0)) + { + theProgram->SetHeader ("#version 300 es"); + } + } + break; + } + } + theProgram->SetId (TCollection_AsciiString ("occt_") + theName + (theMsaa ? "_msaa" : "")); +} + +// ======================================================================= +// function : getStdProgramFont +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramFont() const +{ + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aUniforms .Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + + TCollection_AsciiString aSrcVert = TCollection_AsciiString() + + EOL"void main()" + EOL"{" + EOL" TexCoord = occTexCoord.st;" + + THE_VERT_gl_Position + + EOL"}"; + + TCollection_AsciiString + aSrcGetAlpha = myUseRedAlpha + ? EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }" + : EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }"; + + TCollection_AsciiString aSrcFrag = + aSrcGetAlpha + + EOL"void main()" + EOL"{" + EOL" vec4 aColor = occColor;" + EOL" aColor.a *= getAlpha();" + EOL" if (aColor.a <= 0.285) discard;" + EOL" occSetFragColor (aColor);" + EOL"}"; + + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + defaultGlslVersion (aProgramSrc, "font", 0); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getStdProgramFboBlit +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramFboBlit (Standard_Integer theNbSamples, + Standard_Boolean theIsFallback_sRGB) const +{ + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + + TCollection_AsciiString aSrcVert = + EOL"void main()" + EOL"{" + EOL" TexCoord = occVertex.zw;" + EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);" + EOL"}"; + + TCollection_AsciiString aSrcFrag; + if (theNbSamples > 1) + { + if (myGapi == Aspect_GraphicsLibrary_OpenGLES) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("highp sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("highp sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT)); + } + else + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT)); + } + + aSrcFrag = TCollection_AsciiString() + + EOL"#define THE_NUM_SAMPLES " + theNbSamples + + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "") + + EOL"void main()" + EOL"{" + EOL" ivec2 aSize = textureSize (uColorSampler);" + EOL" ivec2 anUV = ivec2 (vec2 (aSize) * TexCoord);" + EOL" gl_FragDepth = texelFetch (uDepthSampler, anUV, THE_NUM_SAMPLES / 2 - 1).r;" + EOL + EOL" vec4 aColor = vec4 (0.0);" + EOL" for (int aSample = 0; aSample < THE_NUM_SAMPLES; ++aSample)" + EOL" {" + EOL" vec4 aVal = texelFetch (uColorSampler, anUV, aSample);" + EOL" aColor += aVal;" + EOL" }" + EOL" aColor /= float(THE_NUM_SAMPLES);" + EOL"#ifdef THE_SHIFT_sRGB" + EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));" + EOL"#endif" + EOL" occSetFragColor (aColor);" + EOL"}"; + } + else + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D uColorSampler", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D uDepthSampler", Graphic3d_TOS_FRAGMENT)); + aSrcFrag = TCollection_AsciiString() + + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "") + + EOL"void main()" + EOL"{" + EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;" + EOL" vec4 aColor = occTexture2D (uColorSampler, TexCoord);" + EOL"#ifdef THE_SHIFT_sRGB" + EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));" + EOL"#endif" + EOL" occSetFragColor (aColor);" + EOL"}"; + } + + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + switch (myGapi) + { + case Aspect_GraphicsLibrary_OpenGL: + { + if (IsGapiGreaterEqual (3, 2)) + { + aProgramSrc->SetHeader ("#version 150"); + } + break; + } + case Aspect_GraphicsLibrary_OpenGLES: + { + if (IsGapiGreaterEqual (3, 1)) + { + // required for MSAA sampler + aProgramSrc->SetHeader ("#version 310 es"); + } + else if (IsGapiGreaterEqual (3, 0)) + { + aProgramSrc->SetHeader ("#version 300 es"); + } + else if (myGlslExtensions[Graphic3d_GlslExtension_GL_EXT_frag_depth]) + { + aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable" + EOL"#define gl_FragDepth gl_FragDepthEXT"); + } + else + { + // there is no way to draw into depth buffer + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));" + EOL"}"; + } + break; + } + } + + TCollection_AsciiString anId = "occt_blit"; + if (theNbSamples > 1) + { + anId += TCollection_AsciiString ("_msaa") + theNbSamples; + } + if (theIsFallback_sRGB) + { + anId += "_gamma"; + } + aProgramSrc->SetId (anId); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getStdProgramOitCompositing +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramOitCompositing (const Standard_Boolean theMsaa) const +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + TCollection_AsciiString aSrcVert, aSrcFrag; + + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + + aSrcVert = + EOL"void main()" + EOL"{" + EOL" TexCoord = occVertex.zw;" + EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);" + EOL"}"; + + if (!theMsaa) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT)); + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);" + EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;" + EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));" + EOL"}"; + } + else + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT)); + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);" + EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);" + EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;" + EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));" + EOL"}"; + } + defaultOitGlslVersion (aProgramSrc, "weight_oit", theMsaa); + + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getStdProgramOitDepthPeelingBlend +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramOitDepthPeelingBlend (Standard_Boolean theMsaa) const +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + TCollection_AsciiString aSrcVert, aSrcFrag; + + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aSrcVert = + EOL"void main()" + EOL"{" + EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);" + EOL"}"; + + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable (theMsaa + ? "sampler2DMS uDepthPeelingBackColor" + : "sampler2D uDepthPeelingBackColor", Graphic3d_TOS_FRAGMENT)); + aSrcFrag = TCollection_AsciiString() + + EOL"void main()" + EOL"{" + EOL" #define THE_SAMPLE_ID " + (theMsaa ? "gl_SampleID" : "0") + + EOL" occFragColor = texelFetch (uDepthPeelingBackColor, ivec2 (gl_FragCoord.xy), THE_SAMPLE_ID);" + EOL" if (occFragColor.a == 0.0) { discard; }" + EOL"}"; + + defaultOitGlslVersion (aProgramSrc, "oit_peeling_blend", theMsaa); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getStdProgramOitDepthPeelingFlush +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramOitDepthPeelingFlush (Standard_Boolean theMsaa) const +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + TCollection_AsciiString aSrcVert, aSrcFrag; + + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aSrcVert = + EOL"void main()" + EOL"{" + EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);" + EOL"}"; + + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable (theMsaa + ? "sampler2DMS uDepthPeelingFrontColor" + : "sampler2D uDepthPeelingFrontColor", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable (theMsaa + ? "sampler2DMS uDepthPeelingBackColor" + : "sampler2D uDepthPeelingBackColor", Graphic3d_TOS_FRAGMENT)); + aSrcFrag = TCollection_AsciiString() + + EOL"void main()" + EOL"{" + EOL" #define THE_SAMPLE_ID " + (theMsaa ? "gl_SampleID" : "0") + + EOL" ivec2 aFragCoord = ivec2 (gl_FragCoord.xy);" + EOL" vec4 aFrontColor = texelFetch (uDepthPeelingFrontColor, aFragCoord, THE_SAMPLE_ID);" + EOL" vec4 aBackColor = texelFetch (uDepthPeelingBackColor, aFragCoord, THE_SAMPLE_ID);" + EOL" float anAlphaMult = 1.0 - aFrontColor.a;" + EOL" occFragColor = vec4 (aFrontColor.rgb + anAlphaMult * aBackColor.rgb, aFrontColor.a + aBackColor.a);" + EOL"}"; + + defaultOitGlslVersion (aProgramSrc, "oit_peeling_flush", theMsaa); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : pointSpriteAlphaSrc +// purpose : +// ======================================================================= +TCollection_AsciiString Graphic3d_ShaderManager::pointSpriteAlphaSrc (Standard_Integer theBits) const +{ + const bool isAlpha = (theBits & Graphic3d_ShaderFlags_PointSpriteA) == Graphic3d_ShaderFlags_PointSpriteA; + return isAlpha && myUseRedAlpha + ? EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").r; }" + : EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").a; }"; +} + +// ======================================================================= +// function : pointSpriteShadingSrc +// purpose : +// ======================================================================= +TCollection_AsciiString Graphic3d_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc, + Standard_Integer theBits) const +{ + TCollection_AsciiString aSrcFragGetColor; + if ((theBits & Graphic3d_ShaderFlags_PointSpriteA) == Graphic3d_ShaderFlags_PointSpriteA) + { + aSrcFragGetColor = pointSpriteAlphaSrc (theBits) + + EOL"vec4 getColor(void)" + EOL"{" + EOL" vec4 aColor = " + theBaseColorSrc + ";" + EOL" aColor.a = getAlpha();" + EOL" if (aColor.a <= 0.1) discard;" + EOL" return aColor;" + EOL"}"; + } + else if ((theBits & Graphic3d_ShaderFlags_PointSprite) == Graphic3d_ShaderFlags_PointSprite) + { + aSrcFragGetColor = TCollection_AsciiString() + + EOL"vec4 getColor(void)" + EOL"{" + EOL" vec4 aColor = " + theBaseColorSrc + ";" + EOL" aColor = occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ") * aColor;" + EOL" if (aColor.a <= 0.1) discard;" + EOL" return aColor;" + EOL"}"; + } + + return aSrcFragGetColor; +} + +//! Prepare GLSL source for geometry shader according to parameters. +static TCollection_AsciiString prepareGeomMainSrc (Graphic3d_ShaderObject::ShaderVariableList& theUnifoms, + Graphic3d_ShaderObject::ShaderVariableList& theStageInOuts, + Standard_Integer theBits) +{ + if ((theBits & Graphic3d_ShaderFlags_NeedsGeomShader) == 0) + { + return TCollection_AsciiString(); + } + + TCollection_AsciiString aSrcMainGeom = + EOL"void main()" + EOL"{"; + + if ((theBits & Graphic3d_ShaderFlags_MeshEdges) != 0) + { + theUnifoms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY)); + theUnifoms.Append (Graphic3d_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY)); + theUnifoms.Append (Graphic3d_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY)); + theUnifoms.Append (Graphic3d_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT)); + theUnifoms.Append (Graphic3d_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT)); + theUnifoms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT)); + theStageInOuts.Append(Graphic3d_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT)); + + aSrcMainGeom = TCollection_AsciiString() + + EOL"vec3 ViewPortTransform (vec4 theVec)" + EOL"{" + EOL" vec3 aWinCoord = theVec.xyz / theVec.w;" + EOL" aWinCoord = aWinCoord * 0.5 + 0.5;" + EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;" + EOL" return aWinCoord;" + EOL"}" + + aSrcMainGeom + + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);" + EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);" + EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);" + EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);" + EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));" + EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;" + EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance + EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;"; + } + + for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter) + { + const TCollection_AsciiString aVertIndex (aVertIter); + // pass variables from Vertex shader to Fragment shader through Geometry shader + for (Graphic3d_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next()) + { + if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)) + { + const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2); + if (aVarName.Value (aVarName.Length()) == ']') + { + // copy the whole array + const TCollection_AsciiString aVarName2 = aVarName.Token ("[", 1); + aSrcMainGeom += TCollection_AsciiString() + + EOL" geomOut." + aVarName2 + " = geomIn[" + aVertIndex + "]." + aVarName2 + ";"; + } + else + { + aSrcMainGeom += TCollection_AsciiString() + + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";"; + } + } + } + + if ((theBits & Graphic3d_ShaderFlags_MeshEdges) != 0) + { + switch (aVertIter) + { + case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break; + case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break; + case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break; + } + } + aSrcMainGeom += TCollection_AsciiString() + + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;" + EOL" EmitVertex();"; + } + aSrcMainGeom += + EOL" EndPrimitive();" + EOL"}"; + + return aSrcMainGeom; +} + +// ======================================================================= +// function : getStdProgramUnlit +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramUnlit (Standard_Integer theBits, + Standard_Boolean theIsOutline) const +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain; + TCollection_AsciiString aSrcFrag, aSrcFragExtraMain; + TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }"; + TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());"; + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + + if ((theBits & Graphic3d_ShaderFlags_IsPoint) != 0) + { + if (mySetPointSize) + { + aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; + } + + if ((theBits & Graphic3d_ShaderFlags_PointSprite) != 0) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); + if ((theBits & Graphic3d_ShaderFlags_PointSpriteA) != Graphic3d_ShaderFlags_PointSpriteA) + { + aSrcFragGetColor = + EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }"; + } + else if ((theBits & Graphic3d_ShaderFlags_TextureRGB) != 0 + && (theBits & Graphic3d_ShaderFlags_VertColor) == 0) + { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); + aUniforms .Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += + EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; + aSrcFragGetColor = + EOL"vec4 getColor(void) { return VertColor; }"; + } + + aSrcGetAlpha = pointSpriteAlphaSrc (theBits); + aSrcFragMainGetColor = + EOL" vec4 aColor = getColor();" + EOL" aColor.a = getAlpha();" + EOL" if (aColor.a <= 0.1) discard;" + EOL" occSetFragColor (aColor);"; + } + else + { + if ((theBits & Graphic3d_ShaderFlags_TextureRGB) != 0 + && (theBits & Graphic3d_ShaderFlags_VertColor) == 0) + { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); + aUniforms .Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += + EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; + aSrcFragGetColor = + EOL"vec4 getColor(void) { return VertColor; }"; + } + + aSrcFragMainGetColor = + EOL" vec4 aColor = getColor();" + EOL" if (aColor.a <= 0.1) discard;" + EOL" occSetFragColor (aColor);"; + } + } + else + { + if ((theBits & Graphic3d_ShaderFlags_HasTextures) != 0) + { + aUniforms .Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + + if ((theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureEnv) + { + aSrcVertExtraFunc = THE_FUNC_transformNormal_view; + + aSrcVertExtraMain += + EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;" + EOL" vec3 aNormal = transformNormal (occNormal);" + EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);" + EOL" aReflect.z += 1.0;" + EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);"; + + aSrcFragGetColor = + EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }"; + } + else + { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); + aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; + + aSrcFragGetColor = + EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }"; + } + } + } + if ((theBits & Graphic3d_ShaderFlags_VertColor) != 0) + { + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += EOL" VertColor = occVertColor;"; + aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }"; + } + + int aNbClipPlanes = 0; + if ((theBits & Graphic3d_ShaderFlags_ClipPlanesN) != 0) + { + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += + EOL" PositionWorld = occModelWorldMatrix * occVertex;" + EOL" Position = occWorldViewMatrix * PositionWorld;"; + + if ((theBits & Graphic3d_ShaderFlags_ClipPlanesN) == Graphic3d_ShaderFlags_ClipPlanesN) + { + aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT; + aSrcFragExtraMain += (theBits & Graphic3d_ShaderFlags_ClipChains) != 0 + ? THE_FRAG_CLIP_CHAINS_N + : THE_FRAG_CLIP_PLANES_N; + } + else if ((theBits & Graphic3d_ShaderFlags_ClipPlanes1) != 0) + { + aNbClipPlanes = 1; + aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1; + } + else if ((theBits & Graphic3d_ShaderFlags_ClipPlanes2) != 0) + { + aNbClipPlanes = 2; + aSrcFragExtraMain += (theBits & Graphic3d_ShaderFlags_ClipChains) != 0 + ? THE_FRAG_CLIP_CHAINS_2 + : THE_FRAG_CLIP_PLANES_2; + } + } + if ((theBits & Graphic3d_ShaderFlags_OitDepthPeeling) != 0) + { + aProgramSrc->SetNbFragmentOutputs (3); + aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT); + } + else if ((theBits & Graphic3d_ShaderFlags_WriteOit) != 0) + { + aProgramSrc->SetNbFragmentOutputs (2); + aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT); + } + + if (theIsOutline) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("float occOrthoScale", Graphic3d_TOS_VERTEX)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("float occSilhouetteThickness", Graphic3d_TOS_VERTEX)); + aSrcVertEndMain = THE_VERT_gl_Position_OUTLINE; + } + else if ((theBits & Graphic3d_ShaderFlags_StippleLine) != 0) + { + const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits); + if ((aBits & Graphic3d_ShaderFlags_StippleLine) != 0) + { + if (hasGlslBitwiseOps()) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("int occStipplePattern", Graphic3d_TOS_FRAGMENT)); + } + else + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("bool occStipplePattern[16]", Graphic3d_TOS_FRAGMENT)); + } + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("float occStippleFactor", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_VERTEX)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertEndMain = + EOL" vec2 aPosition = gl_Position.xy / gl_Position.w;" + EOL" aPosition = aPosition * 0.5 + 0.5;" + EOL" ScreenSpaceCoord = aPosition.xy * occViewport.zw + occViewport.xy;"; + aSrcFragMainGetColor = TCollection_AsciiString() + + EOL" vec2 anAxis = vec2 (0.0, 1.0);" + EOL" if (abs (dFdx (ScreenSpaceCoord.x)) - abs (dFdy (ScreenSpaceCoord.y)) > 0.001)" + EOL" {" + EOL" anAxis = vec2 (1.0, 0.0);" + EOL" }" + EOL" float aRotatePoint = dot (gl_FragCoord.xy, anAxis);" + + (hasGlslBitwiseOps() + ? EOL" uint aBit = uint (floor (aRotatePoint / occStippleFactor + 0.5)) & 15U;" + EOL" if ((uint (occStipplePattern) & (1U << aBit)) == 0U) discard;" + : EOL" int aBit = int (mod (floor (aRotatePoint / occStippleFactor + 0.5), 16.0));" + EOL" if (!occStipplePattern[aBit]) discard;") + + EOL" vec4 aColor = getFinalColor();" + EOL" if (aColor.a <= 0.1) discard;" + EOL" occSetFragColor (aColor);"; + } + else + { + Message::SendWarning ("Warning: stipple lines in GLSL will be ignored"); + } + } + + aSrcVert = + aSrcVertExtraFunc + + EOL"void main()" + EOL"{" + + aSrcVertExtraMain + + THE_VERT_gl_Position + + aSrcVertEndMain + + EOL"}"; + + TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits); + aSrcFragGetColor += (theBits & Graphic3d_ShaderFlags_MeshEdges) != 0 + ? THE_FRAG_WIREFRAME_COLOR + : EOL"#define getFinalColor getColor"; + + aSrcFrag = + aSrcFragGetColor + + aSrcGetAlpha + + EOL"void main()" + EOL"{" + EOL" if (occFragEarlyReturn()) { return; }" + + aSrcFragExtraMain + + aSrcFragMainGetColor + + EOL"}"; + + defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); + aProgramSrc->SetAlphaTest ((theBits & Graphic3d_ShaderFlags_AlphaTest) != 0); + const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + return aProgramSrc; +} + +// ======================================================================= +// function : stdComputeLighting +// purpose : +// ======================================================================= +TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights, + const Handle(Graphic3d_LightSet)& theLights, + Standard_Boolean theHasVertColor, + Standard_Boolean theIsPBR, + Standard_Boolean theHasEmissive, + Standard_Integer theNbShadowMaps) const +{ + TCollection_AsciiString aLightsFunc, aLightsLoop; + theNbLights = 0; + if (!theLights.IsNull()) + { + theNbLights = theLights->NbEnabled(); + if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX) + { + Standard_Integer anIndex = 0; + if (theNbShadowMaps > 0) + { + for (Graphic3d_LightSet::Iterator aLightIter (theLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); + aLightIter.More(); aLightIter.Next()) + { + if (aLightIter.Value()->Type() == Graphic3d_TOLS_DIRECTIONAL + && aLightIter.Value()->ToCastShadows()) + { + aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront," + EOL" occDirectionalLightShadow (occShadowMapSamplers[" + anIndex + "], " + anIndex + ", theNormal));"; + ++anIndex; + } + } + } + for (Graphic3d_LightSet::Iterator aLightIter (theLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); + aLightIter.More(); aLightIter.Next()) + { + switch (aLightIter.Value()->Type()) + { + case Graphic3d_TOLS_AMBIENT: + { + break; // skip ambient + } + case Graphic3d_TOLS_DIRECTIONAL: + { + if (theNbShadowMaps > 0 + && aLightIter.Value()->ToCastShadows()) + { + break; + } + aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront, 1.0);"; + ++anIndex; + break; + } + case Graphic3d_TOLS_POSITIONAL: + { + aLightsLoop = aLightsLoop + EOL" occPointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; + ++anIndex; + break; + } + case Graphic3d_TOLS_SPOT: + { + aLightsLoop = aLightsLoop + EOL" occSpotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; + ++anIndex; + break; + } + } + } + } + else + { + theNbLights = roundUpMaxLightSources (theNbLights); + bool isFirstInLoop = true; + aLightsLoop = aLightsLoop + + EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)" + EOL" {" + EOL" int aType = occLight_Type (anIndex);"; + if (theLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0) + { + isFirstInLoop = false; + aLightsLoop += + EOL" if (aType == OccLightType_Direct)" + EOL" {" + EOL" occDirectionalLight (anIndex, theNormal, theView, theIsFront, 1.0);" + EOL" }"; + } + if (theLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0) + { + if (!isFirstInLoop) + { + aLightsLoop += EOL" else "; + } + isFirstInLoop = false; + aLightsLoop += + EOL" if (aType == OccLightType_Point)" + EOL" {" + EOL" occPointLight (anIndex, theNormal, theView, aPoint, theIsFront);" + EOL" }"; + } + if (theLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0) + { + if (!isFirstInLoop) + { + aLightsLoop += EOL" else "; + } + isFirstInLoop = false; + aLightsLoop += + EOL" if (aType == OccLightType_Spot)" + EOL" {" + EOL" occSpotLight (anIndex, theNormal, theView, aPoint, theIsFront);" + EOL" }"; + } + aLightsLoop += EOL" }"; + } + + if (theIsPBR) + { + aLightsFunc += Shaders_PBRDistribution_glsl; + aLightsFunc += Shaders_PBRGeometry_glsl; + aLightsFunc += Shaders_PBRFresnel_glsl; + aLightsFunc += Shaders_PBRCookTorrance_glsl; + aLightsFunc += Shaders_PBRIllumination_glsl; + } + + if (theLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1 + && theNbLights == 1 + && !theIsPBR + && theNbShadowMaps == 0) + { + // use the version with hard-coded first index + aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront, 1.0);"; + aLightsFunc += THE_FUNC_directionalLightFirst; + } + else if (theLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0) + { + if (theNbShadowMaps > 0) + { + aLightsFunc += Shaders_DirectionalLightShadow_glsl; + } + aLightsFunc += theIsPBR ? Shaders_PBRDirectionalLight_glsl : Shaders_PhongDirectionalLight_glsl; + } + if (theLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0) + { + aLightsFunc += theIsPBR ? Shaders_PBRPointLight_glsl : Shaders_PhongPointLight_glsl; + } + if (theLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0) + { + aLightsFunc += theIsPBR ? Shaders_PBRSpotLight_glsl : Shaders_PhongSpotLight_glsl; + } + } + + TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();"; + TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();"; + if (theHasVertColor) + { + aGetMatAmbient = "getVertColor();"; + aGetMatDiffuse = "getVertColor();"; + } + + if (!theIsPBR) + { + return TCollection_AsciiString() + + THE_FUNC_lightDef + + Shaders_PointLightAttenuation_glsl + + aLightsFunc + + EOL + EOL"vec4 computeLighting (in vec3 theNormal," + EOL" in vec3 theView," + EOL" in vec4 thePoint," + EOL" in bool theIsFront)" + EOL"{" + EOL" Ambient = occLightAmbient.rgb;" + EOL" Diffuse = vec3 (0.0);" + EOL" Specular = vec3 (0.0);" + EOL" vec3 aPoint = thePoint.xyz / thePoint.w;" + + aLightsLoop + + EOL" vec4 aMatAmbient = " + aGetMatAmbient + + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse + + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();" + EOL" vec3 aColor = Ambient * aMatAmbient.rgb + Diffuse * aMatDiffuse.rgb + Specular * aMatSpecular.rgb;" + EOL" occTextureOcclusion(aColor, TexCoord.st);" + + (theHasEmissive + ? EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();" + EOL" aColor += aMatEmission.rgb;" : "") + + EOL" return vec4 (aColor, aMatDiffuse.a);" + EOL"}"; + } + else + { + return TCollection_AsciiString() + + THE_FUNC_PBR_lightDef + + Shaders_PointLightAttenuation_glsl + + aLightsFunc + + EOL + EOL"vec4 computeLighting (in vec3 theNormal," + EOL" in vec3 theView," + EOL" in vec4 thePoint," + EOL" in bool theIsFront)" + EOL"{" + EOL" DirectLighting = vec3(0.0);" + EOL" BaseColor = " + (theHasVertColor ? "getVertColor();" : "occTextureColor(occPBRMaterial_Color (theIsFront), TexCoord.st / TexCoord.w);") + + EOL" Emission = occTextureEmissive(occPBRMaterial_Emission (theIsFront), TexCoord.st / TexCoord.w);" + EOL" Metallic = occTextureMetallic(occPBRMaterial_Metallic (theIsFront), TexCoord.st / TexCoord.w);" + EOL" NormalizedRoughness = occTextureRoughness(occPBRMaterial_NormalizedRoughness (theIsFront), TexCoord.st / TexCoord.w);" + EOL" Roughness = occRoughness (NormalizedRoughness);" + EOL" IOR = occPBRMaterial_IOR (theIsFront);" + EOL" vec3 aPoint = thePoint.xyz / thePoint.w;" + + aLightsLoop + + EOL" vec3 aColor = DirectLighting;" + EOL" vec3 anIndirectLightingSpec = occPBRFresnel (BaseColor.rgb, Metallic, IOR);" + EOL" vec2 aCoeff = occTexture2D (occEnvLUT, vec2(abs(dot(theView, theNormal)), NormalizedRoughness)).xy;" + EOL" anIndirectLightingSpec *= aCoeff.x;" + EOL" anIndirectLightingSpec += aCoeff.y;" + EOL" anIndirectLightingSpec *= occTextureCubeLod (occSpecIBLMap, -reflect (theView, theNormal), NormalizedRoughness * float (occNbSpecIBLLevels - 1)).rgb;" + EOL" vec3 aRefractionCoeff = 1.0 - occPBRFresnel (BaseColor.rgb, Metallic, NormalizedRoughness, IOR, abs(dot(theView, theNormal)));" + EOL" aRefractionCoeff *= (1.0 - Metallic);" + EOL" vec3 anIndirectLightingDiff = aRefractionCoeff * BaseColor.rgb * BaseColor.a;" + EOL" anIndirectLightingDiff *= occDiffIBLMap (theNormal).rgb;" + EOL" aColor += occLightAmbient.rgb * (anIndirectLightingDiff + anIndirectLightingSpec);" + EOL" aColor += Emission;" + EOL" occTextureOcclusion(aColor, TexCoord.st / TexCoord.w);" + EOL" return vec4 (aColor, mix(1.0, BaseColor.a, aRefractionCoeff.x));" + EOL"}"; + } +} + +// ======================================================================= +// function : getStdProgramGouraud +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramGouraud (const Handle(Graphic3d_LightSet)& theLights, + Standard_Integer theBits) const +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain; + TCollection_AsciiString aSrcFrag, aSrcFragExtraMain; + TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }"; + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + + if ((theBits & Graphic3d_ShaderFlags_IsPoint) != 0) + { + if (mySetPointSize) + { + aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; + } + + if ((theBits & Graphic3d_ShaderFlags_PointSprite) != 0) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); + aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits); + } + + if ((theBits & Graphic3d_ShaderFlags_TextureRGB) != 0 + && (theBits & Graphic3d_ShaderFlags_VertColor) == 0) + { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }"; + } + } + else + { + if ((theBits & Graphic3d_ShaderFlags_TextureRGB) != 0) + { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); + aUniforms .Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; + + aSrcFragGetColor = + EOL"vec4 getColor(void)" + EOL"{" + EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;" + EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;" + EOL"}"; + } + } + + if ((theBits & Graphic3d_ShaderFlags_VertColor) != 0) + { + aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }"; + } + + int aNbClipPlanes = 0; + if ((theBits & Graphic3d_ShaderFlags_ClipPlanesN) != 0) + { + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += + EOL" PositionWorld = aPositionWorld;" + EOL" Position = aPosition;"; + + if ((theBits & Graphic3d_ShaderFlags_ClipPlanesN) == Graphic3d_ShaderFlags_ClipPlanesN) + { + aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT; + aSrcFragExtraMain += (theBits & Graphic3d_ShaderFlags_ClipChains) != 0 + ? THE_FRAG_CLIP_CHAINS_N + : THE_FRAG_CLIP_PLANES_N; + } + else if ((theBits & Graphic3d_ShaderFlags_ClipPlanes1) != 0) + { + aNbClipPlanes = 1; + aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1; + } + else if ((theBits & Graphic3d_ShaderFlags_ClipPlanes2) != 0) + { + aNbClipPlanes = 2; + aSrcFragExtraMain += (theBits & Graphic3d_ShaderFlags_ClipChains) != 0 + ? THE_FRAG_CLIP_CHAINS_2 + : THE_FRAG_CLIP_PLANES_2; + } + } + if ((theBits & Graphic3d_ShaderFlags_OitDepthPeeling) != 0) + { + aProgramSrc->SetNbFragmentOutputs (3); + aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT); + } + else if ((theBits & Graphic3d_ShaderFlags_WriteOit) != 0) + { + aProgramSrc->SetNbFragmentOutputs (2); + aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT); + } + + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + + Standard_Integer aNbLights = 0; + const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, theLights, !aSrcVertColor.IsEmpty(), false, true, 0); + aSrcVert = TCollection_AsciiString() + + THE_FUNC_transformNormal_view + + EOL + + aSrcVertColor + + aLights + + EOL"void main()" + EOL"{" + EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;" + EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;" + EOL" vec3 aNormal = transformNormal (occNormal);" + EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);" + EOL" FrontColor = computeLighting (aNormal, aView, aPosition, true);" + EOL" BackColor = computeLighting (aNormal, aView, aPosition, false);" + + aSrcVertExtraMain + + THE_VERT_gl_Position + + EOL"}"; + + TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits); + aSrcFragGetColor += (theBits & Graphic3d_ShaderFlags_MeshEdges) != 0 + ? THE_FRAG_WIREFRAME_COLOR + : EOL"#define getFinalColor getColor"; + + aSrcFrag = TCollection_AsciiString() + + aSrcFragGetColor + + EOL"void main()" + EOL"{" + EOL" if (occFragEarlyReturn()) { return; }" + + aSrcFragExtraMain + + EOL" occSetFragColor (getFinalColor());" + + EOL"}"; + + const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (theLights, false) + "-"; + defaultGlslVersion (aProgramSrc, aProgId, theBits); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (aNbLights); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); + aProgramSrc->SetAlphaTest ((theBits & Graphic3d_ShaderFlags_AlphaTest) != 0); + const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getStdProgramPhong +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramPhong (const Handle(Graphic3d_LightSet)& theLights, + const Standard_Integer theBits, + const Standard_Boolean theIsFlatNormal, + const Standard_Boolean theIsPBR, + const Standard_Integer theNbShadowMaps) const +{ + TCollection_AsciiString aPosition = theIsPBR ? "PositionWorld" : "Position"; + TCollection_AsciiString aPhongCompLight = TCollection_AsciiString() + + "computeLighting (normalize (Normal), normalize (View), " + aPosition + ", gl_FrontFacing)"; + const bool isFlatNormal = theIsFlatNormal && myHasFlatShading; + const char* aDFdxSignReversion = myToReverseDFdxSign ? "-" : ""; + if (isFlatNormal != theIsFlatNormal) + { + Message::SendWarning ("Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension"); + } + else if (isFlatNormal && myToReverseDFdxSign) + { + Message::SendWarning ("Warning: applied workaround for GLSL flat shading normal computation using dFdx/dFdy on Adreno"); + } + + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + aProgramSrc->SetPBR (theIsPBR); + + TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain; + TCollection_AsciiString aSrcFrag, aSrcFragGetVertColor, aSrcFragExtraMain; + TCollection_AsciiString aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void) { return " + aPhongCompLight + "; }"; + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + if ((theBits & Graphic3d_ShaderFlags_IsPoint) != 0) + { + if (mySetPointSize) + { + aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; + } + + if ((theBits & Graphic3d_ShaderFlags_PointSprite) != 0) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); + aSrcFragGetColor = pointSpriteShadingSrc (aPhongCompLight, theBits); + } + + if ((theBits & Graphic3d_ShaderFlags_TextureRGB) != 0 + && (theBits & Graphic3d_ShaderFlags_VertColor) == 0) + { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); + aUniforms .Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + + aSrcVertExtraMain += EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; + aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }"; + } + } + else + { + if ((theBits & Graphic3d_ShaderFlags_TextureRGB) != 0) + { + aUniforms .Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; + + Standard_Integer aTextureBits = Graphic3d_TextureSetBits_BaseColor | Graphic3d_TextureSetBits_Occlusion | Graphic3d_TextureSetBits_Emissive; + if (!theIsPBR) + { + aSrcFragGetColor = TCollection_AsciiString() + + EOL"vec4 getColor(void)" + EOL"{" + EOL" vec2 aTexUV = TexCoord.st / TexCoord.w;" + EOL" vec4 aColor = " + aPhongCompLight + ";" + EOL" aColor *= occTexture2D(occSamplerBaseColor, aTexUV);" + EOL" vec3 anEmission = occTextureEmissive((gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission()).rgb, aTexUV);" + EOL" aColor.rgb += anEmission;" + EOL" return aColor;" + EOL"}"; + } + else + { + aTextureBits |= Graphic3d_TextureSetBits_MetallicRoughness; + } + if ((theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureNormal + && !isFlatNormal) + { + if (myHasFlatShading) + { + aTextureBits |= Graphic3d_TextureSetBits_Normal; + } + else + { + Message::SendWarning ("Warning: ignoring Normal Map texture in GLSL due to hardware capabilities"); + } + } + aProgramSrc->SetTextureSetBits (aTextureBits); + } + } + + if ((theBits & Graphic3d_ShaderFlags_VertColor) != 0) + { + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += EOL" VertColor = occVertColor;"; + aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }"; + } + + int aNbClipPlanes = 0; + if ((theBits & Graphic3d_ShaderFlags_ClipPlanesN) != 0) + { + if ((theBits & Graphic3d_ShaderFlags_ClipPlanesN) == Graphic3d_ShaderFlags_ClipPlanesN) + { + aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT; + aSrcFragExtraMain += (theBits & Graphic3d_ShaderFlags_ClipChains) != 0 + ? THE_FRAG_CLIP_CHAINS_N + : THE_FRAG_CLIP_PLANES_N; + } + else if ((theBits & Graphic3d_ShaderFlags_ClipPlanes1) != 0) + { + aNbClipPlanes = 1; + aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1; + } + else if ((theBits & Graphic3d_ShaderFlags_ClipPlanes2) != 0) + { + aNbClipPlanes = 2; + aSrcFragExtraMain += (theBits & Graphic3d_ShaderFlags_ClipChains) != 0 + ? THE_FRAG_CLIP_CHAINS_2 + : THE_FRAG_CLIP_PLANES_2; + } + } + if ((theBits & Graphic3d_ShaderFlags_OitDepthPeeling) != 0) + { + aProgramSrc->SetNbFragmentOutputs (3); + aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT); + } + else if ((theBits & Graphic3d_ShaderFlags_WriteOit) != 0) + { + aProgramSrc->SetNbFragmentOutputs (2); + aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT); + } + + if (isFlatNormal) + { + aSrcFragExtraMain += TCollection_AsciiString() + + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (" + aPosition + ".xyz / " + aPosition + ".w), dFdy (" + aPosition + ".xyz / " + aPosition + ".w)));" + EOL" if (!gl_FrontFacing) { Normal = -Normal; }"; + } + else + { + aStageInOuts.Append(Graphic3d_ShaderObject::ShaderVariable("vec3 vNormal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraFunc += THE_FUNC_transformNormal_world; + aSrcVertExtraMain += EOL" vNormal = transformNormal (occNormal);"; + aSrcFragExtraMain += EOL" Normal = vNormal;"; + + if ((theBits & Graphic3d_ShaderFlags_IsPoint) == 0 + && (theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureNormal + && myHasFlatShading) + { + aSrcFrag += Shaders_TangentSpaceNormal_glsl; + // apply normal map texture + aSrcFragExtraMain += + EOL"#if defined(THE_HAS_TEXTURE_NORMAL)" + EOL" vec2 aTexCoord = TexCoord.st / TexCoord.w;" + EOL" vec4 aMapNormalValue = occTextureNormal(aTexCoord);" + EOL" if (aMapNormalValue.w > 0.5)" + EOL" {" + EOL" mat2 aDeltaUVMatrix = mat2 (dFdx(aTexCoord), dFdy(aTexCoord));" + EOL" mat2x3 aDeltaVectorMatrix = mat2x3 (dFdx (PositionWorld.xyz), dFdy (PositionWorld.xyz));" + EOL" Normal = TangentSpaceNormal (aDeltaUVMatrix, aDeltaVectorMatrix, aMapNormalValue.xyz, Normal, !gl_FrontFacing);" + EOL" }" + EOL"#endif"; + } + if (!theIsPBR) + { + aSrcFragExtraMain += + EOL" Normal = normalize ((occWorldViewMatrixInverseTranspose * vec4 (Normal, 0.0)).xyz);"; + } + } + + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + if (theNbShadowMaps > 0) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("mat4 occShadowMapMatrices[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occShadowMapSamplers[THE_NB_SHADOWMAPS]", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 occShadowMapSizeBias", Graphic3d_TOS_FRAGMENT)); + + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 PosLightSpace[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraMain += + EOL" for (int aShadowIter = 0; aShadowIter < THE_NB_SHADOWMAPS; ++aShadowIter)" + EOL" {" + EOL" PosLightSpace[aShadowIter] = occShadowMapMatrices[aShadowIter] * PositionWorld;" + EOL" }"; + } + + aSrcVert = TCollection_AsciiString() + + aSrcVertExtraFunc + + EOL"void main()" + EOL"{" + EOL" PositionWorld = occModelWorldMatrix * occVertex;" + EOL" Position = occWorldViewMatrix * PositionWorld;" + EOL" if (occProjectionMatrix[3][3] == 1.0)" + EOL" {" + EOL" View = vec3(0.0, 0.0, 1.0);" + EOL" }" + EOL" else" + EOL" {" + EOL" View = -Position.xyz;" + EOL" }" + + (theIsPBR ? EOL" View = (occWorldViewMatrixInverse * vec4(View, 0.0)).xyz;" : "") + + aSrcVertExtraMain + + THE_VERT_gl_Position + + EOL"}"; + + TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits); + aSrcFragGetColor += (theBits & Graphic3d_ShaderFlags_MeshEdges) != 0 + ? THE_FRAG_WIREFRAME_COLOR + : EOL"#define getFinalColor getColor"; + + Standard_Integer aNbLights = 0; + const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, theLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR, + (theBits & Graphic3d_ShaderFlags_TextureRGB) == 0 + || (theBits & Graphic3d_ShaderFlags_IsPoint) != 0, + theNbShadowMaps); + aSrcFrag += TCollection_AsciiString() + + EOL + + aSrcFragGetVertColor + + EOL"vec3 Normal;" + + aLights + + aSrcFragGetColor + + EOL + EOL"void main()" + EOL"{" + EOL" if (occFragEarlyReturn()) { return; }" + + aSrcFragExtraMain + + EOL" occSetFragColor (getFinalColor());" + + EOL"}"; + + const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") + + genLightKey (theLights, theNbShadowMaps > 0) + "-"; + defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (aNbLights); + aProgramSrc->SetNbShadowMaps (theNbShadowMaps); + aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); + aProgramSrc->SetAlphaTest ((theBits & Graphic3d_ShaderFlags_AlphaTest) != 0); + + const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getStdProgramStereo +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramStereo (Graphic3d_StereoMode theStereoMode) const +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + TCollection_AsciiString aSrcVert = + EOL"void main()" + EOL"{" + EOL" TexCoord = occVertex.zw;" + EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);" + EOL"}"; + + TCollection_AsciiString aSrcFrag; + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT)); + const char* aName = "stereo"; + switch (theStereoMode) + { + case Graphic3d_StereoMode_Anaglyph: + { + aName = "anaglyph"; + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT)); + const TCollection_AsciiString aNormalize = mySRgbState + ? EOL"#define sRgb2linear(theColor) theColor" + EOL"#define linear2sRgb(theColor) theColor" + : EOL"#define sRgb2linear(theColor) pow(theColor, vec4(2.2, 2.2, 2.2, 1.0))" + EOL"#define linear2sRgb(theColor) pow(theColor, 1.0 / vec4(2.2, 2.2, 2.2, 1.0))"; + aSrcFrag = aNormalize + + EOL"void main()" + EOL"{" + EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" + EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" + EOL" aColorL = sRgb2linear (aColorL);" + EOL" aColorR = sRgb2linear (aColorR);" + EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;" + EOL" occSetFragColor (linear2sRgb (aColor));" + EOL"}"; + break; + } + case Graphic3d_StereoMode_RowInterlaced: + { + aName = "row-interlaced"; + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" + EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" + EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)" + EOL" {" + EOL" occSetFragColor (aColorL);" + EOL" }" + EOL" else" + EOL" {" + EOL" occSetFragColor (aColorR);" + EOL" }" + EOL"}"; + break; + } + case Graphic3d_StereoMode_ColumnInterlaced: + { + aName = "column-interlaced"; + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" + EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" + EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)" + EOL" {" + EOL" occSetFragColor (aColorL);" + EOL" }" + EOL" else" + EOL" {" + EOL" occSetFragColor (aColorR);" + EOL" }" + EOL"}"; + break; + } + case Graphic3d_StereoMode_ChessBoard: + { + aName = "chessboard"; + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" + EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" + EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;" + EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;" + EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))" + EOL" {" + EOL" occSetFragColor (aColorL);" + EOL" }" + EOL" else" + EOL" {" + EOL" occSetFragColor (aColorR);" + EOL" }" + EOL"}"; + break; + } + case Graphic3d_StereoMode_SideBySide: + { + aName = "sidebyside"; + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);" + EOL" if (TexCoord.x > 0.5)" + EOL" {" + EOL" aTexCoord.x -= 1.0;" + EOL" }" + EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);" + EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);" + EOL" if (TexCoord.x <= 0.5)" + EOL" {" + EOL" occSetFragColor (aColorL);" + EOL" }" + EOL" else" + EOL" {" + EOL" occSetFragColor (aColorR);" + EOL" }" + EOL"}"; + break; + } + case Graphic3d_StereoMode_OverUnder: + { + aName = "overunder"; + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);" + EOL" if (TexCoord.y > 0.5)" + EOL" {" + EOL" aTexCoord.y -= 1.0;" + EOL" }" + EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);" + EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);" + EOL" if (TexCoord.y <= 0.5)" + EOL" {" + EOL" occSetFragColor (aColorL);" + EOL" }" + EOL" else" + EOL" {" + EOL" occSetFragColor (aColorR);" + EOL" }" + EOL"}"; + break; + } + case Graphic3d_StereoMode_QuadBuffer: + case Graphic3d_StereoMode_SoftPageFlip: + case Graphic3d_StereoMode_OpenVR: + default: + { + aSrcFrag = + EOL"void main()" + EOL"{" + EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" + EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" + EOL" aColorL.b = 0.0;" + EOL" aColorL.g = 0.0;" + EOL" aColorR.r = 0.0;" + EOL" occSetFragColor (aColorL + aColorR);" + EOL"}"; + break; + } + } + + defaultGlslVersion (aProgramSrc, aName, 0); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getStdProgramBoundBox +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramBoundBox() const +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX)); + + TCollection_AsciiString aSrcVert = + EOL"void main()" + EOL"{" + EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);" + EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);" + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;" + EOL"}"; + + TCollection_AsciiString aSrcFrag = + EOL"void main()" + EOL"{" + EOL" occSetFragColor (occColor);" + EOL"}"; + + defaultGlslVersion (aProgramSrc, "bndbox", 0); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getPBREnvBakingProgram +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getPBREnvBakingProgram (Standard_Integer theIndex) const +{ + Standard_ASSERT_RAISE (theIndex >= 0 && theIndex <= 2,""); + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + + TCollection_AsciiString aSrcVert = TCollection_AsciiString() + + THE_FUNC_cubemap_vector_transform + + Shaders_PBREnvBaking_vs; + + TCollection_AsciiString aSrcFrag = TCollection_AsciiString() + + THE_FUNC_cubemap_vector_transform + + Shaders_PBRDistribution_glsl + + ((theIndex == 0 || theIndex == 2) ? "\n#define THE_TO_BAKE_DIFFUSE\n" : "\n#define THE_TO_BAKE_SPECULAR\n") + + (theIndex == 2 ? "\n#define THE_TO_PACK_FLOAT\n" : "") + + Shaders_PBREnvBaking_fs; + + // constant array definition requires OpenGL 2.1+ or OpenGL ES 3.0+ + switch (myGapi) + { + case Aspect_GraphicsLibrary_OpenGL: + { + aProgramSrc->SetHeader ("#version 120"); + break; + } + case Aspect_GraphicsLibrary_OpenGLES: + { + if (IsGapiGreaterEqual (3, 0)) + { + aProgramSrc->SetHeader ("#version 300 es"); + } + else if (myGlslExtensions[Graphic3d_GlslExtension_GL_EXT_shader_texture_lod]) + { + aProgramSrc->SetHeader ("#extension GL_EXT_shader_texture_lod : enable\n" + "#define textureCubeLod textureCubeLodEXT"); + } + else + { + Message::SendWarning ("Warning: incomplete PBR lighting implementation due to missing OpenGL ES 3.0 or GL_EXT_shader_texture_lod support."); + } + break; + } + } + + static const char* THE_BAKE_NAMES[3] = { "pbr_env_baking_diffuse", "pbr_env_baking_specular", "pbr_env_baking_difffallback" }; + defaultGlslVersion (aProgramSrc, THE_BAKE_NAMES[theIndex], 0); + aProgramSrc->SetDefaultSampler (false); + aProgramSrc->SetNbLightsMax (0); + aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbClipPlanesMax (0); + aProgramSrc->SetPBR (true); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgramSrc; +} + +// ======================================================================= +// function : getBgCubeMapProgram +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getBgCubeMapProgram() const +{ + Handle(Graphic3d_ShaderProgram) aProgSrc = new Graphic3d_ShaderProgram(); + + Graphic3d_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; + aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable("vec3 ViewDirection", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("samplerCube occSampler0", Graphic3d_TOS_FRAGMENT)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX)); + + TCollection_AsciiString aSrcVert = TCollection_AsciiString() + + THE_FUNC_cubemap_vector_transform + + EOL"void main()" + EOL"{" + EOL" ViewDirection = cubemapVectorTransform (occVertex.xyz, uYCoeff, uZCoeff);" + EOL" vec4 aPos = occProjectionMatrix * occWorldViewMatrix * vec4(occVertex.xyz, 1.0);" + // setting Z to W ensures that final Z will be 1.0 after perspective division, (w/w=1)) + // which allows rendering skybox after everything else with depth test enabled (GL_LEQUAL) + EOL" gl_Position = aPos.xyww;" + EOL"}"; + + TCollection_AsciiString aDepthClamp; + if (myToEmulateDepthClamp) + { + // workaround Z clamping issues on some GPUs + aDepthClamp = EOL" gl_FragDepth = clamp (gl_FragDepth, 0.0, 1.0);"; + if (myGapi == Aspect_GraphicsLibrary_OpenGLES) + { + if (IsGapiGreaterEqual (3, 0)) + { + aProgSrc->SetHeader ("#version 300 es"); + } + else if (myGlslExtensions[Graphic3d_GlslExtension_GL_EXT_frag_depth]) + { + aProgSrc->SetHeader ("#extension GL_EXT_frag_depth : enable" + EOL"#define gl_FragDepth gl_FragDepthEXT"); + } + else + { + aDepthClamp.Clear(); + } + } + } + + TCollection_AsciiString aSrcFrag = TCollection_AsciiString() + + EOL"#define occEnvCubemap occSampler0" + EOL"void main()" + EOL"{" + EOL" occSetFragColor (vec4(occTextureCube (occEnvCubemap, ViewDirection).rgb, 1.0));" + + aDepthClamp + + EOL"}"; + + defaultGlslVersion (aProgSrc, "background_cubemap", 0); + aProgSrc->SetDefaultSampler (false); + aProgSrc->SetNbLightsMax (0); + aProgSrc->SetNbShadowMaps (0); + aProgSrc->SetNbClipPlanesMax (0); + aProgSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); + aProgSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + return aProgSrc; +} diff --git a/src/Graphic3d/Graphic3d_ShaderManager.hxx b/src/Graphic3d/Graphic3d_ShaderManager.hxx new file mode 100644 index 0000000000..e4a6a64772 --- /dev/null +++ b/src/Graphic3d/Graphic3d_ShaderManager.hxx @@ -0,0 +1,223 @@ +// Copyright (c) 2013-2021 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_ShaderManager_HeaderFile +#define _Graphic3d_ShaderManager_HeaderFile + +#include +#include +#include +#include +#include +#include + +class Graphic3d_LightSet; +class Graphic3d_ShaderProgram; + +//! GLSL syntax extensions. +enum Graphic3d_GlslExtension +{ + Graphic3d_GlslExtension_GL_OES_standard_derivatives, //!< OpenGL ES 2.0 extension GL_OES_standard_derivatives + Graphic3d_GlslExtension_GL_EXT_shader_texture_lod, //!< OpenGL ES 2.0 extension GL_EXT_shader_texture_lod + Graphic3d_GlslExtension_GL_EXT_frag_depth, //!< OpenGL ES 2.0 extension GL_EXT_frag_depth + Graphic3d_GlslExtension_GL_EXT_gpu_shader4, //!< OpenGL 2.0 extension GL_EXT_gpu_shader4 +}; +enum { Graphic3d_GlslExtension_NB = Graphic3d_GlslExtension_GL_EXT_gpu_shader4 + 1 }; + +//! This class is responsible for generation of shader programs. +class Graphic3d_ShaderManager : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Graphic3d_ShaderManager, Standard_Transient) +public: + + //! Creates new empty shader manager. + Standard_EXPORT Graphic3d_ShaderManager (Aspect_GraphicsLibrary theGapi); + + //! Releases resources of shader manager. + Standard_EXPORT virtual ~Graphic3d_ShaderManager(); + + //! @return true if detected GL version is greater or equal to requested one. + bool IsGapiGreaterEqual (Standard_Integer theVerMajor, + Standard_Integer theVerMinor) const + { + return (myGapiVersion[0] > theVerMajor) + || (myGapiVersion[0] == theVerMajor && myGapiVersion[1] >= theVerMinor); + } + + //! Return GAPI version major number. + Standard_Integer GapiVersionMajor() const { return myGapiVersion[0]; } + + //! Return GAPI version minor number. + Standard_Integer GapiVersionMinor() const { return myGapiVersion[1]; } + + //! Return GAPI version major number. + void SetGapiVersion (Standard_Integer theVerMajor, + Standard_Integer theVerMinor) + { + myGapiVersion.SetValues (theVerMajor, theVerMinor); + } + + //! Return TRUE if RED channel should be used instead of ALPHA for single-channel textures + //! (e.g. GAPI supports only GL_RED textures and not GL_ALPHA). + bool UseRedAlpha() const { return myUseRedAlpha; } + + //! Set if RED channel should be used instead of ALPHA for single-channel textures. + void SetUseRedAlpha (bool theUseRedAlpha) { myUseRedAlpha = theUseRedAlpha; } + + //! Return flag indicating flat shading usage; TRUE by default. + bool HasFlatShading() const { return myHasFlatShading; } + + //! Return flag indicating flat shading should reverse normal flag; FALSE by default. + bool ToReverseDFdxSign() const { return myToReverseDFdxSign; } + + //! Set flag indicating flat shading usage. + void SetFlatShading (bool theToUse, + bool theToReverseSign) + { + myHasFlatShading = theToUse; + myToReverseDFdxSign = theToReverseSign; + } + + //! Return TRUE if depth clamping should be emulated by GLSL program; TRUE by default. + bool ToEmulateDepthClamp() const { return myToEmulateDepthClamp; } + + //! Set if depth clamping should be emulated by GLSL program. + void SetEmulateDepthClamp (bool theToEmulate) { myToEmulateDepthClamp = theToEmulate; } + + //! Return TRUE if specified extension is available. + bool HasGlslExtension (Graphic3d_GlslExtension theExt) const { return myGlslExtensions[theExt]; } + + //! Set if specified extension is available or not. + void EnableGlslExtension (Graphic3d_GlslExtension theExt, + bool theToEnable = true) { myGlslExtensions[theExt] = theToEnable; } + +protected: + + //! Generate map key for light sources configuration. + //! @param theLights [in] list of light sources + //! @param theHasShadowMap [in] flag indicating shadow maps usage + Standard_EXPORT TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights, + const bool theHasShadowMap) const; + + //! Prepare standard GLSL program for textured font. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramFont() const; + + //! Prepare standard GLSL program without lighting. + //! @param theBits [in] program bits + //! @param theIsOutline [in] draw silhouette + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramUnlit (Standard_Integer theBits, + Standard_Boolean theIsOutline = false) const; + + //! Prepare standard GLSL program with per-vertex lighting. + //! @param theLights [in] list of light sources + //! @param theBits [in] program bits + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramGouraud (const Handle(Graphic3d_LightSet)& theLights, + Standard_Integer theBits) const; + + //! Prepare standard GLSL program with per-pixel lighting. + //! @param theLights [in] list of light sources + //! @param theBits [in] program bits + //! @param theIsFlatNormal [in] when TRUE, the Vertex normals will be ignored and Face normal will be computed instead + //! @param theIsPBR [in] when TRUE, the PBR pipeline will be activated + //! @param theNbShadowMaps [in] number of shadow maps + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramPhong (const Handle(Graphic3d_LightSet)& theLights, + const Standard_Integer theBits, + const Standard_Boolean theIsFlatNormal, + const Standard_Boolean theIsPBR, + const Standard_Integer theNbShadowMaps) const; + + //! Prepare standard GLSL program for bounding box. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramBoundBox() const; + + //! Generates shader program to render environment cubemap as background. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getBgCubeMapProgram() const; + + //! Prepare GLSL source for IBL generation used in PBR pipeline. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getPBREnvBakingProgram (Standard_Integer theIndex) const; + + //! Prepare standard GLSL program for FBO blit operation. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramFboBlit (Standard_Integer theNbSamples, + Standard_Boolean theIsFallback_sRGB) const; + + //! Prepare standard GLSL program for stereoscopic image. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramStereo (Graphic3d_StereoMode theStereoMode) const; + + //! Prepare standard GLSL programs for OIT compositing operation. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramOitCompositing (Standard_Boolean theMsaa) const; + + //! Prepare standard GLSL programs for OIT Depth Peeling blend operation. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramOitDepthPeelingBlend (Standard_Boolean theMsaa) const; + + //! Prepare standard GLSL programs for OIT Depth Peeling flush operation. + Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramOitDepthPeelingFlush (Standard_Boolean theMsaa) const; + +protected: + + //! Return TRUE if bitwise operations can be used in GLSL program. + Standard_EXPORT bool hasGlslBitwiseOps() const; + + //! Prepare GLSL version header. + //! @param theProgram [in] [out] program to set version header + //! @param theName [in] program id suffix + //! @param theBits [in] program bits + //! @param theUsesDerivates [in] program uses standard derivatives functions or not + //! @return filtered program bits with unsupported features disabled + Standard_EXPORT Standard_Integer defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, + const TCollection_AsciiString& theName, + Standard_Integer theBits, + bool theUsesDerivates = false) const; + + //! Prepare GLSL version header for OIT composition programs. + //! @param theProgram [in] [out] program to set version header + //! @param theName [in] program id suffix + //! @param theMsaa [in] multisampling flag + Standard_EXPORT void defaultOitGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, + const TCollection_AsciiString& theName, + bool theMsaa) const; + + //! Prepare standard GLSL program for accessing point sprite alpha. + Standard_EXPORT TCollection_AsciiString pointSpriteAlphaSrc (Standard_Integer theBits) const; + + //! Prepare standard GLSL program for computing point sprite shading. + Standard_EXPORT TCollection_AsciiString pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc, + Standard_Integer theBits) const; + + //! Define computeLighting GLSL function depending on current lights configuration + //! @param theNbLights [out] number of defined light sources + //! @param theLights [in] light sources list + //! @param theHasVertColor [in] flag to use getVertColor() instead of Ambient and Diffuse components of active material + //! @param theIsPBR [in] flag to activate PBR pipeline + //! @param theHasEmissive [in] flag to include emissive + //! @param theNbShadowMaps [in] flag to include shadow map + Standard_EXPORT TCollection_AsciiString stdComputeLighting (Standard_Integer& theNbLights, + const Handle(Graphic3d_LightSet)& theLights, + Standard_Boolean theHasVertColor, + Standard_Boolean theIsPBR, + Standard_Boolean theHasEmissive, + Standard_Integer theNbShadowMaps) const; + +protected: + + Aspect_GraphicsLibrary myGapi; //!< GAPI name + Graphic3d_Vec2i myGapiVersion; //!< GAPI version major/minor number pair + Standard_Boolean myGlslExtensions[Graphic3d_GlslExtension_NB]; + Standard_Boolean myHasFlatShading; //!< flag indicating flat shading usage + Standard_Boolean myToReverseDFdxSign; //!< flag to reverse flat shading normal (workaround) + Standard_Boolean mySetPointSize; //!< always set gl_PointSize variable + Standard_Boolean myUseRedAlpha; //!< use RED channel instead of ALPHA (e.g. GAPI supports only GL_RED textures and not GL_ALPHA) + Standard_Boolean myToEmulateDepthClamp; //!< emulate depth clamping in GLSL program + Standard_Boolean mySRgbState; //!< track sRGB state + +}; + +#endif // _Graphic3d_ShaderManager_HeaderFile diff --git a/src/Graphic3d/Graphic3d_ShaderObject.cxx b/src/Graphic3d/Graphic3d_ShaderObject.cxx index eada5bda97..0733255907 100755 --- a/src/Graphic3d/Graphic3d_ShaderObject.cxx +++ b/src/Graphic3d/Graphic3d_ShaderObject.cxx @@ -13,11 +13,12 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include + +#include #include #include #include -#include -#include IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderObject,Standard_Transient) @@ -26,7 +27,6 @@ namespace static volatile Standard_Integer THE_SHADER_OBJECT_COUNTER = 0; } - // ======================================================================= // function : Graphic3d_ShaderObject // purpose : Creates a shader object from specified file @@ -90,3 +90,140 @@ Standard_Boolean Graphic3d_ShaderObject::IsDone() const { return !mySource.IsEmpty(); } + +// ======================================================================= +// function : CreateFromSource +// purpose : +// ======================================================================= +Handle(Graphic3d_ShaderObject) Graphic3d_ShaderObject::CreateFromSource (TCollection_AsciiString& theSource, + Graphic3d_TypeOfShaderObject theType, + const ShaderVariableList& theUniforms, + const ShaderVariableList& theStageInOuts, + const TCollection_AsciiString& theInName, + const TCollection_AsciiString& theOutName, + Standard_Integer theNbGeomInputVerts) +{ + if (theSource.IsEmpty()) + { + return Handle(Graphic3d_ShaderObject)(); + } + + TCollection_AsciiString aSrcUniforms, aSrcInOuts, aSrcInStructs, aSrcOutStructs; + for (ShaderVariableList::Iterator anUniformIter (theUniforms); anUniformIter.More(); anUniformIter.Next()) + { + const ShaderVariable& aVar = anUniformIter.Value(); + if ((aVar.Stages & theType) != 0) + { + aSrcUniforms += TCollection_AsciiString("\nuniform ") + aVar.Name + ";"; + } + } + for (ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next()) + { + const ShaderVariable& aVar = aVarListIter.Value(); + Standard_Integer aStageLower = IntegerLast(), aStageUpper = IntegerFirst(); + Standard_Integer aNbStages = 0; + for (Standard_Integer aStageIter = Graphic3d_TOS_VERTEX; aStageIter <= (Standard_Integer )Graphic3d_TOS_COMPUTE; aStageIter = aStageIter << 1) + { + if ((aVar.Stages & aStageIter) != 0) + { + ++aNbStages; + aStageLower = Min (aStageLower, aStageIter); + aStageUpper = Max (aStageUpper, aStageIter); + } + } + if ((Standard_Integer )theType < aStageLower + || (Standard_Integer )theType > aStageUpper) + { + continue; + } + + const Standard_Boolean hasGeomStage = theNbGeomInputVerts > 0 + && aStageLower < Graphic3d_TOS_GEOMETRY + && aStageUpper >= Graphic3d_TOS_GEOMETRY; + const Standard_Boolean isAllStagesVar = aStageLower == Graphic3d_TOS_VERTEX + && aStageUpper == Graphic3d_TOS_FRAGMENT; + if (hasGeomStage + || !theInName.IsEmpty() + || !theOutName.IsEmpty()) + { + if (aSrcInStructs.IsEmpty() + && aSrcOutStructs.IsEmpty() + && isAllStagesVar) + { + if (theType == aStageLower) + { + aSrcOutStructs = "\nout VertexData\n{"; + } + else if (theType == aStageUpper) + { + aSrcInStructs = "\nin VertexData\n{"; + } + else // requires theInName/theOutName + { + aSrcInStructs = "\nin VertexData\n{"; + aSrcOutStructs = "\nout VertexData\n{"; + } + } + } + + if (isAllStagesVar + && (!aSrcInStructs.IsEmpty() + || !aSrcOutStructs.IsEmpty())) + { + if (!aSrcInStructs.IsEmpty()) + { + aSrcInStructs += TCollection_AsciiString("\n ") + aVar.Name + ";"; + } + if (!aSrcOutStructs.IsEmpty()) + { + aSrcOutStructs += TCollection_AsciiString("\n ") + aVar.Name + ";"; + } + } + else + { + if (theType == aStageLower) + { + aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_OUT ") + aVar.Name + ";"; + } + else if (theType == aStageUpper) + { + aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_IN ") + aVar.Name + ";"; + } + } + } + + if (theType == Graphic3d_TOS_GEOMETRY) + { + aSrcUniforms.Prepend (TCollection_AsciiString() + + "\nlayout (triangles) in;" + "\nlayout (triangle_strip, max_vertices = " + theNbGeomInputVerts + ") out;"); + } + if (!aSrcInStructs.IsEmpty() + && theType == Graphic3d_TOS_GEOMETRY) + { + aSrcInStructs += TCollection_AsciiString ("\n} ") + theInName + "[" + theNbGeomInputVerts + "];"; + } + else if (!aSrcInStructs.IsEmpty()) + { + aSrcInStructs += "\n}"; + if (!theInName.IsEmpty()) + { + aSrcInStructs += " "; + aSrcInStructs += theInName; + } + aSrcInStructs += ";"; + } + if (!aSrcOutStructs.IsEmpty()) + { + aSrcOutStructs += "\n}"; + if (!theOutName.IsEmpty()) + { + aSrcOutStructs += " "; + aSrcOutStructs += theOutName; + } + aSrcOutStructs += ";"; + } + + theSource.Prepend (aSrcUniforms + aSrcInStructs + aSrcOutStructs + aSrcInOuts); + return Graphic3d_ShaderObject::CreateFromSource (theType, theSource); +} diff --git a/src/Graphic3d/Graphic3d_ShaderObject.hxx b/src/Graphic3d/Graphic3d_ShaderObject.hxx index 4bf0130048..6218bfb74c 100755 --- a/src/Graphic3d/Graphic3d_ShaderObject.hxx +++ b/src/Graphic3d/Graphic3d_ShaderObject.hxx @@ -16,15 +16,64 @@ #ifndef _Graphic3d_ShaderObject_HeaderFile #define _Graphic3d_ShaderObject_HeaderFile -#include - #include +#include +#include //! Forward declaration //! This class is responsible for managing shader objects. class Graphic3d_ShaderObject : public Standard_Transient { +public: + //! Structure defining shader uniform or in/out variable. + struct ShaderVariable + { + TCollection_AsciiString Name; //!< variable name + Standard_Integer Stages; //!< active stages as Graphic3d_TypeOfShaderObject bits; + //! for in/out variables, intermediate stages will be automatically filled + + //! Create new shader variable. + ShaderVariable (const TCollection_AsciiString& theVarName, Standard_Integer theShaderStageBits) : Name (theVarName), Stages (theShaderStageBits) {} + + //! Empty constructor. + ShaderVariable() : Stages (0) {} + }; + + //! List of variable of shader program. + typedef NCollection_Sequence ShaderVariableList; + +public: + + //! Creates new shader object from specified file. + Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromFile (const Graphic3d_TypeOfShaderObject theType, + const TCollection_AsciiString& thePath); + + //! Creates new shader object from specified source. + Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromSource (const Graphic3d_TypeOfShaderObject theType, + const TCollection_AsciiString& theSource); + + //! This is a preprocessor for Graphic3d_ShaderObject::CreateFromSource() function. + //! Creates a new shader object from specified source according to list of uniforms and in/out variables. + //! @param theSource shader object source code to modify + //! @param theType shader object type to create + //! @param theUniforms list of uniform variables + //! @param theStageInOuts list of stage in/out variables + //! @param theInName name of input variables block; + //! can be empty for accessing each variable without block prefix + //! (mandatory for stages accessing both inputs and outputs) + //! @param theOutName name of output variables block; + //! can be empty for accessing each variable without block prefix + //! (mandatory for stages accessing both inputs and outputs) + //! @param theNbGeomInputVerts number of geometry shader input vertexes + Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromSource (TCollection_AsciiString& theSource, + Graphic3d_TypeOfShaderObject theType, + const ShaderVariableList& theUniforms, + const ShaderVariableList& theStageInOuts, + const TCollection_AsciiString& theInName = TCollection_AsciiString(), + const TCollection_AsciiString& theOutName = TCollection_AsciiString(), + Standard_Integer theNbGeomInputVerts = 0); + private: //! Creates new shader object of specified type. @@ -50,14 +99,6 @@ public: //! Returns unique ID used to manage resource in graphic driver. const TCollection_AsciiString& GetId() const { return myID; } - //! Creates new shader object from specified file. - Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromFile (const Graphic3d_TypeOfShaderObject theType, - const TCollection_AsciiString& thePath); - - //! Creates new shader object from specified source. - Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromSource (const Graphic3d_TypeOfShaderObject theType, - const TCollection_AsciiString& theSource); - public: DEFINE_STANDARD_RTTIEXT(Graphic3d_ShaderObject,Standard_Transient) diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index a580583644..15a8c4e271 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -1510,6 +1510,30 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) myFuncs->load (*this, isCoreProfile); + // setup shader generator + myShaderManager->SetGapiVersion (myGlVerMajor, myGlVerMinor); + myShaderManager->SetEmulateDepthClamp (!arbDepthClamp); + + bool toReverseDFdxSign = false; +#if defined(GL_ES_VERSION_2_0) + // workaround Adreno driver bug computing reversed normal using dFdx/dFdy + toReverseDFdxSign = myVendor.Search("qualcomm") != -1; +#endif + myShaderManager->SetFlatShading (hasFlatShading != OpenGl_FeatureNotAvailable, toReverseDFdxSign); +#if defined(GL_ES_VERSION_2_0) + myShaderManager->SetUseRedAlpha (false); +#else + myShaderManager->SetUseRedAlpha (core11 == NULL); +#endif + #define checkGlslExtensionShort(theName) myShaderManager->EnableGlslExtension (Graphic3d_GlslExtension_ ## theName, CheckExtension (#theName)) +#if defined(GL_ES_VERSION_2_0) + checkGlslExtensionShort(GL_OES_standard_derivatives); + checkGlslExtensionShort(GL_EXT_shader_texture_lod); + checkGlslExtensionShort(GL_EXT_frag_depth); +#else + checkGlslExtensionShort(GL_EXT_gpu_shader4); +#endif + // initialize debug context extension if (arbDbg != NULL && caps->contextDebug) diff --git a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx index 8b718bb5c7..8d6ab3e083 100644 --- a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx +++ b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx @@ -16,35 +16,11 @@ #ifndef _OpenGl_SetOfShaderPrograms_HeaderFile #define _OpenGl_SetOfShaderPrograms_HeaderFile +#include #include #include -#include -//! Standard GLSL program combination bits. -enum OpenGl_ProgramOptions -{ - OpenGl_PO_VertColor = 0x0001, //!< per-vertex color - OpenGl_PO_TextureRGB = 0x0002, //!< handle RGB texturing - OpenGl_PO_TextureEnv = 0x0004, //!< handle environment map (obsolete, to be removed) - OpenGl_PO_TextureNormal = OpenGl_PO_TextureRGB|OpenGl_PO_TextureEnv, //!< extended texture set (with normal map) - OpenGl_PO_PointSimple = 0x0008, //!< point marker without sprite - OpenGl_PO_PointSprite = 0x0010, //!< point sprite with RGB image - OpenGl_PO_PointSpriteA = OpenGl_PO_PointSimple|OpenGl_PO_PointSprite, //!< point sprite with Alpha image - OpenGl_PO_StippleLine = 0x0020, //!< stipple line - OpenGl_PO_ClipPlanes1 = 0x0040, //!< handle 1 clipping plane - OpenGl_PO_ClipPlanes2 = 0x0080, //!< handle 2 clipping planes - OpenGl_PO_ClipPlanesN = OpenGl_PO_ClipPlanes1|OpenGl_PO_ClipPlanes2, //!< handle N clipping planes - OpenGl_PO_ClipChains = 0x0100, //!< handle chains of clipping planes - OpenGl_PO_MeshEdges = 0x0200, //!< draw mesh edges (wireframe) - OpenGl_PO_AlphaTest = 0x0400, //!< discard fragment by alpha test (defined by cutoff value) - OpenGl_PO_WriteOit = 0x0800, //!< write coverage buffer for Blended Order-Independent Transparency - OpenGl_PO_OitDepthPeeling = 0x1000, //!< handle Depth Peeling OIT - // - OpenGl_PO_NB = 0x2000, //!< overall number of combinations - OpenGl_PO_IsPoint = OpenGl_PO_PointSimple|OpenGl_PO_PointSprite|OpenGl_PO_PointSpriteA, - OpenGl_PO_HasTextures = OpenGl_PO_TextureRGB|OpenGl_PO_TextureEnv, - OpenGl_PO_NeedsGeomShader = OpenGl_PO_MeshEdges, -}; +class OpenGl_ShaderProgram; //! Alias to programs array of predefined length class OpenGl_SetOfPrograms : public Standard_Transient @@ -59,7 +35,7 @@ public: Handle(OpenGl_ShaderProgram)& ChangeValue (Standard_Integer theProgramBits) { return myPrograms[theProgramBits]; } protected: - Handle(OpenGl_ShaderProgram) myPrograms[OpenGl_PO_NB]; //!< programs array + Handle(OpenGl_ShaderProgram) myPrograms[Graphic3d_ShaderFlags_NB]; //!< programs array }; //! Alias to 2D programs array of predefined length diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 6a3653134c..c36482b55f 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -13,224 +13,23 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#include +#include +#include #include #include #include #include -#include -#include #include #include #include #include #include -#include -#include "../Shaders/Shaders_DirectionalLightShadow_glsl.pxx" -#include "../Shaders/Shaders_PBRDistribution_glsl.pxx" -#include "../Shaders/Shaders_PBRDirectionalLight_glsl.pxx" -#include "../Shaders/Shaders_PBRGeometry_glsl.pxx" -#include "../Shaders/Shaders_PBRFresnel_glsl.pxx" -#include "../Shaders/Shaders_PBRCookTorrance_glsl.pxx" -#include "../Shaders/Shaders_PBRIllumination_glsl.pxx" -#include "../Shaders/Shaders_PBRPointLight_glsl.pxx" -#include "../Shaders/Shaders_PBRSpotLight_glsl.pxx" -#include "../Shaders/Shaders_PBREnvBaking_fs.pxx" -#include "../Shaders/Shaders_PBREnvBaking_vs.pxx" -#include "../Shaders/Shaders_PhongDirectionalLight_glsl.pxx" -#include "../Shaders/Shaders_PhongPointLight_glsl.pxx" -#include "../Shaders/Shaders_PhongSpotLight_glsl.pxx" -#include "../Shaders/Shaders_PointLightAttenuation_glsl.pxx" -#include "../Shaders/Shaders_TangentSpaceNormal_glsl.pxx" - -IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Graphic3d_ShaderManager) namespace { - //! Number specifying maximum number of light sources to prepare a GLSL program with unrolled loop. - const Standard_Integer THE_NB_UNROLLED_LIGHTS_MAX = 32; - - //! Compute the size of array storing holding light sources definition. - static Standard_Integer roundUpMaxLightSources (Standard_Integer theNbLights) - { - Standard_Integer aMaxLimit = THE_NB_UNROLLED_LIGHTS_MAX; - for (; aMaxLimit < theNbLights; aMaxLimit *= 2) {} - return aMaxLimit; - } - -#define EOL "\n" - -//! Compute TexCoord value in Vertex Shader -const char THE_VARY_TexCoord_Trsf[] = - EOL" float aRotSin = occTextureTrsf_RotationSin();" - EOL" float aRotCos = occTextureTrsf_RotationCos();" - EOL" vec2 aTex2 = vec2 (occTexCoord.x * aRotCos - occTexCoord.y * aRotSin," - EOL" occTexCoord.x * aRotSin + occTexCoord.y * aRotCos);" - EOL" aTex2 = (aTex2 + occTextureTrsf_Translation()) * occTextureTrsf_Scale();" - EOL" TexCoord = vec4(aTex2, occTexCoord.zw);"; - -//! Auxiliary function to flip gl_PointCoord vertically -#define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)" - -//! Auxiliary function to transform normal from model to view coordinate system. -const char THE_FUNC_transformNormal_view[] = - EOL"vec3 transformNormal (in vec3 theNormal)" - EOL"{" - EOL" vec4 aResult = occWorldViewMatrixInverseTranspose" - EOL" * occModelWorldMatrixInverseTranspose" - EOL" * vec4 (theNormal, 0.0);" - EOL" return normalize (aResult.xyz);" - EOL"}"; - -//! The same function as THE_FUNC_transformNormal but is used in PBR pipeline. -//! The normals are expected to be in world coordinate system in PBR pipeline. -const char THE_FUNC_transformNormal_world[] = - EOL"vec3 transformNormal (in vec3 theNormal)" - EOL"{" - EOL" vec4 aResult = occModelWorldMatrixInverseTranspose" - EOL" * vec4 (theNormal, 0.0);" - EOL" return normalize (aResult.xyz);" - EOL"}"; - -//! Global shader variable for color definition with lighting enabled. -const char THE_FUNC_lightDef[] = - EOL"vec3 Ambient;" //!< Ambient contribution of light sources - EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources - EOL"vec3 Specular;"; //!< Specular contribution of light sources - -//! Global shader variable for color definition with lighting enabled. -const char THE_FUNC_PBR_lightDef[] = - EOL"vec3 DirectLighting;" //!< Accumulator of direct lighting from light sources - EOL"vec4 BaseColor;" //!< Base color (albedo) of material for PBR - EOL"float Metallic;" //!< Metallic coefficient of material - EOL"float NormalizedRoughness;" //!< Normalized roughness coefficient of material - EOL"float Roughness;" //!< Roughness coefficient of material - EOL"vec3 Emission;" //!< Light intensity emitted by material - EOL"float IOR;"; //!< Material's index of refraction - -//! The same as Shaders_PhongDirectionalLight_glsl 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" in float theShadow)" - EOL"{" - EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (0), 0.0));" - 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 += occLight_Diffuse(0) * aNdotL * theShadow;" - EOL" Specular += occLight_Specular(0) * aSpecl * theShadow;" - EOL"}"; - -//! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip. -const char THE_FUNC_cubemap_vector_transform[] = - EOL"vec3 cubemapVectorTransform (in vec3 theVector," - EOL" in int theYCoeff," - EOL" in int theZCoeff)" - EOL"{" - EOL" theVector = theVector.yzx;" - EOL" theVector.y *= float(theYCoeff);" - EOL" theVector.z *= float(theZCoeff);" - EOL" return theVector;" - EOL"}"; - -//! Process clipping planes in Fragment Shader. -//! Should be added at the beginning of the main() function. -const char THE_FRAG_CLIP_PLANES_N[] = - EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)" - EOL" {" - EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];" - EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)" - EOL" {" - EOL" discard;" - EOL" }" - EOL" }"; - -//! Process chains of clipping planes in Fragment Shader. -const char THE_FRAG_CLIP_CHAINS_N[] = -EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)" -EOL" {" -EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];" -EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)" -EOL" {" -EOL" if (occClipPlaneChains[aPlaneIter] == 1)" -EOL" {" -EOL" discard;" -EOL" }" -EOL" aPlaneIter += 1;" -EOL" }" -EOL" else" -EOL" {" -EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];" -EOL" }" -EOL" }"; - -//! Process 1 clipping plane in Fragment Shader. -const char THE_FRAG_CLIP_PLANES_1[] = - EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];" - EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)" - EOL" {" - EOL" discard;" - EOL" }"; - -//! Process 2 clipping planes in Fragment Shader. -const char THE_FRAG_CLIP_PLANES_2[] = - EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];" - EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];" - EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0" - EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)" - EOL" {" - EOL" discard;" - EOL" }"; - -//! Process a chain of 2 clipping planes in Fragment Shader (3/4 section). -const char THE_FRAG_CLIP_CHAINS_2[] = -EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];" -EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];" -EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0" -EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)" -EOL" {" -EOL" discard;" -EOL" }"; - -//! Modify color for Wireframe presentation. -const char THE_FRAG_WIREFRAME_COLOR[] = -EOL"vec4 getFinalColor(void)" -EOL"{" -EOL" float aDistance = min (min (EdgeDistance[0], EdgeDistance[1]), EdgeDistance[2]);" -EOL" bool isHollow = occWireframeColor.a < 0.0;" -EOL" float aMixVal = smoothstep (occLineWidth - occLineFeather * 0.5, occLineWidth + occLineFeather * 0.5, aDistance);" -EOL" vec4 aMixColor = isHollow" -EOL" ? vec4 (getColor().rgb, 1.0 - aMixVal)" // edges only (of interior color) -EOL" : mix (occWireframeColor, getColor(), aMixVal);" // interior + edges -EOL" return aMixColor;" -EOL"}"; - -//! Compute gl_Position vertex shader output. -const char THE_VERT_gl_Position[] = -EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"; - -//! Displace gl_Position alongside vertex normal for outline rendering. -//! This code adds silhouette only for smooth surfaces of closed primitive, and produces visual artifacts on sharp edges. -const char THE_VERT_gl_Position_OUTLINE[] = -EOL" float anOutlineDisp = occOrthoScale > 0.0 ? occOrthoScale : gl_Position.w;" -EOL" vec4 anOutlinePos = occVertex + vec4 (occNormal * (occSilhouetteThickness * anOutlineDisp), 0.0);" -EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * anOutlinePos;"; - #if !defined(GL_ES_VERSION_2_0) static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -313,21 +112,6 @@ EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatr glEnable (theLightGlId); } #endif - - //! Generate map key for light sources configuration. - static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights, - const bool theHasShadowMap) - { - if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX) - { - return theHasShadowMap - ? TCollection_AsciiString ("ls_") + theLights->KeyEnabledLong() - : TCollection_AsciiString ("l_") + theLights->KeyEnabledLong(); - } - - const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled()); - return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit; - } } // ======================================================================= @@ -335,14 +119,18 @@ EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatr // purpose : Creates new empty shader manager // ======================================================================= OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext) -: myFfpProgram (new OpenGl_ShaderProgramFFP()), +#if defined(GL_ES_VERSION_2_0) +: Graphic3d_ShaderManager (Aspect_GraphicsLibrary_OpenGLES), +#else +: Graphic3d_ShaderManager (Aspect_GraphicsLibrary_OpenGL), +#endif + myFfpProgram (new OpenGl_ShaderProgramFFP()), myShadingModel (Graphic3d_TOSM_VERTEX), myUnlitPrograms (new OpenGl_SetOfPrograms()), myContext (theContext), - mySRgbState (theContext->ToRenderSRGB()), myHasLocalOrigin (Standard_False) { - // + mySRgbState = theContext->ToRenderSRGB(); } // ======================================================================= @@ -455,24 +243,6 @@ void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey } } -// ======================================================================= -// function : ShaderPrograms -// purpose : Returns list of registered shader programs -// ======================================================================= -const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const -{ - return myProgramList; -} - -// ======================================================================= -// function : Empty -// purpose : Returns true if no program objects are attached -// ======================================================================= -Standard_Boolean OpenGl_ShaderManager::IsEmpty() const -{ - return myProgramList.IsEmpty(); -} - // ======================================================================= // function : switchLightPrograms // purpose : @@ -995,8 +765,7 @@ void OpenGl_ShaderManager::pushClippingState (const Handle(OpenGl_ShaderProgram) } else if (aPlaneId >= aNbMaxPlanes) { - myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, - TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded."); + Message::SendWarning() << "OpenGl_ShaderManager, warning: clipping planes limit (" << aNbMaxPlanes << ") has been exceeded"; break; } @@ -1305,56 +1074,29 @@ void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& thePro } // ======================================================================= -// function : prepareStdProgramFont +// function : BindFontProgram // purpose : // ======================================================================= -Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont() +Standard_Boolean OpenGl_ShaderManager::BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram) { - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - - TCollection_AsciiString aSrcVert = TCollection_AsciiString() - + EOL"void main()" - EOL"{" - EOL" TexCoord = occTexCoord.st;" - + THE_VERT_gl_Position - + EOL"}"; - - TCollection_AsciiString - aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }"; -#if !defined(GL_ES_VERSION_2_0) - if (myContext->core11 == NULL) + if (!theCustomProgram.IsNull() + || myContext->caps->ffpEnable) { - aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }"; + return bindProgramWithState (theCustomProgram, Graphic3d_TOSM_UNLIT); } -#endif - TCollection_AsciiString aSrcFrag = - aSrcGetAlpha - + EOL"void main()" - EOL"{" - EOL" vec4 aColor = occColor;" - EOL" aColor.a *= getAlpha();" - EOL" if (aColor.a <= 0.285) discard;" - EOL" occSetFragColor (aColor);" - EOL"}"; - - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - defaultGlslVersion (aProgramSrc, "font", 0); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); - TCollection_AsciiString aKey; - if (!Create (aProgramSrc, aKey, myFontProgram)) + if (myFontProgram.IsNull()) { - myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid - return Standard_False; + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramFont(); + TCollection_AsciiString aKey; + if (!Create (aProgramSrc, aKey, myFontProgram)) + { + myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid + return false; + } } - return Standard_True; + + return bindProgramWithState (myFontProgram, Graphic3d_TOSM_UNLIT); } // ======================================================================= @@ -1372,243 +1114,66 @@ Standard_Boolean OpenGl_ShaderManager::BindFboBlitProgram (Standard_Integer theN } Handle(OpenGl_ShaderProgram)& aProg = aList[aNbSamples]; - if (aProg.IsNull()) + if (!aProg.IsNull()) { - prepareStdProgramFboBlit (aProg, aNbSamples, theIsFallback_sRGB); - } - return !aProg.IsNull() - && myContext->BindProgram (aProg); -} - -// ======================================================================= -// function : prepareStdProgramFboBlit -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit (Handle(OpenGl_ShaderProgram)& theProgram, - Standard_Integer theNbSamples, - Standard_Boolean theIsFallback_sRGB) -{ - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - - TCollection_AsciiString aSrcVert = - EOL"void main()" - EOL"{" - EOL" TexCoord = occVertex.zw;" - EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);" - EOL"}"; - - TCollection_AsciiString aSrcFrag; - if (theNbSamples > 1) - { - #if defined(GL_ES_VERSION_2_0) - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT)); - #else - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT)); - #endif - aSrcFrag = TCollection_AsciiString() - + EOL"#define THE_NUM_SAMPLES " + theNbSamples - + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "") - + EOL"void main()" - EOL"{" - EOL" ivec2 aSize = textureSize (uColorSampler);" - EOL" ivec2 anUV = ivec2 (vec2 (aSize) * TexCoord);" - EOL" gl_FragDepth = texelFetch (uDepthSampler, anUV, THE_NUM_SAMPLES / 2 - 1).r;" - EOL - EOL" vec4 aColor = vec4 (0.0);" - EOL" for (int aSample = 0; aSample < THE_NUM_SAMPLES; ++aSample)" - EOL" {" - EOL" vec4 aVal = texelFetch (uColorSampler, anUV, aSample);" - EOL" aColor += aVal;" - EOL" }" - EOL" aColor /= float(THE_NUM_SAMPLES);" - EOL"#ifdef THE_SHIFT_sRGB" - EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));" - EOL"#endif" - EOL" occSetFragColor (aColor);" - EOL"}"; - } - else - { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uColorSampler", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uDepthSampler", Graphic3d_TOS_FRAGMENT)); - aSrcFrag = TCollection_AsciiString() - + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "") - + EOL"void main()" - EOL"{" - EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;" - EOL" vec4 aColor = occTexture2D (uColorSampler, TexCoord);" - EOL"#ifdef THE_SHIFT_sRGB" - EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));" - EOL"#endif" - EOL" occSetFragColor (aColor);" - EOL"}"; + return myContext->BindProgram (aProg); } - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); -#if defined(GL_ES_VERSION_2_0) - if (myContext->IsGlGreaterEqual (3, 1)) - { - // required for MSAA sampler - aProgramSrc->SetHeader ("#version 310 es"); - } - else if (myContext->IsGlGreaterEqual (3, 0)) - { - aProgramSrc->SetHeader ("#version 300 es"); - } - else if (myContext->extFragDepth) - { - aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable" - EOL"#define gl_FragDepth gl_FragDepthEXT"); - } - else - { - // there is no way to draw into depth buffer - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));" - EOL"}"; - } -#else - if (myContext->core32 != NULL) - { - aProgramSrc->SetHeader ("#version 150"); - } -#endif - TCollection_AsciiString anId = "occt_blit"; - if (theNbSamples > 1) - { - anId += TCollection_AsciiString ("_msaa") + theNbSamples; - } - if (theIsFallback_sRGB) - { - anId += "_gamma"; - } - aProgramSrc->SetId (anId); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramFboBlit (aNbSamples, theIsFallback_sRGB); TCollection_AsciiString aKey; - if (!Create (aProgramSrc, aKey, theProgram)) + if (!Create (aProgramSrc, aKey, aProg)) { - theProgram = new OpenGl_ShaderProgram(); // just mark as invalid - return Standard_False; + aProg = new OpenGl_ShaderProgram(); // just mark as invalid + return false; } - myContext->BindProgram (theProgram); - theProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0); - theProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1); - myContext->BindProgram (NULL); - return Standard_True; + myContext->BindProgram (aProg); + aProg->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0); + aProg->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1); + return true; } // ======================================================================= -// function : prepareStdProgramOitCompositing +// function : BindOitCompositingProgram // purpose : // ======================================================================= -Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa) +Standard_Boolean OpenGl_ShaderManager::BindOitCompositingProgram (Standard_Boolean theIsMSAAEnabled) { - Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0]; - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - TCollection_AsciiString aSrcVert, aSrcFrag; - - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - - aSrcVert = - EOL"void main()" - EOL"{" - EOL" TexCoord = occVertex.zw;" - EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);" - EOL"}"; - - if (!theMsaa) + const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; + Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[aProgramIdx]; + if (!aProgram.IsNull()) { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT)); - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);" - EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;" - EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));" - EOL"}"; + return myContext->BindProgram (aProgram); } - else - { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT)); - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);" - EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);" - EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;" - EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));" - EOL"}"; - } - defaultOitGlslVersion (aProgramSrc, "weight_oit", theMsaa); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramOitCompositing (theIsMSAAEnabled); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, aProgram)) { aProgram = new OpenGl_ShaderProgram(); // just mark as invalid - return Standard_False; + return false; } myContext->BindProgram (aProgram); aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0); aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1); - myContext->BindProgram (Handle(OpenGl_ShaderProgram)()); - return Standard_True; + return true; } // ======================================================================= -// function : prepareStdProgramOitDepthPeelingBlend +// function : BindOitDepthPeelingBlendProgram // purpose : // ======================================================================= -Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitDepthPeelingBlend (Standard_Boolean theMsaa) +Standard_Boolean OpenGl_ShaderManager::BindOitDepthPeelingBlendProgram (bool theIsMSAAEnabled) { - Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingBlendProgram[theMsaa ? 1 : 0]; - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - TCollection_AsciiString aSrcVert, aSrcFrag; + const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; + Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingBlendProgram [aProgramIdx]; + if (!aProgram.IsNull()) + { + return myContext->BindProgram (aProgram); + } - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - aSrcVert = - EOL"void main()" - EOL"{" - EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);" - EOL"}"; - - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable (theMsaa - ? "sampler2DMS uDepthPeelingBackColor" - : "sampler2D uDepthPeelingBackColor", Graphic3d_TOS_FRAGMENT)); - aSrcFrag = TCollection_AsciiString() - + EOL"void main()" - EOL"{" - EOL" #define THE_SAMPLE_ID " + (theMsaa ? "gl_SampleID" : "0") - + EOL" occFragColor = texelFetch (uDepthPeelingBackColor, ivec2 (gl_FragCoord.xy), THE_SAMPLE_ID);" - EOL" if (occFragColor.a == 0.0) { discard; }" - EOL"}"; - - defaultOitGlslVersion (aProgramSrc, "oit_peeling_blend", theMsaa); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramOitDepthPeelingBlend (theIsMSAAEnabled); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, aProgram)) { @@ -1618,50 +1183,23 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitDepthPeelingBlend (St myContext->BindProgram (aProgram); aProgram->SetSampler (myContext, "uDepthPeelingBackColor", Graphic3d_TextureUnit_0); - myContext->BindProgram (Handle(OpenGl_ShaderProgram)()); return true; } // ======================================================================= -// function : prepareStdProgramOitDepthPeelingFlush +// function : BindOitDepthPeelingFlushProgram // purpose : // ======================================================================= -Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitDepthPeelingFlush (Standard_Boolean theMsaa) +Standard_Boolean OpenGl_ShaderManager::BindOitDepthPeelingFlushProgram (bool theIsMSAAEnabled) { - Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingFlushProgram[theMsaa ? 1 : 0]; - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - TCollection_AsciiString aSrcVert, aSrcFrag; + const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; + Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingFlushProgram [aProgramIdx]; + if (!aProgram.IsNull()) + { + return myContext->BindProgram (aProgram); + } - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - aSrcVert = - EOL"void main()" - EOL"{" - EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);" - EOL"}"; - - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable (theMsaa - ? "sampler2DMS uDepthPeelingFrontColor" - : "sampler2D uDepthPeelingFrontColor", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable (theMsaa - ? "sampler2DMS uDepthPeelingBackColor" - : "sampler2D uDepthPeelingBackColor", Graphic3d_TOS_FRAGMENT)); - aSrcFrag = TCollection_AsciiString() - + EOL"void main()" - EOL"{" - EOL" #define THE_SAMPLE_ID " + (theMsaa ? "gl_SampleID" : "0") - + EOL" ivec2 aFragCoord = ivec2 (gl_FragCoord.xy);" - EOL" vec4 aFrontColor = texelFetch (uDepthPeelingFrontColor, aFragCoord, THE_SAMPLE_ID);" - EOL" vec4 aBackColor = texelFetch (uDepthPeelingBackColor, aFragCoord, THE_SAMPLE_ID);" - EOL" float anAlphaMult = 1.0 - aFrontColor.a;" - EOL" occFragColor = vec4 (aFrontColor.rgb + anAlphaMult * aBackColor.rgb, aFrontColor.a + aBackColor.a);" - EOL"}"; - - defaultOitGlslVersion (aProgramSrc, "oit_peeling_flush", theMsaa); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramOitDepthPeelingFlush (theIsMSAAEnabled); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, aProgram)) { @@ -1672,288 +1210,9 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitDepthPeelingFlush (St myContext->BindProgram (aProgram); aProgram->SetSampler (myContext, "uDepthPeelingFrontColor", Graphic3d_TextureUnit_0); aProgram->SetSampler (myContext, "uDepthPeelingBackColor", Graphic3d_TextureUnit_1); - myContext->BindProgram (Handle(OpenGl_ShaderProgram)()); return true; } -// ======================================================================= -// function : pointSpriteAlphaSrc -// purpose : -// ======================================================================= -TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (Standard_Integer theBits) -{ - TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").a; }"; -#if !defined(GL_ES_VERSION_2_0) - if (myContext->core11 == NULL - && (theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA) - { - aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").r; }"; - } -#else - (void )theBits; -#endif - return aSrcGetAlpha; -} - -// ======================================================================= -// function : defaultGlslVersion -// purpose : -// ======================================================================= -int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, - const TCollection_AsciiString& theName, - int theBits, - bool theUsesDerivates) const -{ - int aBits = theBits; - const bool toUseDerivates = theUsesDerivates - || (theBits & OpenGl_PO_StippleLine) != 0 - || (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal; -#if !defined(GL_ES_VERSION_2_0) - if (myContext->core32 != NULL) - { - theProgram->SetHeader ("#version 150"); - } - else - { - const bool toUseMat2x3 = (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal; - if (toUseMat2x3) // TangentSpaceNormal() function uses mat2x3 type - { - if (myContext->IsGlGreaterEqual (2, 1)) - { - theProgram->SetHeader ("#version 120"); - } - } - if ((theBits & OpenGl_PO_StippleLine) != 0 - || theProgram->IsPBR()) - { - if (myContext->IsGlGreaterEqual (3, 0)) - { - theProgram->SetHeader ("#version 130"); - } - else if (myContext->CheckExtension ("GL_EXT_gpu_shader4")) // myContext->hasGlslBitwiseOps == OpenGl_FeatureInExtensions - { - // GL_EXT_gpu_shader4 defines GLSL type "unsigned int", while core GLSL specs define type "uint" - theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable\n" - "#define uint unsigned int"); - } - } - } - (void )toUseDerivates; -#else - -#if defined(__EMSCRIPTEN__) - if (myContext->IsGlGreaterEqual (3, 0)) - { - // consider this is browser responsibility to provide working WebGL 2.0 implementation - // and black-list broken drivers (there is no OpenGL ES greater than 3.0) - theProgram->SetHeader ("#version 300 es"); - } -#endif - // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es") - // and "300 es" on OpenGL ES 3.1+ devices - if (myContext->IsGlGreaterEqual (3, 1)) - { - if ((theBits & OpenGl_PO_NeedsGeomShader) != 0) - { - theProgram->SetHeader (myContext->hasGeometryStage != OpenGl_FeatureInExtensions ? "#version 320 es" : "#version 310 es"); - } - else - { - theProgram->SetHeader ("#version 300 es"); - } - } - else - { - TCollection_AsciiString aGles2Extensions; - if (theProgram->IsPBR()) - { - if (myContext->IsGlGreaterEqual (3, 0)) - { - theProgram->SetHeader ("#version 300 es"); - } - else if (myContext->CheckExtension ("GL_EXT_shader_texture_lod")) - { - aGles2Extensions += "#extension GL_EXT_shader_texture_lod : enable\n" - "#define textureCubeLod textureCubeLodEXT\n"; - } - } - if ((theBits & OpenGl_PO_WriteOit) != 0 - || (theBits & OpenGl_PO_OitDepthPeeling) != 0 - || (theBits & OpenGl_PO_StippleLine) != 0) - { - if (myContext->IsGlGreaterEqual (3, 0)) - { - theProgram->SetHeader ("#version 300 es"); - } - else - { - aBits = aBits & ~OpenGl_PO_WriteOit; - aBits = aBits & ~OpenGl_PO_OitDepthPeeling; - if (!myContext->oesStdDerivatives) - { - aBits = aBits & ~OpenGl_PO_StippleLine; - } - } - } - if (toUseDerivates) - { - if (myContext->IsGlGreaterEqual (3, 0)) - { - theProgram->SetHeader ("#version 300 es"); - } - else if (myContext->oesStdDerivatives) - { - aGles2Extensions += "#extension GL_OES_standard_derivatives : enable\n"; - } - } - - if (!aGles2Extensions.IsEmpty()) - { - theProgram->SetHeader (aGles2Extensions); - } - } -#endif - - // should fit OpenGl_PO_NB - char aBitsStr[64]; - Sprintf (aBitsStr, "%04x", aBits); - theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr); - return aBits; -} - -// ======================================================================= -// function : defaultOitGlslVersion -// purpose : -// ======================================================================= -void OpenGl_ShaderManager::defaultOitGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, - const TCollection_AsciiString& theName, - bool theMsaa) const -{ - if (theMsaa) - { - #if !defined(GL_ES_VERSION_2_0) - if (myContext->IsGlGreaterEqual (4, 0)) - { - theProgram->SetHeader ("#version 400"); - } - #else - if (myContext->IsGlGreaterEqual (3, 2)) - { - theProgram->SetHeader ("#version 320 es"); - } - else if (myContext->IsGlGreaterEqual (3, 0)) - { - theProgram->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension - } - #endif - } - else - { - #if !defined(GL_ES_VERSION_2_0) - if (myContext->IsGlGreaterEqual (3, 2)) - { - theProgram->SetHeader ("#version 150"); - } - #else - if (myContext->IsGlGreaterEqual (3, 0)) - { - theProgram->SetHeader ("#version 300 es"); - } - #endif - } - theProgram->SetId (TCollection_AsciiString ("occt_") + theName + (theMsaa ? "_msaa" : "")); -} - -// ======================================================================= -// function : prepareGeomMainSrc -// purpose : -// ======================================================================= -TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms, - OpenGl_ShaderObject::ShaderVariableList& theStageInOuts, - Standard_Integer theBits) -{ - if ((theBits & OpenGl_PO_NeedsGeomShader) == 0) - { - return TCollection_AsciiString(); - } - - TCollection_AsciiString aSrcMainGeom = - EOL"void main()" - EOL"{"; - - if ((theBits & OpenGl_PO_MeshEdges) != 0) - { - theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY)); - theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY)); - theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY)); - theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT)); - theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT)); - theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT)); - theStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT)); - - aSrcMainGeom = TCollection_AsciiString() - + EOL"vec3 ViewPortTransform (vec4 theVec)" - EOL"{" - EOL" vec3 aWinCoord = theVec.xyz / theVec.w;" - EOL" aWinCoord = aWinCoord * 0.5 + 0.5;" - EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;" - EOL" return aWinCoord;" - EOL"}" - + aSrcMainGeom - + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);" - EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);" - EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);" - EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);" - EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));" - EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;" - EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance - EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;"; - } - - for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter) - { - const TCollection_AsciiString aVertIndex (aVertIter); - // pass variables from Vertex shader to Fragment shader through Geometry shader - for (OpenGl_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next()) - { - if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)) - { - const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2); - if (aVarName.Value (aVarName.Length()) == ']') - { - // copy the whole array - const TCollection_AsciiString aVarName2 = aVarName.Token ("[", 1); - aSrcMainGeom += TCollection_AsciiString() - + EOL" geomOut." + aVarName2 + " = geomIn[" + aVertIndex + "]." + aVarName2 + ";"; - } - else - { - aSrcMainGeom += TCollection_AsciiString() - + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";"; - } - } - } - - if ((theBits & OpenGl_PO_MeshEdges) != 0) - { - switch (aVertIter) - { - case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break; - case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break; - case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break; - } - } - aSrcMainGeom += TCollection_AsciiString() - + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;" - EOL" EmitVertex();"; - } - aSrcMainGeom += - EOL" EndPrimitive();" - EOL"}"; - - return aSrcMainGeom; -} - // ======================================================================= // function : prepareStdProgramUnlit // purpose : @@ -1962,235 +1221,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha Standard_Integer theBits, Standard_Boolean theIsOutline) { - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain; - TCollection_AsciiString aSrcFrag, aSrcFragExtraMain; - TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }"; - TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());"; - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - - if ((theBits & OpenGl_PO_IsPoint) != 0) - { - #if defined(GL_ES_VERSION_2_0) - aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; - #endif - - if ((theBits & OpenGl_PO_PointSprite) != 0) - { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); - if ((theBits & OpenGl_PO_PointSpriteA) != OpenGl_PO_PointSpriteA) - { - aSrcFragGetColor = - EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }"; - } - else if ((theBits & OpenGl_PO_TextureRGB) != 0 - && (theBits & OpenGl_PO_VertColor) == 0) - { - aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); - aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += - EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; - aSrcFragGetColor = - EOL"vec4 getColor(void) { return VertColor; }"; - } - - aSrcGetAlpha = pointSpriteAlphaSrc (theBits); - - #if !defined(GL_ES_VERSION_2_0) - if (myContext->core11 != NULL - && myContext->IsGlGreaterEqual (2, 1)) - { - aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2 - } - #endif - - aSrcFragMainGetColor = - EOL" vec4 aColor = getColor();" - EOL" aColor.a = getAlpha();" - EOL" if (aColor.a <= 0.1) discard;" - EOL" occSetFragColor (aColor);"; - } - else - { - if ((theBits & OpenGl_PO_TextureRGB) != 0 - && (theBits & OpenGl_PO_VertColor) == 0) - { - aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); - aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += - EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; - aSrcFragGetColor = - EOL"vec4 getColor(void) { return VertColor; }"; - } - - aSrcFragMainGetColor = - EOL" vec4 aColor = getColor();" - EOL" if (aColor.a <= 0.1) discard;" - EOL" occSetFragColor (aColor);"; - } - } - else - { - if ((theBits & OpenGl_PO_HasTextures) != 0) - { - aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureEnv) - { - aSrcVertExtraFunc = THE_FUNC_transformNormal_view; - - aSrcVertExtraMain += - EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;" - EOL" vec3 aNormal = transformNormal (occNormal);" - EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);" - EOL" aReflect.z += 1.0;" - EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);"; - - aSrcFragGetColor = - EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }"; - } - else - { - aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); - aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; - - aSrcFragGetColor = - EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }"; - } - } - } - if ((theBits & OpenGl_PO_VertColor) != 0) - { - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += EOL" VertColor = occVertColor;"; - aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }"; - } - - int aNbClipPlanes = 0; - if ((theBits & OpenGl_PO_ClipPlanesN) != 0) - { - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += - EOL" PositionWorld = occModelWorldMatrix * occVertex;" - EOL" Position = occWorldViewMatrix * PositionWorld;"; - - if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN) - { - aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT; - aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0 - ? THE_FRAG_CLIP_CHAINS_N - : THE_FRAG_CLIP_PLANES_N; - } - else if ((theBits & OpenGl_PO_ClipPlanes1) != 0) - { - aNbClipPlanes = 1; - aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1; - } - else if ((theBits & OpenGl_PO_ClipPlanes2) != 0) - { - aNbClipPlanes = 2; - aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0 - ? THE_FRAG_CLIP_CHAINS_2 - : THE_FRAG_CLIP_PLANES_2; - } - } - if ((theBits & OpenGl_PO_OitDepthPeeling) != 0) - { - aProgramSrc->SetNbFragmentOutputs (3); - aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT); - } - else if ((theBits & OpenGl_PO_WriteOit) != 0) - { - aProgramSrc->SetNbFragmentOutputs (2); - aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT); - } - - if (theIsOutline) - { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occOrthoScale", Graphic3d_TOS_VERTEX)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occSilhouetteThickness", Graphic3d_TOS_VERTEX)); - aSrcVertEndMain = THE_VERT_gl_Position_OUTLINE; - } - else if ((theBits & OpenGl_PO_StippleLine) != 0) - { - const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits); - if ((aBits & OpenGl_PO_StippleLine) != 0) - { - if (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable) - { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int occStipplePattern", Graphic3d_TOS_FRAGMENT)); - } - else - { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occStipplePattern[16]", Graphic3d_TOS_FRAGMENT)); - } - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occStippleFactor", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_VERTEX)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertEndMain = - EOL" vec2 aPosition = gl_Position.xy / gl_Position.w;" - EOL" aPosition = aPosition * 0.5 + 0.5;" - EOL" ScreenSpaceCoord = aPosition.xy * occViewport.zw + occViewport.xy;"; - aSrcFragMainGetColor = TCollection_AsciiString() - + EOL" vec2 anAxis = vec2 (0.0, 1.0);" - EOL" if (abs (dFdx (ScreenSpaceCoord.x)) - abs (dFdy (ScreenSpaceCoord.y)) > 0.001)" - EOL" {" - EOL" anAxis = vec2 (1.0, 0.0);" - EOL" }" - EOL" float aRotatePoint = dot (gl_FragCoord.xy, anAxis);" - + (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable - ? EOL" uint aBit = uint (floor (aRotatePoint / occStippleFactor + 0.5)) & 15U;" - EOL" if ((uint (occStipplePattern) & (1U << aBit)) == 0U) discard;" - : EOL" int aBit = int (mod (floor (aRotatePoint / occStippleFactor + 0.5), 16.0));" - EOL" if (!occStipplePattern[aBit]) discard;") - + EOL" vec4 aColor = getFinalColor();" - EOL" if (aColor.a <= 0.1) discard;" - EOL" occSetFragColor (aColor);"; - } - else - { - myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning: stipple lines in GLSL will be ignored."); - } - } - - aSrcVert = - aSrcVertExtraFunc - + EOL"void main()" - EOL"{" - + aSrcVertExtraMain - + THE_VERT_gl_Position - + aSrcVertEndMain - + EOL"}"; - - TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits); - aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0 - ? THE_FRAG_WIREFRAME_COLOR - : EOL"#define getFinalColor getColor"; - - aSrcFrag = - aSrcFragGetColor - + aSrcGetAlpha - + EOL"void main()" - EOL"{" - EOL" if (occFragEarlyReturn()) { return; }" - + aSrcFragExtraMain - + aSrcFragMainGetColor - + EOL"}"; - - defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); - aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); - const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramUnlit (theBits, theIsOutline); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, theProgram)) { @@ -2200,266 +1231,6 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha return Standard_True; } -// ======================================================================= -// function : pointSpriteShadingSrc -// purpose : -// ======================================================================= -TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc, - Standard_Integer theBits) -{ - TCollection_AsciiString aSrcFragGetColor; - if ((theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA) - { - aSrcFragGetColor = pointSpriteAlphaSrc (theBits) + - EOL"vec4 getColor(void)" - EOL"{" - EOL" vec4 aColor = " + theBaseColorSrc + ";" - EOL" aColor.a = getAlpha();" - EOL" if (aColor.a <= 0.1) discard;" - EOL" return aColor;" - EOL"}"; - } - else if ((theBits & OpenGl_PO_PointSprite) == OpenGl_PO_PointSprite) - { - aSrcFragGetColor = TCollection_AsciiString() + - EOL"vec4 getColor(void)" - EOL"{" - EOL" vec4 aColor = " + theBaseColorSrc + ";" - EOL" aColor = occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ") * aColor;" - EOL" if (aColor.a <= 0.1) discard;" - EOL" return aColor;" - EOL"}"; - } - - return aSrcFragGetColor; -} - -// ======================================================================= -// function : stdComputeLighting -// purpose : -// ======================================================================= -TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights, - Standard_Boolean theHasVertColor, - Standard_Boolean theIsPBR, - Standard_Boolean theHasEmissive, - Standard_Boolean theHasShadowMap) -{ - TCollection_AsciiString aLightsFunc, aLightsLoop; - theNbLights = 0; - const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources(); - if (!aLights.IsNull()) - { - const bool hasShadowMap = theHasShadowMap && myLightSourceState.HasShadowMaps(); - theNbLights = aLights->NbEnabled(); - if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX) - { - Standard_Integer anIndex = 0; - if (hasShadowMap) - { - for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); - aLightIter.More(); aLightIter.Next()) - { - if (aLightIter.Value()->Type() == Graphic3d_TOLS_DIRECTIONAL - && aLightIter.Value()->ToCastShadows()) - { - aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront," - EOL" occDirectionalLightShadow (occShadowMapSamplers[" + anIndex + "], " + anIndex + ", theNormal));"; - ++anIndex; - } - } - } - for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); - aLightIter.More(); aLightIter.Next()) - { - switch (aLightIter.Value()->Type()) - { - case Graphic3d_TOLS_AMBIENT: - { - break; // skip ambient - } - case Graphic3d_TOLS_DIRECTIONAL: - { - if (hasShadowMap - && aLightIter.Value()->ToCastShadows()) - { - break; - } - aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront, 1.0);"; - ++anIndex; - break; - } - case Graphic3d_TOLS_POSITIONAL: - { - aLightsLoop = aLightsLoop + EOL" occPointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; - ++anIndex; - break; - } - case Graphic3d_TOLS_SPOT: - { - aLightsLoop = aLightsLoop + EOL" occSpotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; - ++anIndex; - break; - } - } - } - } - else - { - theNbLights = roundUpMaxLightSources (theNbLights); - bool isFirstInLoop = true; - aLightsLoop = aLightsLoop + - EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)" - EOL" {" - EOL" int aType = occLight_Type (anIndex);"; - if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0) - { - isFirstInLoop = false; - aLightsLoop += - EOL" if (aType == OccLightType_Direct)" - EOL" {" - EOL" occDirectionalLight (anIndex, theNormal, theView, theIsFront, 1.0);" - EOL" }"; - } - if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0) - { - if (!isFirstInLoop) - { - aLightsLoop += EOL" else "; - } - isFirstInLoop = false; - aLightsLoop += - EOL" if (aType == OccLightType_Point)" - EOL" {" - EOL" occPointLight (anIndex, theNormal, theView, aPoint, theIsFront);" - EOL" }"; - } - if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0) - { - if (!isFirstInLoop) - { - aLightsLoop += EOL" else "; - } - isFirstInLoop = false; - aLightsLoop += - EOL" if (aType == OccLightType_Spot)" - EOL" {" - EOL" occSpotLight (anIndex, theNormal, theView, aPoint, theIsFront);" - EOL" }"; - } - aLightsLoop += EOL" }"; - } - - if (theIsPBR) - { - aLightsFunc += Shaders_PBRDistribution_glsl; - aLightsFunc += Shaders_PBRGeometry_glsl; - aLightsFunc += Shaders_PBRFresnel_glsl; - aLightsFunc += Shaders_PBRCookTorrance_glsl; - aLightsFunc += Shaders_PBRIllumination_glsl; - } - - if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1 - && theNbLights == 1 - && !theIsPBR - && !hasShadowMap) - { - // use the version with hard-coded first index - aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront, 1.0);"; - aLightsFunc += THE_FUNC_directionalLightFirst; - } - else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0) - { - if (hasShadowMap) - { - aLightsFunc += Shaders_DirectionalLightShadow_glsl; - } - aLightsFunc += theIsPBR ? Shaders_PBRDirectionalLight_glsl : Shaders_PhongDirectionalLight_glsl; - } - if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0) - { - aLightsFunc += theIsPBR ? Shaders_PBRPointLight_glsl : Shaders_PhongPointLight_glsl; - } - if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0) - { - aLightsFunc += theIsPBR ? Shaders_PBRSpotLight_glsl : Shaders_PhongSpotLight_glsl; - } - } - - TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();"; - TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();"; - if (theHasVertColor) - { - aGetMatAmbient = "getVertColor();"; - aGetMatDiffuse = "getVertColor();"; - } - - if (!theIsPBR) - { - return TCollection_AsciiString() - + THE_FUNC_lightDef - + Shaders_PointLightAttenuation_glsl - + aLightsFunc - + EOL - EOL"vec4 computeLighting (in vec3 theNormal," - EOL" in vec3 theView," - EOL" in vec4 thePoint," - EOL" in bool theIsFront)" - EOL"{" - EOL" Ambient = occLightAmbient.rgb;" - EOL" Diffuse = vec3 (0.0);" - EOL" Specular = vec3 (0.0);" - EOL" vec3 aPoint = thePoint.xyz / thePoint.w;" - + aLightsLoop - + EOL" vec4 aMatAmbient = " + aGetMatAmbient - + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse - + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();" - EOL" vec3 aColor = Ambient * aMatAmbient.rgb + Diffuse * aMatDiffuse.rgb + Specular * aMatSpecular.rgb;" - EOL" occTextureOcclusion(aColor, TexCoord.st);" - + (theHasEmissive - ? EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();" - EOL" aColor += aMatEmission.rgb;" : "") - + EOL" return vec4 (aColor, aMatDiffuse.a);" - EOL"}"; - } - else - { - return TCollection_AsciiString() - + THE_FUNC_PBR_lightDef - + Shaders_PointLightAttenuation_glsl - + aLightsFunc - + EOL - EOL"vec4 computeLighting (in vec3 theNormal," - EOL" in vec3 theView," - EOL" in vec4 thePoint," - EOL" in bool theIsFront)" - EOL"{" - EOL" DirectLighting = vec3(0.0);" - EOL" BaseColor = " + (theHasVertColor ? "getVertColor();" : "occTextureColor(occPBRMaterial_Color (theIsFront), TexCoord.st / TexCoord.w);") - + EOL" Emission = occTextureEmissive(occPBRMaterial_Emission (theIsFront), TexCoord.st / TexCoord.w);" - EOL" Metallic = occTextureMetallic(occPBRMaterial_Metallic (theIsFront), TexCoord.st / TexCoord.w);" - EOL" NormalizedRoughness = occTextureRoughness(occPBRMaterial_NormalizedRoughness (theIsFront), TexCoord.st / TexCoord.w);" - EOL" Roughness = occRoughness (NormalizedRoughness);" - EOL" IOR = occPBRMaterial_IOR (theIsFront);" - EOL" vec3 aPoint = thePoint.xyz / thePoint.w;" - + aLightsLoop - + EOL" vec3 aColor = DirectLighting;" - EOL" vec3 anIndirectLightingSpec = occPBRFresnel (BaseColor.rgb, Metallic, IOR);" - EOL" vec2 aCoeff = occTexture2D (occEnvLUT, vec2(abs(dot(theView, theNormal)), NormalizedRoughness)).xy;" - EOL" anIndirectLightingSpec *= aCoeff.x;" - EOL" anIndirectLightingSpec += aCoeff.y;" - EOL" anIndirectLightingSpec *= occTextureCubeLod (occSpecIBLMap, -reflect (theView, theNormal), NormalizedRoughness * float (occNbSpecIBLLevels - 1)).rgb;" - EOL" vec3 aRefractionCoeff = 1.0 - occPBRFresnel (BaseColor.rgb, Metallic, NormalizedRoughness, IOR, abs(dot(theView, theNormal)));" - EOL" aRefractionCoeff *= (1.0 - Metallic);" - EOL" vec3 anIndirectLightingDiff = aRefractionCoeff * BaseColor.rgb * BaseColor.a;" - EOL" anIndirectLightingDiff *= occDiffIBLMap (theNormal).rgb;" - EOL" aColor += occLightAmbient.rgb * (anIndirectLightingDiff + anIndirectLightingSpec);" - EOL" aColor += Emission;" - EOL" occTextureOcclusion(aColor, TexCoord.st / TexCoord.w);" - EOL" return vec4 (aColor, mix(1.0, BaseColor.a, aRefractionCoeff.x));" - EOL"}"; - } -} - // ======================================================================= // function : prepareStdProgramGouraud // purpose : @@ -2467,150 +1238,7 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram, const Standard_Integer theBits) { - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain; - TCollection_AsciiString aSrcFrag, aSrcFragExtraMain; - TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }"; - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - - if ((theBits & OpenGl_PO_IsPoint) != 0) - { - #if defined(GL_ES_VERSION_2_0) - aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; - #endif - - if ((theBits & OpenGl_PO_PointSprite) != 0) - { - #if !defined(GL_ES_VERSION_2_0) - if (myContext->core11 != NULL - && myContext->IsGlGreaterEqual (2, 1)) - { - aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2 - } - #endif - - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); - aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits); - } - - if ((theBits & OpenGl_PO_TextureRGB) != 0 - && (theBits & OpenGl_PO_VertColor) == 0) - { - aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); - aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }"; - } - } - else - { - if ((theBits & OpenGl_PO_TextureRGB) != 0) - { - aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); - aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; - - aSrcFragGetColor = - EOL"vec4 getColor(void)" - EOL"{" - EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;" - EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;" - EOL"}"; - } - } - - if ((theBits & OpenGl_PO_VertColor) != 0) - { - aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }"; - } - - int aNbClipPlanes = 0; - if ((theBits & OpenGl_PO_ClipPlanesN) != 0) - { - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += - EOL" PositionWorld = aPositionWorld;" - EOL" Position = aPosition;"; - - if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN) - { - aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT; - aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0 - ? THE_FRAG_CLIP_CHAINS_N - : THE_FRAG_CLIP_PLANES_N; - } - else if ((theBits & OpenGl_PO_ClipPlanes1) != 0) - { - aNbClipPlanes = 1; - aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1; - } - else if ((theBits & OpenGl_PO_ClipPlanes2) != 0) - { - aNbClipPlanes = 2; - aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0 - ? THE_FRAG_CLIP_CHAINS_2 - : THE_FRAG_CLIP_PLANES_2; - } - } - if ((theBits & OpenGl_PO_OitDepthPeeling) != 0) - { - aProgramSrc->SetNbFragmentOutputs (3); - aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT); - } - else if ((theBits & OpenGl_PO_WriteOit) != 0) - { - aProgramSrc->SetNbFragmentOutputs (2); - aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT); - } - - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - - Standard_Integer aNbLights = 0; - const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false, true, false); - aSrcVert = TCollection_AsciiString() - + THE_FUNC_transformNormal_view - + EOL - + aSrcVertColor - + aLights - + EOL"void main()" - EOL"{" - EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;" - EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;" - EOL" vec3 aNormal = transformNormal (occNormal);" - EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);" - EOL" FrontColor = computeLighting (aNormal, aView, aPosition, true);" - EOL" BackColor = computeLighting (aNormal, aView, aPosition, false);" - + aSrcVertExtraMain - + THE_VERT_gl_Position - + EOL"}"; - - TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits); - aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0 - ? THE_FRAG_WIREFRAME_COLOR - : EOL"#define getFinalColor getColor"; - - aSrcFrag = TCollection_AsciiString() - + aSrcFragGetColor - + EOL"void main()" - EOL"{" - EOL" if (occFragEarlyReturn()) { return; }" - + aSrcFragExtraMain - + EOL" occSetFragColor (getFinalColor());" - + EOL"}"; - - const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources(), false) + "-"; - defaultGlslVersion (aProgramSrc, aProgId, theBits); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (aNbLights); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); - aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); - const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramGouraud (myLightSourceState.LightSources(), theBits); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, theProgram)) { @@ -2629,264 +1257,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha const Standard_Boolean theIsFlatNormal, const Standard_Boolean theIsPBR) { - TCollection_AsciiString aPosition = theIsPBR ? "PositionWorld" : "Position"; - TCollection_AsciiString aPhongCompLight = TCollection_AsciiString() + - "computeLighting (normalize (Normal), normalize (View), " + aPosition + ", gl_FrontFacing)"; - const bool isFlatNormal = theIsFlatNormal - && myContext->hasFlatShading != OpenGl_FeatureNotAvailable; - const char* aDFdxSignReversion = ""; -#if defined(GL_ES_VERSION_2_0) - if (isFlatNormal != theIsFlatNormal) - { - 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."); - } - else if (isFlatNormal - && myContext->Vendor().Search("qualcomm") != -1) - { - // workaround Adreno driver bug computing reversed normal using dFdx/dFdy - aDFdxSignReversion = "-"; - myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, - "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno"); - } -#endif - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - aProgramSrc->SetPBR (theIsPBR); - - TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain; - TCollection_AsciiString aSrcFrag, aSrcFragGetVertColor, aSrcFragExtraMain; - TCollection_AsciiString aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void) { return " + aPhongCompLight + "; }"; - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - if ((theBits & OpenGl_PO_IsPoint) != 0) - { - #if defined(GL_ES_VERSION_2_0) - aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; - #endif - - if ((theBits & OpenGl_PO_PointSprite) != 0) - { - #if !defined(GL_ES_VERSION_2_0) - if (myContext->core11 != NULL - && myContext->IsGlGreaterEqual (2, 1)) - { - aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2 - } - #endif - - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT)); - aSrcFragGetColor = pointSpriteShadingSrc (aPhongCompLight, theBits); - } - - if ((theBits & OpenGl_PO_TextureRGB) != 0 - && (theBits & OpenGl_PO_VertColor) == 0) - { - aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); - aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - - aSrcVertExtraMain += EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);"; - aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }"; - } - } - else - { - if ((theBits & OpenGl_PO_TextureRGB) != 0) - { - aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; - - Standard_Integer aTextureBits = Graphic3d_TextureSetBits_BaseColor | Graphic3d_TextureSetBits_Occlusion | Graphic3d_TextureSetBits_Emissive; - if (!theIsPBR) - { - aSrcFragGetColor = TCollection_AsciiString() + - EOL"vec4 getColor(void)" - EOL"{" - EOL" vec2 aTexUV = TexCoord.st / TexCoord.w;" - EOL" vec4 aColor = " + aPhongCompLight + ";" - EOL" aColor *= occTexture2D(occSamplerBaseColor, aTexUV);" - EOL" vec3 anEmission = occTextureEmissive((gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission()).rgb, aTexUV);" - EOL" aColor.rgb += anEmission;" - EOL" return aColor;" - EOL"}"; - } - else - { - aTextureBits |= Graphic3d_TextureSetBits_MetallicRoughness; - } - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal - && !isFlatNormal) - { - if (myContext->hasFlatShading != OpenGl_FeatureNotAvailable) - { - aTextureBits |= Graphic3d_TextureSetBits_Normal; - } - else - { - myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, - "Warning: ignoring Normal Map texture due to hardware capabilities"); - } - } - aProgramSrc->SetTextureSetBits (aTextureBits); - } - } - - if ((theBits & OpenGl_PO_VertColor) != 0) - { - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += EOL" VertColor = occVertColor;"; - aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }"; - } - - int aNbClipPlanes = 0; - if ((theBits & OpenGl_PO_ClipPlanesN) != 0) - { - if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN) - { - aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT; - aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0 - ? THE_FRAG_CLIP_CHAINS_N - : THE_FRAG_CLIP_PLANES_N; - } - else if ((theBits & OpenGl_PO_ClipPlanes1) != 0) - { - aNbClipPlanes = 1; - aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1; - } - else if ((theBits & OpenGl_PO_ClipPlanes2) != 0) - { - aNbClipPlanes = 2; - aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0 - ? THE_FRAG_CLIP_CHAINS_2 - : THE_FRAG_CLIP_PLANES_2; - } - } - if ((theBits & OpenGl_PO_OitDepthPeeling) != 0) - { - aProgramSrc->SetNbFragmentOutputs (3); - aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT); - } - else if ((theBits & OpenGl_PO_WriteOit) != 0) - { - aProgramSrc->SetNbFragmentOutputs (2); - aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT); - } - - if (isFlatNormal) - { - aSrcFragExtraMain += TCollection_AsciiString() - + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (" + aPosition + ".xyz / " + aPosition + ".w), dFdy (" + aPosition + ".xyz / " + aPosition + ".w)));" - EOL" if (!gl_FrontFacing) { Normal = -Normal; }"; - } - else - { - aStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable("vec3 vNormal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraFunc += THE_FUNC_transformNormal_world; - aSrcVertExtraMain += EOL" vNormal = transformNormal (occNormal);"; - aSrcFragExtraMain += EOL" Normal = vNormal;"; - - if ((theBits & OpenGl_PO_IsPoint) == 0 - && (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal - && myContext->hasFlatShading != OpenGl_FeatureNotAvailable) - { - aSrcFrag += Shaders_TangentSpaceNormal_glsl; - // apply normal map texture - aSrcFragExtraMain += - EOL"#if defined(THE_HAS_TEXTURE_NORMAL)" - EOL" vec2 aTexCoord = TexCoord.st / TexCoord.w;" - EOL" vec4 aMapNormalValue = occTextureNormal(aTexCoord);" - EOL" if (aMapNormalValue.w > 0.5)" - EOL" {" - EOL" mat2 aDeltaUVMatrix = mat2 (dFdx(aTexCoord), dFdy(aTexCoord));" - EOL" mat2x3 aDeltaVectorMatrix = mat2x3 (dFdx (PositionWorld.xyz), dFdy (PositionWorld.xyz));" - EOL" Normal = TangentSpaceNormal (aDeltaUVMatrix, aDeltaVectorMatrix, aMapNormalValue.xyz, Normal, !gl_FrontFacing);" - EOL" }" - EOL"#endif"; - } - if (!theIsPBR) - { - aSrcFragExtraMain += - EOL" Normal = normalize ((occWorldViewMatrixInverseTranspose * vec4 (Normal, 0.0)).xyz);"; - } - } - - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - if (myLightSourceState.HasShadowMaps()) - { - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 occShadowMapMatrices[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occShadowMapSamplers[THE_NB_SHADOWMAPS]", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 occShadowMapSizeBias", Graphic3d_TOS_FRAGMENT)); - - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PosLightSpace[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraMain += - EOL" for (int aShadowIter = 0; aShadowIter < THE_NB_SHADOWMAPS; ++aShadowIter)" - EOL" {" - EOL" PosLightSpace[aShadowIter] = occShadowMapMatrices[aShadowIter] * PositionWorld;" - EOL" }"; - } - - aSrcVert = TCollection_AsciiString() - + aSrcVertExtraFunc - + EOL"void main()" - EOL"{" - EOL" PositionWorld = occModelWorldMatrix * occVertex;" - EOL" Position = occWorldViewMatrix * PositionWorld;" - EOL" if (occProjectionMatrix[3][3] == 1.0)" - EOL" {" - EOL" View = vec3(0.0, 0.0, 1.0);" - EOL" }" - EOL" else" - EOL" {" - EOL" View = -Position.xyz;" - EOL" }" - + (theIsPBR ? EOL" View = (occWorldViewMatrixInverse * vec4(View, 0.0)).xyz;" : "") - + aSrcVertExtraMain - + THE_VERT_gl_Position - + EOL"}"; - - TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits); - aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0 - ? THE_FRAG_WIREFRAME_COLOR - : EOL"#define getFinalColor getColor"; - - Standard_Integer aNbLights = 0; Standard_Integer aNbShadowMaps = myLightSourceState.HasShadowMaps() ? myLightSourceState.LightSources()->NbCastShadows() : 0; - const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR, - (theBits & OpenGl_PO_TextureRGB) == 0 - || (theBits & OpenGl_PO_IsPoint) != 0, - myLightSourceState.HasShadowMaps()); - aSrcFrag += TCollection_AsciiString() - + EOL - + aSrcFragGetVertColor - + EOL"vec3 Normal;" - + aLights - + aSrcFragGetColor - + EOL - EOL"void main()" - EOL"{" - EOL" if (occFragEarlyReturn()) { return; }" - + aSrcFragExtraMain - + EOL" occSetFragColor (getFinalColor());" - + EOL"}"; - - const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") - + genLightKey (myLightSourceState.LightSources(), aNbShadowMaps > 0) + "-"; - defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (aNbLights); - aProgramSrc->SetNbShadowMaps (aNbShadowMaps); - aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); - aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); - - const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramPhong (myLightSourceState.LightSources(), theBits, theIsFlatNormal, theIsPBR, aNbShadowMaps); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, theProgram)) { @@ -2897,201 +1271,34 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha } // ======================================================================= -// function : prepareStdProgramStereo +// function : BindStereoProgram // purpose : // ======================================================================= -Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram, - const Graphic3d_StereoMode theStereoMode) +Standard_Boolean OpenGl_ShaderManager::BindStereoProgram (Graphic3d_StereoMode theStereoMode) { - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - TCollection_AsciiString aSrcVert = - EOL"void main()" - EOL"{" - EOL" TexCoord = occVertex.zw;" - EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);" - EOL"}"; - - TCollection_AsciiString aSrcFrag; - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT)); - const char* aName = "stereo"; - switch (theStereoMode) + if (theStereoMode < 0 || theStereoMode >= Graphic3d_StereoMode_NB) { - case Graphic3d_StereoMode_Anaglyph: - { - aName = "anaglyph"; - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT)); - const TCollection_AsciiString aNormalize = mySRgbState - ? EOL"#define sRgb2linear(theColor) theColor" - EOL"#define linear2sRgb(theColor) theColor" - : EOL"#define sRgb2linear(theColor) pow(theColor, vec4(2.2, 2.2, 2.2, 1.0))" - EOL"#define linear2sRgb(theColor) pow(theColor, 1.0 / vec4(2.2, 2.2, 2.2, 1.0))"; - aSrcFrag = aNormalize - + EOL"void main()" - EOL"{" - EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" - EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" - EOL" aColorL = sRgb2linear (aColorL);" - EOL" aColorR = sRgb2linear (aColorR);" - EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;" - EOL" occSetFragColor (linear2sRgb (aColor));" - EOL"}"; - break; - } - case Graphic3d_StereoMode_RowInterlaced: - { - aName = "row-interlaced"; - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" - EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" - EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)" - EOL" {" - EOL" occSetFragColor (aColorL);" - EOL" }" - EOL" else" - EOL" {" - EOL" occSetFragColor (aColorR);" - EOL" }" - EOL"}"; - break; - } - case Graphic3d_StereoMode_ColumnInterlaced: - { - aName = "column-interlaced"; - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" - EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" - EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)" - EOL" {" - EOL" occSetFragColor (aColorL);" - EOL" }" - EOL" else" - EOL" {" - EOL" occSetFragColor (aColorR);" - EOL" }" - EOL"}"; - break; - } - case Graphic3d_StereoMode_ChessBoard: - { - aName = "chessboard"; - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" - EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" - EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;" - EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;" - EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))" - EOL" {" - EOL" occSetFragColor (aColorL);" - EOL" }" - EOL" else" - EOL" {" - EOL" occSetFragColor (aColorR);" - EOL" }" - EOL"}"; - break; - } - case Graphic3d_StereoMode_SideBySide: - { - aName = "sidebyside"; - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);" - EOL" if (TexCoord.x > 0.5)" - EOL" {" - EOL" aTexCoord.x -= 1.0;" - EOL" }" - EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);" - EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);" - EOL" if (TexCoord.x <= 0.5)" - EOL" {" - EOL" occSetFragColor (aColorL);" - EOL" }" - EOL" else" - EOL" {" - EOL" occSetFragColor (aColorR);" - EOL" }" - EOL"}"; - break; - } - case Graphic3d_StereoMode_OverUnder: - { - aName = "overunder"; - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);" - EOL" if (TexCoord.y > 0.5)" - EOL" {" - EOL" aTexCoord.y -= 1.0;" - EOL" }" - EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);" - EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);" - EOL" if (TexCoord.y <= 0.5)" - EOL" {" - EOL" occSetFragColor (aColorL);" - EOL" }" - EOL" else" - EOL" {" - EOL" occSetFragColor (aColorR);" - EOL" }" - EOL"}"; - break; - } - case Graphic3d_StereoMode_QuadBuffer: - case Graphic3d_StereoMode_SoftPageFlip: - case Graphic3d_StereoMode_OpenVR: - default: - { - /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer]; - if (!aProgram.IsNull()) - { - return aProgram->IsValid(); - }*/ - aSrcFrag = - EOL"void main()" - EOL"{" - EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);" - EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);" - EOL" aColorL.b = 0.0;" - EOL" aColorL.g = 0.0;" - EOL" aColorR.r = 0.0;" - EOL" occSetFragColor (aColorL + aColorR);" - EOL"}"; - break; - } + return false; } - defaultGlslVersion (aProgramSrc, aName, 0); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[theStereoMode]; + if (!aProgram.IsNull()) + { + return myContext->BindProgram (aProgram); + } + + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramStereo (theStereoMode); TCollection_AsciiString aKey; - if (!Create (aProgramSrc, aKey, theProgram)) + if (!Create (aProgramSrc, aKey, aProgram)) { - theProgram = new OpenGl_ShaderProgram(); // just mark as invalid - return Standard_False; + aProgram = new OpenGl_ShaderProgram(); // just mark as invalid + return false; } - myContext->BindProgram (theProgram); - theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0); - theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1); - myContext->BindProgram (NULL); - return Standard_True; + myContext->BindProgram (aProgram); + aProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0); + aProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1); + return true; } // ======================================================================= @@ -3100,33 +1307,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh // ======================================================================= Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox() { - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX)); - - TCollection_AsciiString aSrcVert = - EOL"void main()" - EOL"{" - EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);" - EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);" - EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;" - EOL"}"; - - TCollection_AsciiString aSrcFrag = - EOL"void main()" - EOL"{" - EOL" occSetFragColor (occColor);" - EOL"}"; - - defaultGlslVersion (aProgramSrc, "bndbox", 0); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = Graphic3d_ShaderManager::getStdProgramBoundBox(); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, myBoundBoxProgram)) { @@ -3180,50 +1361,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox() // ======================================================================= Standard_Boolean OpenGl_ShaderManager::preparePBREnvBakingProgram (Standard_Integer theIndex) { - Standard_ASSERT_RAISE (theIndex >= 0 && theIndex <= 2,""); - Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - - TCollection_AsciiString aSrcVert = TCollection_AsciiString() - + THE_FUNC_cubemap_vector_transform - + Shaders_PBREnvBaking_vs; - - TCollection_AsciiString aSrcFrag = TCollection_AsciiString() - + THE_FUNC_cubemap_vector_transform - + Shaders_PBRDistribution_glsl - + ((theIndex == 0 || theIndex == 2) ? "\n#define THE_TO_BAKE_DIFFUSE\n" : "\n#define THE_TO_BAKE_SPECULAR\n") - + (theIndex == 2 ? "\n#define THE_TO_PACK_FLOAT\n" : "") - + Shaders_PBREnvBaking_fs; - - // constant array definition requires OpenGL 2.1+ or OpenGL ES 3.0+ -#if defined(GL_ES_VERSION_2_0) - if (myContext->IsGlGreaterEqual (3, 0)) - { - aProgramSrc->SetHeader ("#version 300 es"); - } - else if (myContext->CheckExtension ("GL_EXT_shader_texture_lod")) - { - aProgramSrc->SetHeader ("#extension GL_EXT_shader_texture_lod : enable\n" - "#define textureCubeLod textureCubeLodEXT"); - } - else - { - myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, - "Warning: incomplete PBR lighting implementation due to missing OpenGL ES 3.0 or GL_EXT_shader_texture_lod support."); - } -#else - aProgramSrc->SetHeader ("#version 120"); -#endif - - static const char* THE_BAKE_NAMES[3] = { "pbr_env_baking_diffuse", "pbr_env_baking_specular", "pbr_env_baking_difffallback" }; - defaultGlslVersion (aProgramSrc, THE_BAKE_NAMES[theIndex], 0); - aProgramSrc->SetDefaultSampler (false); - aProgramSrc->SetNbLightsMax (0); - aProgramSrc->SetNbShadowMaps (0); - aProgramSrc->SetNbClipPlanesMax (0); - aProgramSrc->SetPBR (true); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + Handle(Graphic3d_ShaderProgram) aProgramSrc = getPBREnvBakingProgram (theIndex); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, myPBREnvBakingProgram[theIndex])) { @@ -3258,64 +1396,8 @@ const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram { if (myBgCubeMapProgram.IsNull()) { - myBgCubeMapProgram = new Graphic3d_ShaderProgram(); - - OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts; - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable("vec3 ViewDirection", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("samplerCube occSampler0", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX)); - aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX)); - - TCollection_AsciiString aSrcVert = TCollection_AsciiString() - + THE_FUNC_cubemap_vector_transform - + EOL"void main()" - EOL"{" - EOL" ViewDirection = cubemapVectorTransform (occVertex.xyz, uYCoeff, uZCoeff);" - EOL" vec4 aPos = occProjectionMatrix * occWorldViewMatrix * vec4(occVertex.xyz, 1.0);" - // setting Z to W ensures that final Z will be 1.0 after perspective division, (w/w=1)) - // which allows rendering skybox after everything else with depth test enabled (GL_LEQUAL) - EOL" gl_Position = aPos.xyww;" - EOL"}"; - - TCollection_AsciiString aDepthClamp; - if (!myContext->arbDepthClamp) - { - // workaround Z clamping issues on some GPUs - aDepthClamp = EOL" gl_FragDepth = clamp (gl_FragDepth, 0.0, 1.0);"; - #if defined(GL_ES_VERSION_2_0) - if (myContext->IsGlGreaterEqual (3, 0)) - { - myBgCubeMapProgram->SetHeader ("#version 300 es"); - } - else if (myContext->extFragDepth) - { - myBgCubeMapProgram->SetHeader ("#extension GL_EXT_frag_depth : enable" - EOL"#define gl_FragDepth gl_FragDepthEXT"); - } - else - { - aDepthClamp.Clear(); - } - #endif - } - - TCollection_AsciiString aSrcFrag = TCollection_AsciiString() - + EOL"#define occEnvCubemap occSampler0" - EOL"void main()" - EOL"{" - EOL" occSetFragColor (vec4(occTextureCube (occEnvCubemap, ViewDirection).rgb, 1.0));" - + aDepthClamp - + EOL"}"; - - defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0); - myBgCubeMapProgram->SetDefaultSampler (false); - myBgCubeMapProgram->SetNbLightsMax (0); - myBgCubeMapProgram->SetNbShadowMaps (0); - myBgCubeMapProgram->SetNbClipPlanesMax (0); - myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); - myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); + myBgCubeMapProgram = getBgCubeMapProgram(); } - return myBgCubeMapProgram; } @@ -3356,11 +1438,11 @@ Standard_Boolean OpenGl_ShaderManager::BindMarkerProgram (const Handle(OpenGl_Te if (!theTextures.IsNull() && theTextures->HasPointSprite()) { - aBits |= theTextures->Last()->IsAlpha() ? OpenGl_PO_PointSpriteA : OpenGl_PO_PointSprite; + aBits |= theTextures->Last()->IsAlpha() ? Graphic3d_ShaderFlags_PointSpriteA : Graphic3d_ShaderFlags_PointSprite; } else { - aBits |= OpenGl_PO_PointSimple; + aBits |= Graphic3d_ShaderFlags_PointSimple; } Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits); return bindProgramWithState (aProgram, theShadingModel); diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 44f2c2d3ac..4350e8fadd 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -16,12 +16,8 @@ #ifndef _OpenGl_ShaderManager_HeaderFile #define _OpenGl_ShaderManager_HeaderFile -#include -#include - -#include +#include #include - #include #include #include @@ -36,9 +32,9 @@ class OpenGl_VertexBuffer; typedef NCollection_Sequence OpenGl_ShaderProgramList; //! This class is responsible for managing shader programs. -class OpenGl_ShaderManager : public Standard_Transient +class OpenGl_ShaderManager : public Graphic3d_ShaderManager { - DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient) + DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderManager, Graphic3d_ShaderManager) friend class OpenGl_ShaderProgram; public: @@ -90,10 +86,10 @@ public: Handle(OpenGl_ShaderProgram)& theProgram); //! Returns list of registered shader programs. - Standard_EXPORT const OpenGl_ShaderProgramList& ShaderPrograms() const; + const OpenGl_ShaderProgramList& ShaderPrograms() const { return myProgramList; } //! Returns true if no program objects are registered in the manager. - Standard_EXPORT Standard_Boolean IsEmpty() const; + Standard_Boolean IsEmpty() const { return myProgramList.IsEmpty(); } //! Bind program for filled primitives rendering Standard_Boolean BindFaceProgram (const Handle(OpenGl_TextureSet)& theTextures, @@ -149,7 +145,7 @@ public: Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false); if (theLineType != Aspect_TOL_SOLID) { - aBits |= OpenGl_PO_StippleLine; + aBits |= Graphic3d_ShaderFlags_StippleLine; } Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits); @@ -164,21 +160,7 @@ public: const Handle(OpenGl_ShaderProgram)& theCustomProgram); //! Bind program for rendering alpha-textured font. - Standard_Boolean BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram) - { - if (!theCustomProgram.IsNull() - || myContext->caps->ffpEnable) - { - return bindProgramWithState (theCustomProgram, Graphic3d_TOSM_UNLIT); - } - - if (myFontProgram.IsNull()) - { - prepareStdProgramFont(); - } - - return bindProgramWithState (myFontProgram, Graphic3d_TOSM_UNLIT); - } + Standard_Boolean BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram); //! Bind program for outline rendering Standard_Boolean BindOutlineProgram() @@ -208,60 +190,16 @@ public: Standard_Boolean theIsFallback_sRGB); //! Bind program for blended order-independent transparency buffers compositing. - Standard_Boolean BindOitCompositingProgram (const Standard_Boolean theIsMSAAEnabled) - { - const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; - if (myOitCompositingProgram[aProgramIdx].IsNull()) - { - prepareStdProgramOitCompositing (theIsMSAAEnabled); - } - - const Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram [aProgramIdx]; - return !aProgram.IsNull() && myContext->BindProgram (aProgram); - } + Standard_EXPORT Standard_Boolean BindOitCompositingProgram (Standard_Boolean theIsMSAAEnabled); //! Bind program for Depth Peeling order-independent transparency back color blending. - Standard_Boolean BindOitDepthPeelingBlendProgram (bool theIsMSAAEnabled) - { - const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; - if (myOitDepthPeelingBlendProgram[aProgramIdx].IsNull()) - { - prepareStdProgramOitDepthPeelingBlend (theIsMSAAEnabled); - } - - const Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingBlendProgram [aProgramIdx]; - return !aProgram.IsNull() && myContext->BindProgram (aProgram); - } + Standard_EXPORT Standard_Boolean BindOitDepthPeelingBlendProgram (bool theIsMSAAEnabled); //! Bind program for Depth Peeling order-independent transparency flush. - Standard_Boolean BindOitDepthPeelingFlushProgram (bool theIsMSAAEnabled) - { - const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; - if (myOitDepthPeelingFlushProgram[aProgramIdx].IsNull()) - { - prepareStdProgramOitDepthPeelingFlush (theIsMSAAEnabled); - } - - const Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingFlushProgram [aProgramIdx]; - return !aProgram.IsNull() && myContext->BindProgram (aProgram); - } + Standard_EXPORT Standard_Boolean BindOitDepthPeelingFlushProgram (bool theIsMSAAEnabled); //! Bind program for rendering stereoscopic image. - Standard_Boolean BindStereoProgram (const Graphic3d_StereoMode theStereoMode) - { - if (theStereoMode < 0 || theStereoMode >= Graphic3d_StereoMode_NB) - { - return Standard_False; - } - - if (myStereoPrograms[theStereoMode].IsNull()) - { - prepareStdProgramStereo (myStereoPrograms[theStereoMode], theStereoMode); - } - const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[theStereoMode]; - return !aProgram.IsNull() - && myContext->BindProgram (aProgram); - } + Standard_EXPORT Standard_Boolean BindStereoProgram (Graphic3d_StereoMode theStereoMode); //! Bind program for rendering bounding box. Standard_Boolean BindBoundBoxProgram() @@ -613,20 +551,20 @@ protected: Standard_Integer aBits = 0; if (myContext->Clipping().HasClippingChains()) { - aBits |= OpenGl_PO_ClipChains; + aBits |= Graphic3d_ShaderFlags_ClipChains; } if (aNbPlanes == 1) { - aBits |= OpenGl_PO_ClipPlanes1; + aBits |= Graphic3d_ShaderFlags_ClipPlanes1; } else if (aNbPlanes == 2) { - aBits |= OpenGl_PO_ClipPlanes2; + aBits |= Graphic3d_ShaderFlags_ClipPlanes2; } else { - aBits |= OpenGl_PO_ClipPlanesN; + aBits |= Graphic3d_ShaderFlags_ClipPlanesN; } return aBits; } @@ -642,47 +580,47 @@ protected: Standard_Integer aBits = 0; if (theAlphaMode == Graphic3d_AlphaMode_Mask) { - aBits |= OpenGl_PO_AlphaTest; + aBits |= Graphic3d_ShaderFlags_AlphaTest; } aBits |= getClipPlaneBits(); if (theEnableMeshEdges && myContext->hasGeometryStage != OpenGl_FeatureNotAvailable) { - aBits |= OpenGl_PO_MeshEdges; + aBits |= Graphic3d_ShaderFlags_MeshEdges; if (theInteriorStyle == Aspect_IS_HOLLOW) { - aBits |= OpenGl_PO_AlphaTest; + aBits |= Graphic3d_ShaderFlags_AlphaTest; } } if (theEnableEnvMap) { // Environment map overwrites material texture - aBits |= OpenGl_PO_TextureEnv; + aBits |= Graphic3d_ShaderFlags_TextureEnv; } else if (!theTextures.IsNull() && theTextures->HasNonPointSprite()) { - aBits |= OpenGl_PO_TextureRGB; + aBits |= Graphic3d_ShaderFlags_TextureRGB; if ((theTextures->TextureSetBits() & Graphic3d_TextureSetBits_Normal) != 0) { - aBits |= OpenGl_PO_TextureNormal; + aBits |= Graphic3d_ShaderFlags_TextureNormal; } } if (theHasVertColor && theInteriorStyle != Aspect_IS_HIDDENLINE) { - aBits |= OpenGl_PO_VertColor; + aBits |= Graphic3d_ShaderFlags_VertColor; } if (myOitState.ActiveMode() == Graphic3d_RTM_BLEND_OIT) { - aBits |= OpenGl_PO_WriteOit; + aBits |= Graphic3d_ShaderFlags_WriteOit; } else if (myOitState.ActiveMode() == Graphic3d_RTM_DEPTH_PEELING_OIT) { - aBits |= OpenGl_PO_OitDepthPeeling; + aBits |= Graphic3d_ShaderFlags_OitDepthPeeling; } return aBits; } @@ -692,7 +630,7 @@ protected: Standard_Integer theBits) { if (theShadingModel == Graphic3d_TOSM_UNLIT - || (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureEnv) + || (theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureEnv) { // If environment map is enabled lighting calculations are // not needed (in accordance with default OCCT behavior) @@ -712,30 +650,6 @@ protected: return aProgram; } - //! Prepare standard GLSL program for accessing point sprite alpha. - Standard_EXPORT TCollection_AsciiString pointSpriteAlphaSrc (Standard_Integer theBits); - - //! Prepare standard GLSL program for computing point sprite shading. - Standard_EXPORT TCollection_AsciiString pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc, - Standard_Integer theBits); - - //! Prepare standard GLSL program for textured font. - Standard_EXPORT Standard_Boolean prepareStdProgramFont(); - - //! Prepare standard GLSL program for FBO blit operation. - Standard_EXPORT Standard_Boolean prepareStdProgramFboBlit (Handle(OpenGl_ShaderProgram)& theProgram, - Standard_Integer theNbSamples, - Standard_Boolean theIsFallback_sRGB); - - //! Prepare standard GLSL programs for OIT compositing operation. - Standard_EXPORT Standard_Boolean prepareStdProgramOitCompositing (const Standard_Boolean theMsaa); - - //! Prepare standard GLSL programs for OIT Depth Peeling blend operation. - Standard_EXPORT Standard_Boolean prepareStdProgramOitDepthPeelingBlend (Standard_Boolean theMsaa); - - //! Prepare standard GLSL programs for OIT Depth Peeling flush operation. - Standard_EXPORT Standard_Boolean prepareStdProgramOitDepthPeelingFlush (Standard_Boolean theMsaa); - //! Prepare standard GLSL program without lighting. Standard_EXPORT Standard_Boolean prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram, Standard_Integer theBits, @@ -771,18 +685,6 @@ protected: const Standard_Boolean theIsFlatNormal = false, const Standard_Boolean theIsPBR = false); - //! Define computeLighting GLSL function depending on current lights configuration - //! @param theNbLights [out] number of defined light sources - //! @param theHasVertColor [in] flag to use getVertColor() instead of Ambient and Diffuse components of active material - //! @param theIsPBR [in] flag to activate PBR pipeline - //! @param theHasEmissive [in] flag to include emissive - //! @param theHasShadowMap [in] flag to include shadow map - Standard_EXPORT TCollection_AsciiString stdComputeLighting (Standard_Integer& theNbLights, - Standard_Boolean theHasVertColor, - Standard_Boolean theIsPBR, - Standard_Boolean theHasEmissive, - Standard_Boolean theHasShadowMap); - //! Bind specified program to current context and apply state. Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram, Graphic3d_TypeOfShadingModel theShadingModel); @@ -790,29 +692,9 @@ protected: //! Set pointer myLightPrograms to active lighting programs set from myMapOfLightPrograms Standard_EXPORT void switchLightPrograms(); - //! Prepare standard GLSL program for stereoscopic image. - Standard_EXPORT Standard_Boolean prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram, - const Graphic3d_StereoMode theStereoMode); - //! Prepare standard GLSL program for bounding box. Standard_EXPORT Standard_Boolean prepareStdProgramBoundBox(); - //! Prepare GLSL version header. - Standard_EXPORT Standard_Integer defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, - const TCollection_AsciiString& theName, - Standard_Integer theBits, - bool theUsesDerivates = false) const; - - //! Prepare GLSL version header for OIT composition programs. - Standard_EXPORT void defaultOitGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, - const TCollection_AsciiString& theName, - bool theMsaa) const; - - //! Prepare GLSL source for geometry shader according to parameters. - Standard_EXPORT TCollection_AsciiString prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms, - OpenGl_ShaderObject::ShaderVariableList& theStageInOuts, - Standard_Integer theBits); - //! Prepare GLSL source for IBL generation used in PBR pipeline. Standard_EXPORT Standard_Boolean preparePBREnvBakingProgram (Standard_Integer theIndex); @@ -893,7 +775,6 @@ protected: mutable Handle(OpenGl_PBREnvironment) myPBREnvironment; //!< manager of IBL maps used in PBR pipeline OpenGl_Context* myContext; //!< OpenGL context - Standard_Boolean mySRgbState; //!< track sRGB state protected: @@ -917,6 +798,4 @@ protected: }; -DEFINE_STANDARD_HANDLE(OpenGl_ShaderManager, Standard_Transient) - #endif // _OpenGl_ShaderManager_HeaderFile diff --git a/src/OpenGl/OpenGl_ShaderObject.cxx b/src/OpenGl/OpenGl_ShaderObject.cxx index abb78f6b7e..f9c5d4d813 100755 --- a/src/OpenGl/OpenGl_ShaderObject.cxx +++ b/src/OpenGl/OpenGl_ShaderObject.cxx @@ -64,143 +64,6 @@ static TCollection_AsciiString getShaderTypeString (GLenum theType) return "Shader"; } -// ======================================================================= -// function : CreateFromSource -// purpose : -// ======================================================================= -Handle(Graphic3d_ShaderObject) OpenGl_ShaderObject::CreateFromSource (TCollection_AsciiString& theSource, - Graphic3d_TypeOfShaderObject theType, - const ShaderVariableList& theUniforms, - const ShaderVariableList& theStageInOuts, - const TCollection_AsciiString& theInName, - const TCollection_AsciiString& theOutName, - Standard_Integer theNbGeomInputVerts) -{ - if (theSource.IsEmpty()) - { - return Handle(Graphic3d_ShaderObject)(); - } - - TCollection_AsciiString aSrcUniforms, aSrcInOuts, aSrcInStructs, aSrcOutStructs; - for (ShaderVariableList::Iterator anUniformIter (theUniforms); anUniformIter.More(); anUniformIter.Next()) - { - const ShaderVariable& aVar = anUniformIter.Value(); - if ((aVar.Stages & theType) != 0) - { - aSrcUniforms += TCollection_AsciiString("\nuniform ") + aVar.Name + ";"; - } - } - for (ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next()) - { - const ShaderVariable& aVar = aVarListIter.Value(); - Standard_Integer aStageLower = IntegerLast(), aStageUpper = IntegerFirst(); - Standard_Integer aNbStages = 0; - for (Standard_Integer aStageIter = Graphic3d_TOS_VERTEX; aStageIter <= (Standard_Integer )Graphic3d_TOS_COMPUTE; aStageIter = aStageIter << 1) - { - if ((aVar.Stages & aStageIter) != 0) - { - ++aNbStages; - aStageLower = Min (aStageLower, aStageIter); - aStageUpper = Max (aStageUpper, aStageIter); - } - } - if ((Standard_Integer )theType < aStageLower - || (Standard_Integer )theType > aStageUpper) - { - continue; - } - - const Standard_Boolean hasGeomStage = theNbGeomInputVerts > 0 - && aStageLower < Graphic3d_TOS_GEOMETRY - && aStageUpper >= Graphic3d_TOS_GEOMETRY; - const Standard_Boolean isAllStagesVar = aStageLower == Graphic3d_TOS_VERTEX - && aStageUpper == Graphic3d_TOS_FRAGMENT; - if (hasGeomStage - || !theInName.IsEmpty() - || !theOutName.IsEmpty()) - { - if (aSrcInStructs.IsEmpty() - && aSrcOutStructs.IsEmpty() - && isAllStagesVar) - { - if (theType == aStageLower) - { - aSrcOutStructs = "\nout VertexData\n{"; - } - else if (theType == aStageUpper) - { - aSrcInStructs = "\nin VertexData\n{"; - } - else // requires theInName/theOutName - { - aSrcInStructs = "\nin VertexData\n{"; - aSrcOutStructs = "\nout VertexData\n{"; - } - } - } - - if (isAllStagesVar - && (!aSrcInStructs.IsEmpty() - || !aSrcOutStructs.IsEmpty())) - { - if (!aSrcInStructs.IsEmpty()) - { - aSrcInStructs += TCollection_AsciiString("\n ") + aVar.Name + ";"; - } - if (!aSrcOutStructs.IsEmpty()) - { - aSrcOutStructs += TCollection_AsciiString("\n ") + aVar.Name + ";"; - } - } - else - { - if (theType == aStageLower) - { - aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_OUT ") + aVar.Name + ";"; - } - else if (theType == aStageUpper) - { - aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_IN ") + aVar.Name + ";"; - } - } - } - - if (theType == Graphic3d_TOS_GEOMETRY) - { - aSrcUniforms.Prepend (TCollection_AsciiString() - + "\nlayout (triangles) in;" - "\nlayout (triangle_strip, max_vertices = " + theNbGeomInputVerts + ") out;"); - } - if (!aSrcInStructs.IsEmpty() - && theType == Graphic3d_TOS_GEOMETRY) - { - aSrcInStructs += TCollection_AsciiString ("\n} ") + theInName + "[" + theNbGeomInputVerts + "];"; - } - else if (!aSrcInStructs.IsEmpty()) - { - aSrcInStructs += "\n}"; - if (!theInName.IsEmpty()) - { - aSrcInStructs += " "; - aSrcInStructs += theInName; - } - aSrcInStructs += ";"; - } - if (!aSrcOutStructs.IsEmpty()) - { - aSrcOutStructs += "\n}"; - if (!theOutName.IsEmpty()) - { - aSrcOutStructs += " "; - aSrcOutStructs += theOutName; - } - aSrcOutStructs += ";"; - } - - theSource.Prepend (aSrcUniforms + aSrcInStructs + aSrcOutStructs + aSrcInOuts); - return Graphic3d_ShaderObject::CreateFromSource (theType, theSource); -} - // ======================================================================= // function : OpenGl_ShaderObject // purpose : Creates uninitialized shader object diff --git a/src/OpenGl/OpenGl_ShaderObject.hxx b/src/OpenGl/OpenGl_ShaderObject.hxx index 0d90082fb9..4e4b5965b8 100755 --- a/src/OpenGl/OpenGl_ShaderObject.hxx +++ b/src/OpenGl/OpenGl_ShaderObject.hxx @@ -31,46 +31,6 @@ public: //! Non-valid shader name. static const GLuint NO_SHADER = 0; -public: - - //! Structure defining shader uniform or in/out variable. - struct ShaderVariable - { - TCollection_AsciiString Name; //!< variable name - Standard_Integer Stages; //!< active stages as Graphic3d_TypeOfShaderObject bits; - //! for in/out variables, intermediate stages will be automatically filled - - //! Create new shader variable. - ShaderVariable (const TCollection_AsciiString& theVarName, Standard_Integer theShaderStageBits) : Name (theVarName), Stages (theShaderStageBits) {} - - //! Empty constructor. - ShaderVariable() : Stages (0) {} - }; - - //! List of variable of shader program. - typedef NCollection_Sequence ShaderVariableList; - - //! This is a preprocessor for Graphic3d_ShaderObject::CreateFromSource() function. - //! Creates a new shader object from specified source according to list of uniforms and in/out variables. - //! @param theSource shader object source code to modify - //! @param theType shader object type to create - //! @param theUniforms list of uniform variables - //! @param theStageInOuts list of stage in/out variables - //! @param theInName name of input variables block; - //! can be empty for accessing each variable without block prefix - //! (mandatory for stages accessing both inputs and outputs) - //! @param theOutName name of output variables block; - //! can be empty for accessing each variable without block prefix - //! (mandatory for stages accessing both inputs and outputs) - //! @param theNbGeomInputVerts number of geometry shader input vertexes - Standard_EXPORT static Handle(Graphic3d_ShaderObject) CreateFromSource (TCollection_AsciiString& theSource, - Graphic3d_TypeOfShaderObject theType, - const ShaderVariableList& theUniforms, - const ShaderVariableList& theStageInOuts, - const TCollection_AsciiString& theInName = TCollection_AsciiString(), - const TCollection_AsciiString& theOutName = TCollection_AsciiString(), - Standard_Integer theNbGeomInputVerts = 0); - public: //! Creates uninitialized shader object.