diff --git a/src/Draw/TKViewerTest/ViewerTest/ViewerTest_OpenGlCommands.cxx b/src/Draw/TKViewerTest/ViewerTest/ViewerTest_OpenGlCommands.cxx index 6fd3496b09..6e08a55b5c 100644 --- a/src/Draw/TKViewerTest/ViewerTest/ViewerTest_OpenGlCommands.cxx +++ b/src/Draw/TKViewerTest/ViewerTest/ViewerTest_OpenGlCommands.cxx @@ -25,6 +25,8 @@ #include #include +#include +#include #include #include #include @@ -296,6 +298,59 @@ static int VShaderProg(Draw_Interpretor&, int theArgNb, const char** theArgVec) TCollection_AsciiString aName = theArgVec[++anArgIter]; aProgram->PushVariableFloat(aName, float(Draw::Atof(theArgVec[++anArgIter]))); } + else if (!aProgram.IsNull() && anArg == "-vec2" && anArgIter + 3 < theArgNb) + { + const TCollection_AsciiString aName = theArgVec[++anArgIter]; + const NCollection_Vec2 aVec(float(Draw::Atof(theArgVec[anArgIter + 1])), + float(Draw::Atof(theArgVec[anArgIter + 2]))); + anArgIter += 2; + aProgram->PushVariableVec2(aName, aVec); + } + else if (!aProgram.IsNull() && anArg == "-vec3" && anArgIter + 4 < theArgNb) + { + const TCollection_AsciiString aName = theArgVec[++anArgIter]; + const NCollection_Vec3 aVec(float(Draw::Atof(theArgVec[anArgIter + 1])), + float(Draw::Atof(theArgVec[anArgIter + 2])), + float(Draw::Atof(theArgVec[anArgIter + 3]))); + anArgIter += 3; + aProgram->PushVariableVec3(aName, aVec); + } + else if (!aProgram.IsNull() && anArg == "-vec4" && anArgIter + 5 < theArgNb) + { + const TCollection_AsciiString aName = theArgVec[++anArgIter]; + const NCollection_Vec4 aVec(float(Draw::Atof(theArgVec[anArgIter + 1])), + float(Draw::Atof(theArgVec[anArgIter + 2])), + float(Draw::Atof(theArgVec[anArgIter + 3])), + float(Draw::Atof(theArgVec[anArgIter + 4]))); + anArgIter += 4; + aProgram->PushVariableVec4(aName, aVec); + } + else if (!aProgram.IsNull() && anArg == "-mat3" && anArgIter + 10 < theArgNb) + { + const TCollection_AsciiString aName = theArgVec[++anArgIter]; + NCollection_Mat3 aMat; + for (int aRowIter = 0; aRowIter < 3; ++aRowIter) + { + for (int aColIter = 0; aColIter < 3; ++aColIter) + { + aMat.SetValue(aRowIter, aColIter, float(Draw::Atof(theArgVec[++anArgIter]))); + } + } + aProgram->PushVariableMat3(aName, aMat); + } + else if (!aProgram.IsNull() && anArg == "-mat4" && anArgIter + 17 < theArgNb) + { + const TCollection_AsciiString aName = theArgVec[++anArgIter]; + NCollection_Mat4 aMat; + for (int aRowIter = 0; aRowIter < 4; ++aRowIter) + { + for (int aColIter = 0; aColIter < 4; ++aColIter) + { + aMat.SetValue(aRowIter, aColIter, float(Draw::Atof(theArgVec[++anArgIter]))); + } + } + aProgram->PushVariableMat4(aName, aMat); + } else if (!aProgram.IsNull() && aProgram->ShaderObjects().IsEmpty() && (anArg == "-off" || anArg == "off")) { @@ -1175,6 +1230,8 @@ vshader name -vert VertexShader -frag FragmentShader [-geom GeometryShader] [-header VersionHeader] [-tessControl TessControlShader -tessEval TessEvaluationShader] [-uniform Name FloatValue] + [-vec2 Name X Y] [-vec3 Name X Y Z] [-vec4 Name X Y Z W] + [-mat3 Name V1..V9] [-mat4 Name V1..V16] [-defaultSampler {0|1}]=1 Assign custom GLSL program to presentation aspects. )" /* [vshader] */); diff --git a/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.cxx b/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.cxx index d6e1fce99a..c6de06eee6 100644 --- a/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.cxx @@ -135,7 +135,11 @@ OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector() Graphic3d_UniformValueTypeID>::ID, new OpenGl_VariableSetter>())( Graphic3d_UniformValueTypeID>::ID, - new OpenGl_VariableSetter>()); + new OpenGl_VariableSetter>())( + Graphic3d_UniformValueTypeID>::ID, + new OpenGl_VariableSetter>())( + Graphic3d_UniformValueTypeID>::ID, + new OpenGl_VariableSetter>()); } // ======================================================================= @@ -1267,6 +1271,26 @@ bool OpenGl_ShaderProgram::SetUniform(const occ::handle& theCtx, return true; } +//================================================================================================= + +bool OpenGl_ShaderProgram::SetUniform(const occ::handle& theCtx, + GLint theLocation, + const NCollection_Mat3& theValue, + GLboolean theTranspose) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return false; + } + + theCtx->core20fwd->glUniformMatrix3fv(theLocation, + 1, + GL_FALSE, + theTranspose ? theValue.Transposed().GetData() + : theValue.GetData()); + return true; +} + // ======================================================================= // function : SetUniform // purpose : Specifies the value of the floating-point uniform 4x4 matrix diff --git a/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.hxx b/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.hxx index 9affc115eb..a61e6f20e9 100644 --- a/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/Visualization/TKOpenGl/OpenGl/OpenGl_ShaderProgram.hxx @@ -496,6 +496,23 @@ public: GLuint theCount, const NCollection_Mat3* theData); + //! Specifies the value of the float uniform 3x3 matrix. + //! Wrapper for glUniformMatrix3fv() + bool SetUniform(const occ::handle& theCtx, + const GLchar* theName, + const NCollection_Mat3& theValue, + GLboolean theTranspose = GL_FALSE) + { + return SetUniform(theCtx, GetUniformLocation(theCtx, theName), theValue, theTranspose); + } + + //! Specifies the value of the float uniform 3x3 matrix. + //! Wrapper for glUniformMatrix3fv() + Standard_EXPORT bool SetUniform(const occ::handle& theCtx, + GLint theLocation, + const NCollection_Mat3& theValue, + GLboolean theTranspose = GL_FALSE); + //! Specifies the value of the float uniform 4x4 matrix. //! Wrapper for glUniformMatrix4fv() bool SetUniform(const occ::handle& theCtx, diff --git a/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderProgram.hxx index 81de88381b..36d653d511 100644 --- a/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -244,6 +244,20 @@ public: return PushVariable(theName, theValue); } + //! Pushes mat3 uniform. + bool PushVariableMat3(const TCollection_AsciiString& theName, + const NCollection_Mat3& theValue) + { + return PushVariable(theName, theValue); + } + + //! Pushes mat4 uniform. + bool PushVariableMat4(const TCollection_AsciiString& theName, + const NCollection_Mat4& theValue) + { + return PushVariable(theName, theValue); + } + public: //! The path to GLSL programs determined from CSF_ShadersDirectory or CASROOT environment //! variables. diff --git a/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.cxx b/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.cxx index ddaafe1906..e89a4900c9 100644 --- a/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.cxx +++ b/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.cxx @@ -26,6 +26,8 @@ template struct Graphic3d_UniformValue>; template struct Graphic3d_UniformValue>; template struct Graphic3d_UniformValue>; template struct Graphic3d_UniformValue>; +template struct Graphic3d_UniformValue>; +template struct Graphic3d_UniformValue>; // ======================================================================= // function : ~Graphic3d_ValueInterface diff --git a/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.hxx b/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.hxx index ce23f0104f..3c206f37a2 100644 --- a/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.hxx +++ b/src/Visualization/TKService/Graphic3d/Graphic3d_ShaderVariable.hxx @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -101,6 +102,18 @@ struct Graphic3d_UniformValueTypeID> static const size_t ID = __LINE__; }; +template <> +struct Graphic3d_UniformValueTypeID> +{ + static const size_t ID = __LINE__; +}; + +template <> +struct Graphic3d_UniformValueTypeID> +{ + static const size_t ID = __LINE__; +}; + //! Describes specific value of custom uniform variable. template struct Graphic3d_UniformValue : public Graphic3d_ValueInterface @@ -142,6 +155,12 @@ typedef Graphic3d_UniformValue> Graphic3d_UniformVec3; //! Floating-point uniform 4D vector. typedef Graphic3d_UniformValue> Graphic3d_UniformVec4; +//! Floating-point uniform 3x3 matrix. +typedef Graphic3d_UniformValue> Graphic3d_UniformMat3; + +//! Floating-point uniform 4x4 matrix. +typedef Graphic3d_UniformValue> Graphic3d_UniformMat4; + //! Describes custom uniform shader variable. class Graphic3d_ShaderVariable : public Standard_Transient { diff --git a/tests/opengl/data/shaderprog/uniforms b/tests/opengl/data/shaderprog/uniforms new file mode 100644 index 0000000000..c53f1e775e --- /dev/null +++ b/tests/opengl/data/shaderprog/uniforms @@ -0,0 +1,65 @@ +puts "========" +puts "Test custom uniform variables: -vec2, -vec3, -vec4, -mat3, -mat4" +puts "========" + +pload MODELING VISUALIZATION + +# draw a box +box b 1 2 3 +vclear +vclose ALL +vinit View1 +vsetdispmode 1 +vaxo +vdisplay b +vfit +vrotate 0.2 0.0 0.0 + +set aGlslVer "#version 110" +if { [vdriver -default] == "TKOpenGles" } { set aGlslVer "#version 300 es" } + +# vertex shader applying a mat4 uniform transform and passing a vec4 color to fragment +set aShaderVert " +uniform mat4 uModelTrsf; +uniform mat3 uNormTrsf; +uniform vec4 uColor; +uniform vec3 uLightDir; +uniform vec2 uScale; +THE_SHADER_OUT vec4 vColor; +THE_SHADER_OUT vec3 vNormal; +void main() { + vec4 aPos = uModelTrsf * occVertex; + aPos.xy *= uScale; + vNormal = normalize(uNormTrsf * occNormal.xyz); + vColor = uColor; + gl_Position = occProjectionMatrix * occWorldViewMatrix * aPos; +}" + +# fragment shader using the passed color and simple diffuse lighting +set aShaderFrag " +uniform vec3 uLightDir; +THE_SHADER_IN vec4 vColor; +THE_SHADER_IN vec3 vNormal; +void main() { + float aNdotL = max(dot(normalize(vNormal), normalize(uLightDir)), 0.2); + occSetFragColor(vec4(vColor.rgb * aNdotL, vColor.a)); +}" + +# identity mat4 (row-major: 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1) +# identity mat3 (row-major: 1 0 0 0 1 0 0 0 1) +vshaderprog b -vert $aShaderVert -frag $aShaderFrag -header "$aGlslVer" \ + -mat4 uModelTrsf 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 \ + -mat3 uNormTrsf 1 0 0 0 1 0 0 0 1 \ + -vec4 uColor 0.2 0.6 1.0 1.0 \ + -vec3 uLightDir 0.0 0.0 1.0 \ + -vec2 uScale 1.0 1.0 +vdump $::imagedir/${::casename}_identity.png + +# apply a non-identity mat4 (translation by 0.5 in X) +vshaderprog b -vert $aShaderVert -frag $aShaderFrag -header "$aGlslVer" \ + -mat4 uModelTrsf 1 0 0 0.5 0 1 0 0 0 0 1 0 0 0 0 1 \ + -mat3 uNormTrsf 1 0 0 0 1 0 0 0 1 \ + -vec4 uColor 1.0 0.4 0.2 1.0 \ + -vec3 uLightDir 1.0 1.0 1.0 \ + -vec2 uScale 0.8 0.8 +vdump $::imagedir/${::casename}_translated.png