1 // Created on: 2013-09-19
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
20 #include <OSD_File.hxx>
21 #include <OSD_Protection.hxx>
23 #include <Standard_Assert.hxx>
24 #include <Standard_Atomic.hxx>
25 #include <TCollection_ExtendedString.hxx>
27 #include <OpenGl_Context.hxx>
28 #include <OpenGl_ShaderProgram.hxx>
29 #include <OpenGl_ShaderManager.hxx>
31 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
32 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
34 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
36 // Declare OCCT-specific OpenGL/GLSL shader variables
37 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
39 /* OpenGl_OCC_MODEL_WORLD_MATRIX */ "occModelWorldMatrix",
40 /* OpenGl_OCC_WORLD_VIEW_MATRIX */ "occWorldViewMatrix",
41 /* OpenGl_OCC_PROJECTION_MATRIX */ "occProjectionMatrix",
42 /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE */ "occModelWorldMatrixInverse",
43 /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE */ "occWorldViewMatrixInverse",
44 /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE */ "occProjectionMatrixInverse",
45 /* OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE */ "occModelWorldMatrixTranspose",
46 /* OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE */ "occWorldViewMatrixTranspose",
47 /* OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE */ "occProjectionMatrixTranspose",
48 /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE */ "occModelWorldMatrixInverseTranspose",
49 /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE */ "occWorldViewMatrixInverseTranspose",
50 /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE */ "occProjectionMatrixInverseTranspose",
52 /* OpenGl_OCC_CLIP_PLANE_0_EQUATION */ "occClipPlanes[0].Equation",
53 /* OpenGl_OCC_CLIP_PLANE_1_EQUATION */ "occClipPlanes[1].Equation",
54 /* OpenGl_OCC_CLIP_PLANE_2_EQUATION */ "occClipPlanes[2].Equation",
55 /* OpenGl_OCC_CLIP_PLANE_3_EQUATION */ "occClipPlanes[3].Equation",
56 /* OpenGl_OCC_CLIP_PLANE_4_EQUATION */ "occClipPlanes[4].Equation",
57 /* OpenGl_OCC_CLIP_PLANE_5_EQUATION */ "occClipPlanes[5].Equation",
58 /* OpenGl_OCC_CLIP_PLANE_6_EQUATION */ "occClipPlanes[6].Equation",
59 /* OpenGl_OCC_CLIP_PLANE_7_EQUATION */ "occClipPlanes[7].Equation",
61 /* OpenGl_OCC_CLIP_PLANE_0_SPACE */ "occClipPlanes[0].Space",
62 /* OpenGl_OCC_CLIP_PLANE_1_SPACE */ "occClipPlanes[1].Space",
63 /* OpenGl_OCC_CLIP_PLANE_2_SPACE */ "occClipPlanes[2].Space",
64 /* OpenGl_OCC_CLIP_PLANE_3_SPACE */ "occClipPlanes[3].Space",
65 /* OpenGl_OCC_CLIP_PLANE_4_SPACE */ "occClipPlanes[4].Space",
66 /* OpenGl_OCC_CLIP_PLANE_5_SPACE */ "occClipPlanes[5].Space",
67 /* OpenGl_OCC_CLIP_PLANE_6_SPACE */ "occClipPlanes[6].Space",
68 /* OpenGl_OCC_CLIP_PLANE_7_SPACE */ "occClipPlanes[7].Space",
70 /* OpenGl_OCC_LIGHT_SOURCE_COUNT */ "occLightSourcesCount",
72 /* OpenGl_OCC_LIGHT_SOURCE_0_TYPE */ "occLightSources[0].Type",
73 /* OpenGl_OCC_LIGHT_SOURCE_1_TYPE */ "occLightSources[1].Type",
74 /* OpenGl_OCC_LIGHT_SOURCE_2_TYPE */ "occLightSources[2].Type",
75 /* OpenGl_OCC_LIGHT_SOURCE_3_TYPE */ "occLightSources[3].Type",
76 /* OpenGl_OCC_LIGHT_SOURCE_4_TYPE */ "occLightSources[4].Type",
77 /* OpenGl_OCC_LIGHT_SOURCE_5_TYPE */ "occLightSources[5].Type",
78 /* OpenGl_OCC_LIGHT_SOURCE_6_TYPE */ "occLightSources[6].Type",
79 /* OpenGl_OCC_LIGHT_SOURCE_7_TYPE */ "occLightSources[7].Type",
81 /* OpenGl_OCC_LIGHT_SOURCE_0_HEAD */ "occLightSources[0].Head",
82 /* OpenGl_OCC_LIGHT_SOURCE_1_HEAD */ "occLightSources[1].Head",
83 /* OpenGl_OCC_LIGHT_SOURCE_2_HEAD */ "occLightSources[2].Head",
84 /* OpenGl_OCC_LIGHT_SOURCE_3_HEAD */ "occLightSources[3].Head",
85 /* OpenGl_OCC_LIGHT_SOURCE_4_HEAD */ "occLightSources[4].Head",
86 /* OpenGl_OCC_LIGHT_SOURCE_5_HEAD */ "occLightSources[5].Head",
87 /* OpenGl_OCC_LIGHT_SOURCE_6_HEAD */ "occLightSources[6].Head",
88 /* OpenGl_OCC_LIGHT_SOURCE_7_HEAD */ "occLightSources[7].Head",
90 /* OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT */ "occLightSources[0].Ambient",
91 /* OpenGl_OCC_LIGHT_SOURCE_1_AMBIENT */ "occLightSources[1].Ambient",
92 /* OpenGl_OCC_LIGHT_SOURCE_2_AMBIENT */ "occLightSources[2].Ambient",
93 /* OpenGl_OCC_LIGHT_SOURCE_3_AMBIENT */ "occLightSources[3].Ambient",
94 /* OpenGl_OCC_LIGHT_SOURCE_4_AMBIENT */ "occLightSources[4].Ambient",
95 /* OpenGl_OCC_LIGHT_SOURCE_5_AMBIENT */ "occLightSources[5].Ambient",
96 /* OpenGl_OCC_LIGHT_SOURCE_6_AMBIENT */ "occLightSources[6].Ambient",
97 /* OpenGl_OCC_LIGHT_SOURCE_7_AMBIENT */ "occLightSources[7].Ambient",
99 /* OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE */ "occLightSources[0].Diffuse",
100 /* OpenGl_OCC_LIGHT_SOURCE_1_DIFFUSE */ "occLightSources[1].Diffuse",
101 /* OpenGl_OCC_LIGHT_SOURCE_2_DIFFUSE */ "occLightSources[2].Diffuse",
102 /* OpenGl_OCC_LIGHT_SOURCE_3_DIFFUSE */ "occLightSources[3].Diffuse",
103 /* OpenGl_OCC_LIGHT_SOURCE_4_DIFFUSE */ "occLightSources[4].Diffuse",
104 /* OpenGl_OCC_LIGHT_SOURCE_5_DIFFUSE */ "occLightSources[5].Diffuse",
105 /* OpenGl_OCC_LIGHT_SOURCE_6_DIFFUSE */ "occLightSources[6].Diffuse",
106 /* OpenGl_OCC_LIGHT_SOURCE_7_DIFFUSE */ "occLightSources[7].Diffuse",
108 /* OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR */ "occLightSources[0].Specular",
109 /* OpenGl_OCC_LIGHT_SOURCE_1_SPECULAR */ "occLightSources[1].Specular",
110 /* OpenGl_OCC_LIGHT_SOURCE_2_SPECULAR */ "occLightSources[2].Specular",
111 /* OpenGl_OCC_LIGHT_SOURCE_3_SPECULAR */ "occLightSources[3].Specular",
112 /* OpenGl_OCC_LIGHT_SOURCE_4_SPECULAR */ "occLightSources[4].Specular",
113 /* OpenGl_OCC_LIGHT_SOURCE_5_SPECULAR */ "occLightSources[5].Specular",
114 /* OpenGl_OCC_LIGHT_SOURCE_6_SPECULAR */ "occLightSources[6].Specular",
115 /* OpenGl_OCC_LIGHT_SOURCE_7_SPECULAR */ "occLightSources[7].Specular",
117 /* OpenGl_OCC_LIGHT_SOURCE_0_POSITION */ "occLightSources[0].Position",
118 /* OpenGl_OCC_LIGHT_SOURCE_1_POSITION */ "occLightSources[1].Position",
119 /* OpenGl_OCC_LIGHT_SOURCE_2_POSITION */ "occLightSources[2].Position",
120 /* OpenGl_OCC_LIGHT_SOURCE_3_POSITION */ "occLightSources[3].Position",
121 /* OpenGl_OCC_LIGHT_SOURCE_4_POSITION */ "occLightSources[4].Position",
122 /* OpenGl_OCC_LIGHT_SOURCE_5_POSITION */ "occLightSources[5].Position",
123 /* OpenGl_OCC_LIGHT_SOURCE_6_POSITION */ "occLightSources[6].Position",
124 /* OpenGl_OCC_LIGHT_SOURCE_7_POSITION */ "occLightSources[7].Position",
126 /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF */ "occLightSources[0].SpotCutoff",
127 /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_CUTOFF */ "occLightSources[1].SpotCutoff",
128 /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_CUTOFF */ "occLightSources[2].SpotCutoff",
129 /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_CUTOFF */ "occLightSources[3].SpotCutoff",
130 /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_CUTOFF */ "occLightSources[4].SpotCutoff",
131 /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_CUTOFF */ "occLightSources[5].SpotCutoff",
132 /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_CUTOFF */ "occLightSources[6].SpotCutoff",
133 /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_CUTOFF */ "occLightSources[7].SpotCutoff",
135 /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT */ "occLightSources[0].SpotExponent",
136 /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_EXPONENT */ "occLightSources[1].SpotExponent",
137 /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_EXPONENT */ "occLightSources[2].SpotExponent",
138 /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_EXPONENT */ "occLightSources[3].SpotExponent",
139 /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_EXPONENT */ "occLightSources[4].SpotExponent",
140 /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_EXPONENT */ "occLightSources[5].SpotExponent",
141 /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_EXPONENT */ "occLightSources[6].SpotExponent",
142 /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_EXPONENT */ "occLightSources[7].SpotExponent",
144 /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION */ "occLightSources[0].SpotDirection",
145 /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_DIRECTION */ "occLightSources[1].SpotDirection",
146 /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_DIRECTION */ "occLightSources[2].SpotDirection",
147 /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_DIRECTION */ "occLightSources[3].SpotDirection",
148 /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_DIRECTION */ "occLightSources[4].SpotDirection",
149 /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_DIRECTION */ "occLightSources[5].SpotDirection",
150 /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_DIRECTION */ "occLightSources[6].SpotDirection",
151 /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_DIRECTION */ "occLightSources[7].SpotDirection",
153 /* OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION */ "occLightSources[0].ConstAttenuation",
154 /* OpenGl_OCC_LIGHT_SOURCE_1_CONST_ATTENUATION */ "occLightSources[1].ConstAttenuation",
155 /* OpenGl_OCC_LIGHT_SOURCE_2_CONST_ATTENUATION */ "occLightSources[2].ConstAttenuation",
156 /* OpenGl_OCC_LIGHT_SOURCE_3_CONST_ATTENUATION */ "occLightSources[3].ConstAttenuation",
157 /* OpenGl_OCC_LIGHT_SOURCE_4_CONST_ATTENUATION */ "occLightSources[4].ConstAttenuation",
158 /* OpenGl_OCC_LIGHT_SOURCE_5_CONST_ATTENUATION */ "occLightSources[5].ConstAttenuation",
159 /* OpenGl_OCC_LIGHT_SOURCE_6_CONST_ATTENUATION */ "occLightSources[6].ConstAttenuation",
160 /* OpenGl_OCC_LIGHT_SOURCE_7_CONST_ATTENUATION */ "occLightSources[7].ConstAttenuation",
162 /* OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION */ "occLightSources[0].LinearAttenuation",
163 /* OpenGl_OCC_LIGHT_SOURCE_1_LINEAR_ATTENUATION */ "occLightSources[1].LinearAttenuation",
164 /* OpenGl_OCC_LIGHT_SOURCE_2_LINEAR_ATTENUATION */ "occLightSources[2].LinearAttenuation",
165 /* OpenGl_OCC_LIGHT_SOURCE_3_LINEAR_ATTENUATION */ "occLightSources[3].LinearAttenuation",
166 /* OpenGl_OCC_LIGHT_SOURCE_4_LINEAR_ATTENUATION */ "occLightSources[4].LinearAttenuation",
167 /* OpenGl_OCC_LIGHT_SOURCE_5_LINEAR_ATTENUATION */ "occLightSources[5].LinearAttenuation",
168 /* OpenGl_OCC_LIGHT_SOURCE_6_LINEAR_ATTENUATION */ "occLightSources[6].LinearAttenuation",
169 /* OpenGl_OCC_LIGHT_SOURCE_7_LINEAR_ATTENUATION */ "occLightSources[7].LinearAttenuation",
171 /* OpenGl_OCCT_ACTIVE_SAMPLER */ "occActiveSampler",
172 /* OpenGl_OCCT_TEXTURE_ENABLE */ "occTextureEnable",
173 /* OpenGl_OCCT_DISTINGUISH_MODE */ "occDistinguishingMode",
174 /* OpenGl_OCCT_FRONT_MATERIAL_AMBIENT */ "occFrontMaterial.Ambient",
175 /* OpenGl_OCCT_BACK_MATERIAL_AMBIENT */ "occBackMaterial.Ambient",
176 /* OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE */ "occFrontMaterial.Diffuse",
177 /* OpenGl_OCCT_BACK_MATERIAL_DIFFUSE */ "occBackMaterial.Diffuse",
178 /* OpenGl_OCCT_FRONT_MATERIAL_SPECULAR */ "occFrontMaterial.Specular",
179 /* OpenGl_OCCT_BACK_MATERIAL_SPECULAR */ "occBackMaterial.Specular",
180 /* OpenGl_OCCT_FRONT_MATERIAL_EMISSION */ "occFrontMaterial.Emission",
181 /* OpenGl_OCCT_BACK_MATERIAL_EMISSION */ "occBackMaterial.Emission",
182 /* OpenGl_OCCT_FRONT_MATERIAL_SHININESS */ "occFrontMaterial.Shininess",
183 /* OpenGl_OCCT_BACK_MATERIAL_SHININESS */ "occBackMaterial.Shininess",
184 /* OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY */ "occFrontMaterial.Transparency",
185 /* OpenGl_OCCT_BACK_MATERIAL_TRANSPARENCY */ "occBackMaterial.Transparency"
189 // =======================================================================
190 // function : OpenGl_VariableSetterSelector
191 // purpose : Creates new variable setter selector
192 // =======================================================================
193 OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
195 // Note: Add new variable setters here
196 mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
197 (Graphic3d_UniformValueTypeID<int>::ID, new OpenGl_VariableSetter<int>())
198 (Graphic3d_UniformValueTypeID<float>::ID, new OpenGl_VariableSetter<float>())
199 (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID, new OpenGl_VariableSetter<OpenGl_Vec2>())
200 (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID, new OpenGl_VariableSetter<OpenGl_Vec3>())
201 (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID, new OpenGl_VariableSetter<OpenGl_Vec4>())
202 (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
203 (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
204 (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
207 // =======================================================================
208 // function : ~OpenGl_VariableSetterSelector
209 // purpose : Releases memory resources of variable setter selector
210 // =======================================================================
211 OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
213 for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
218 mySetterList.Clear();
221 // =======================================================================
223 // purpose : Sets generic variable to specified shader program
224 // =======================================================================
225 void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)& theCtx,
226 const Handle(Graphic3d_ShaderVariable)& theVariable,
227 OpenGl_ShaderProgram* theProgram) const
229 Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
230 "The type of user-defined uniform variable is not supported...", );
232 mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
235 // =======================================================================
236 // function : OpenGl_ShaderProgram
237 // purpose : Creates uninitialized shader program
238 // =======================================================================
239 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
240 : myProgramID (NO_PROGRAM),
243 memset (myCurrentState, 0, sizeof (myCurrentState));
244 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
246 myStateLocations[aVar] = INVALID_LOCATION;
250 // =======================================================================
251 // function : Initialize
252 // purpose : Initializes program object with the list of shader objects
253 // =======================================================================
254 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& theCtx,
255 const Graphic3d_ShaderObjectList& theShaders)
257 if (theCtx.IsNull() || !Create (theCtx))
259 return Standard_False;
262 GLchar *aShaderDir = getenv ("CSF_ShadersDirectory");
263 if (aShaderDir == NULL)
265 TCollection_ExtendedString aMsg = "Error! Failed to get OCCT shaders directory";
267 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
268 GL_DEBUG_TYPE_ERROR_ARB,
270 GL_DEBUG_SEVERITY_HIGH_ARB,
273 return Standard_False;
276 OSD_File aDeclFile (TCollection_AsciiString (aShaderDir) + "/Declarations.glsl");
277 if (!aDeclFile.Exists())
279 TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
281 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
282 GL_DEBUG_TYPE_ERROR_ARB,
284 GL_DEBUG_SEVERITY_HIGH_ARB,
287 return Standard_False;
290 TCollection_AsciiString aDeclarations;
292 aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
293 aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
296 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
297 anIter.More(); anIter.Next())
299 if (!anIter.Value()->IsDone())
301 TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
303 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
304 GL_DEBUG_TYPE_ERROR_ARB,
306 GL_DEBUG_SEVERITY_HIGH_ARB,
309 return Standard_False;
312 Handle(OpenGl_ShaderObject) aShader;
314 // Note: Add support of other shader types here
315 switch (anIter.Value()->Type())
317 case Graphic3d_TOS_VERTEX:
318 aShader = new OpenGl_ShaderObject (GL_VERTEX_SHADER);
320 case Graphic3d_TOS_FRAGMENT:
321 aShader = new OpenGl_ShaderObject (GL_FRAGMENT_SHADER);
325 // Is unsupported shader type?
326 if (aShader.IsNull())
328 TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
330 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
331 GL_DEBUG_TYPE_ERROR_ARB,
333 GL_DEBUG_SEVERITY_HIGH_ARB,
336 return Standard_False;
339 if (!aShader->Create (theCtx))
341 return Standard_False;
344 TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
346 if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
348 aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
351 if (!aShader->LoadSource (theCtx, aSource))
353 TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
355 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
356 GL_DEBUG_TYPE_ERROR_ARB,
358 GL_DEBUG_SEVERITY_HIGH_ARB,
361 return Standard_False;
364 if (!aShader->Compile (theCtx))
366 TCollection_ExtendedString aMsg = "Error! Failed to compile shader object";
368 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
369 GL_DEBUG_TYPE_ERROR_ARB,
371 GL_DEBUG_SEVERITY_HIGH_ARB,
374 if (theCtx->caps->contextDebug)
376 TCollection_AsciiString aLog;
377 aShader->FetchInfoLog (theCtx, aLog);
380 std::cout << aLog.ToCString() << std::endl << std::flush;
384 std::cout << "Information log is empty" << std::endl;
388 return Standard_False;
391 if (!AttachShader (theCtx, aShader))
393 return Standard_False;
399 TCollection_ExtendedString aMsg = "Error! Failed to link program object";
401 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
402 GL_DEBUG_TYPE_ERROR_ARB,
404 GL_DEBUG_SEVERITY_HIGH_ARB,
407 if (theCtx->caps->contextDebug)
409 TCollection_AsciiString aLog;
410 FetchInfoLog (theCtx, aLog);
413 std::cout << aLog.ToCString() << std::endl;
417 std::cout << "Information log is empty" << std::endl;
421 return Standard_False;
424 return Standard_True;
427 // =======================================================================
428 // function : ~OpenGl_ShaderProgram
429 // purpose : Releases resources of shader program
430 // =======================================================================
431 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
436 // =======================================================================
437 // function : AttachShader
438 // purpose : Attaches shader object to the program object
439 // =======================================================================
440 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)& theCtx,
441 const Handle(OpenGl_ShaderObject)& theShader)
443 if (myProgramID == NO_PROGRAM || theShader.IsNull())
445 return Standard_False;
448 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
450 if (theShader == anIter.Value())
452 return Standard_False;
456 myShaderObjects.Append (theShader);
457 theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID);
458 return Standard_True;
461 // =======================================================================
462 // function : DetachShader
463 // purpose : Detaches shader object to the program object
464 // =======================================================================
465 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)& theCtx,
466 const Handle(OpenGl_ShaderObject)& theShader)
468 if (myProgramID == NO_PROGRAM
469 || theShader.IsNull())
471 return Standard_False;
474 OpenGl_ShaderList::Iterator anIter (myShaderObjects);
475 while (anIter.More())
477 if (theShader == anIter.Value())
479 myShaderObjects.Remove (anIter);
488 return Standard_False;
491 theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID);
492 return Standard_True;
495 // =======================================================================
497 // purpose : Links the program object
498 // =======================================================================
499 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx)
501 if (myProgramID == NO_PROGRAM)
503 return Standard_False;
506 theCtx->core20->glLinkProgram (myProgramID);
508 GLint aStatus = GL_FALSE;
509 theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
511 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
513 myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
516 return aStatus != GL_FALSE;
519 // =======================================================================
520 // function : FetchInfoLog
521 // purpose : Fetches information log of the last link operation
522 // =======================================================================
523 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
524 TCollection_AsciiString& theOutput)
526 if (myProgramID == NO_PROGRAM)
528 return Standard_False;
532 theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
535 GLchar* aLog = (GLchar*) alloca (aLength);
536 memset (aLog, 0, aLength);
537 theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
540 return Standard_True;
543 // =======================================================================
545 // purpose : Sets the program object as part of current rendering state
546 // =======================================================================
547 void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const
549 if (myProgramID == NO_PROGRAM)
554 theCtx->core20->glUseProgram (myProgramID);
555 theCtx->ShaderManager()->myIsPP = Standard_True;
558 // =======================================================================
559 // function : ApplyVariables
560 // purpose : Fetches uniform variables from proxy shader program
561 // =======================================================================
562 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
564 if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
566 return Standard_False;
569 for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
571 mySetterSelector.Set (theCtx, anIter.Value(), this);
574 myProxy->ClearVariables();
575 return Standard_True;
578 // =======================================================================
579 // function : BindWithVariables
580 // purpose : Binds the program object and applies variables
581 // =======================================================================
582 Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx)
585 return ApplyVariables (theCtx);
588 // =======================================================================
590 // purpose : Reverts to fixed-function graphics pipeline (FFP)
591 // =======================================================================
592 void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx)
594 if (theCtx->ShaderManager()->myIsPP)
596 theCtx->core20->glUseProgram (NO_PROGRAM);
597 theCtx->ShaderManager()->myIsPP = Standard_False;
601 // =======================================================================
602 // function : ActiveState
603 // purpose : Returns index of last modification for specified state type
604 // =======================================================================
605 Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
607 if (theType < MaxStateTypes)
609 return myCurrentState[theType];
614 // =======================================================================
615 // function : UpdateState
616 // purpose : Updates index of last modification for specified state type
617 // =======================================================================
618 void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
619 const Standard_Size theIndex)
621 if (theType < MaxStateTypes)
623 myCurrentState[theType] = theIndex;
627 // =======================================================================
628 // function : GetUniformLocation
629 // purpose : Returns location (index) of the specific uniform variable
630 // =======================================================================
631 GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
632 const GLchar* theName) const
634 return myProgramID != NO_PROGRAM
635 ? theCtx->core20->glGetUniformLocation (myProgramID, theName)
639 // =======================================================================
640 // function : GetAttributeLocation
641 // purpose : Returns location (index) of the generic vertex attribute
642 // =======================================================================
643 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
644 const GLchar* theName) const
646 return myProgramID != NO_PROGRAM
647 ? theCtx->core20->glGetAttribLocation (myProgramID, theName)
651 // =======================================================================
652 // function : GetStateLocation
653 // purpose : Returns location of the OCCT state uniform variable
654 // =======================================================================
655 GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
657 if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
659 return myStateLocations[theVariable];
661 return INVALID_LOCATION;
664 // =======================================================================
665 // function : GetUniform
666 // purpose : Returns the value of the integer uniform variable
667 // =======================================================================
668 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
669 const GLchar* theName,
670 OpenGl_Vec4i& theValue) const
672 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
675 // =======================================================================
676 // function : GetUniform
677 // purpose : Returns the value of the integer uniform variable
678 // =======================================================================
679 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
681 OpenGl_Vec4i& theValue) const
683 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
685 return Standard_False;
688 theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue);
689 return Standard_True;
692 // =======================================================================
693 // function : GetUniform
694 // purpose : Returns the value of the floating-point uniform variable
695 // =======================================================================
696 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
697 const GLchar* theName,
698 OpenGl_Vec4& theValue) const
700 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
703 // =======================================================================
704 // function : GetUniform
705 // purpose : Returns the value of the floating-point uniform variable
706 // =======================================================================
707 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
709 OpenGl_Vec4& theValue) const
711 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
713 return Standard_False;
716 theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue);
717 return Standard_True;
720 // =======================================================================
721 // function : GetAttribute
722 // purpose : Returns the integer vertex attribute
723 // =======================================================================
724 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
725 const GLchar* theName,
726 OpenGl_Vec4i& theValue) const
728 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
731 // =======================================================================
732 // function : GetAttribute
733 // purpose : Returns the integer vertex attribute
734 // =======================================================================
735 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
737 OpenGl_Vec4i& theValue) const
739 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
741 return Standard_False;
744 theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
745 return Standard_True;
748 // =======================================================================
749 // function : GetAttribute
750 // purpose : Returns the floating-point vertex attribute
751 // =======================================================================
752 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
753 const GLchar* theName,
754 OpenGl_Vec4& theValue) const
756 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
759 // =======================================================================
760 // function : GetAttribute
761 // purpose : Returns the floating-point vertex attribute
762 // =======================================================================
763 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
765 OpenGl_Vec4& theValue) const
767 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
769 return Standard_False;
772 theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
773 return Standard_True;
776 // =======================================================================
777 // function : SetUniform
778 // purpose : Specifies the value of the integer uniform variable
779 // =======================================================================
780 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
781 const GLchar* theName,
784 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
787 // =======================================================================
788 // function : SetUniform
789 // purpose : Specifies the value of the integer uniform variable
790 // =======================================================================
791 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
795 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
797 return Standard_False;
800 theCtx->core20->glUniform1i (theLocation, theValue);
801 return Standard_True;
804 // =======================================================================
805 // function : SetUniform
806 // purpose : Specifies the value of the floating-point uniform variable
807 // =======================================================================
808 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
809 const GLchar* theName,
812 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
815 // =======================================================================
816 // function : SetUniform
817 // purpose : Specifies the value of the floating-point uniform variable
818 // =======================================================================
819 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
823 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
825 return Standard_False;
828 theCtx->core20->glUniform1f (theLocation, theValue);
829 return Standard_True;
832 // =======================================================================
833 // function : SetUniform
834 // purpose : Specifies the value of the integer uniform 2D vector
835 // =======================================================================
836 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
837 const GLchar* theName,
838 const OpenGl_Vec2i& theValue)
840 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
843 // =======================================================================
844 // function : SetUniform
845 // purpose : Specifies the value of the integer uniform 2D vector
846 // =======================================================================
847 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
849 const OpenGl_Vec2i& theValue)
851 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
853 return Standard_False;
856 theCtx->core20->glUniform2iv (theLocation, 1, theValue);
857 return Standard_True;
860 // =======================================================================
861 // function : SetUniform
862 // purpose : Specifies the value of the integer uniform 3D vector
863 // =======================================================================
864 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
865 const GLchar* theName,
866 const OpenGl_Vec3i& theValue)
868 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
871 // =======================================================================
872 // function : SetUniform
873 // purpose : Specifies the value of the integer uniform 3D vector
874 // =======================================================================
875 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
877 const OpenGl_Vec3i& theValue)
879 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
881 return Standard_False;
884 theCtx->core20->glUniform3iv (theLocation, 1, theValue);
885 return Standard_True;
888 // =======================================================================
889 // function : SetUniform
890 // purpose : Specifies the value of the integer uniform 4D vector
891 // =======================================================================
892 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
893 const GLchar* theName,
894 const OpenGl_Vec4i& theValue)
896 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
899 // =======================================================================
900 // function : SetUniform
901 // purpose : Specifies the value of the integer uniform 4D vector
902 // =======================================================================
903 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
905 const OpenGl_Vec4i& theValue)
907 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
909 return Standard_False;
912 theCtx->core20->glUniform4iv (theLocation, 1, theValue);
913 return Standard_True;
916 // =======================================================================
917 // function : SetUniform
918 // purpose : Specifies the value of the floating-point uniform 2D vector
919 // =======================================================================
920 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
921 const GLchar* theName,
922 const OpenGl_Vec2& theValue)
924 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
927 // =======================================================================
928 // function : SetUniform
929 // purpose : Specifies the value of the floating-point uniform 2D vector
930 // =======================================================================
931 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
933 const OpenGl_Vec2& theValue)
935 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
937 return Standard_False;
940 theCtx->core20->glUniform2fv (theLocation, 1, theValue);
941 return Standard_True;
944 // =======================================================================
945 // function : SetUniform
946 // purpose : Specifies the value of the floating-point uniform 3D vector
947 // =======================================================================
948 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
949 const GLchar* theName,
950 const OpenGl_Vec3& theValue)
952 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
955 // =======================================================================
956 // function : SetUniform
957 // purpose : Specifies the value of the floating-point uniform 3D vector
958 // =======================================================================
959 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
961 const OpenGl_Vec3& theValue)
963 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
965 return Standard_False;
968 theCtx->core20->glUniform3fv (theLocation, 1, theValue);
969 return Standard_True;
972 // =======================================================================
973 // function : SetUniform
974 // purpose : Specifies the value of the floating-point uniform 4D vector
975 // =======================================================================
976 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
977 const GLchar* theName,
978 const OpenGl_Vec4& theValue)
980 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
983 // =======================================================================
984 // function : SetUniform
985 // purpose : Specifies the value of the floating-point uniform 4D vector
986 // =======================================================================
987 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
989 const OpenGl_Vec4& theValue)
991 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
993 return Standard_False;
996 theCtx->core20->glUniform4fv (theLocation, 1, theValue);
997 return Standard_True;
1000 // =======================================================================
1001 // function : SetUniform
1002 // purpose : Specifies the value of the floating-point uniform 4x4 matrix
1003 // =======================================================================
1004 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1005 const GLchar* theName,
1006 const OpenGl_Matrix& theValue,
1007 GLboolean theTranspose)
1009 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1012 // =======================================================================
1013 // function : SetUniform
1014 // purpose : Specifies the value of the floating-point uniform 4x4 matrix
1015 // =======================================================================
1016 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1018 const OpenGl_Matrix& theValue,
1019 GLboolean theTranspose)
1021 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1023 return Standard_False;
1026 theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat);
1027 return Standard_True;
1030 // =======================================================================
1031 // function : SetUniform
1032 // purpose : Specifies the value of the floating-point uniform 4x4 matrix
1033 // =======================================================================
1034 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1035 const GLchar* theName,
1036 const Tmatrix3& theValue,
1037 GLboolean theTranspose)
1039 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1042 // =======================================================================
1043 // function : SetUniform
1044 // purpose : Specifies the value of the floating-point uniform 4x4 matrix
1045 // =======================================================================
1046 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1048 const Tmatrix3& theValue,
1049 GLboolean theTranspose)
1051 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1053 return Standard_False;
1056 theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue);
1057 return Standard_True;
1060 // =======================================================================
1061 // function : SetSampler
1062 // purpose : Specifies the value of the sampler uniform variable
1063 // =======================================================================
1064 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1065 const GLchar* theName,
1066 const GLenum theTextureUnit)
1068 return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1071 // =======================================================================
1072 // function : SetSampler
1073 // purpose : Specifies the value of the sampler uniform variable
1074 // =======================================================================
1075 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1077 const GLenum theTextureUnit)
1079 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1081 return Standard_False;
1084 theCtx->core20->glUniform1i (theLocation, theTextureUnit);
1085 return Standard_True;
1088 // =======================================================================
1089 // function : Create
1090 // purpose : Creates new empty shader program of specified type
1091 // =======================================================================
1092 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1094 if (myProgramID == NO_PROGRAM
1095 && theCtx->core20 != NULL)
1097 myProgramID = theCtx->core20->glCreateProgram();
1100 return myProgramID != NO_PROGRAM;
1103 // =======================================================================
1104 // function : Release
1105 // purpose : Destroys shader program
1106 // =======================================================================
1107 void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx)
1109 if (myProgramID == NO_PROGRAM)
1114 Standard_ASSERT_RETURN (theCtx != NULL,
1115 "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1117 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1119 anIter.ChangeValue()->Release (theCtx);
1120 anIter.ChangeValue().Nullify();
1123 if (theCtx->core20 != NULL
1124 && theCtx->IsValid())
1126 theCtx->core20->glDeleteProgram (myProgramID);
1129 myProgramID = NO_PROGRAM;