0024437: Visualization - silhouette edges based on OpenGL
[occt.git] / src / OpenGl / OpenGl_ShaderProgram.cxx
... / ...
CommitLineData
1// Created on: 2013-09-19
2// Created by: Denis BOGOLEPOV
3// Copyright (c) 2013-2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <OSD_File.hxx>
17#include <OSD_Environment.hxx>
18#include <OSD_Protection.hxx>
19
20#include <Graphic3d_Buffer.hxx>
21#include <Standard_Assert.hxx>
22#include <Standard_Atomic.hxx>
23#include <TCollection_ExtendedString.hxx>
24
25#include <OpenGl_Context.hxx>
26#include <OpenGl_ShaderProgram.hxx>
27#include <OpenGl_ShaderManager.hxx>
28#include <OpenGl_ArbTexBindless.hxx>
29
30#include <OpenGl_GlCore32.hxx>
31
32#include "../Shaders/Shaders_DeclarationsImpl_glsl.pxx"
33#include "../Shaders/Shaders_Declarations_glsl.pxx"
34
35#ifdef _WIN32
36 #include <malloc.h> // for alloca()
37#endif
38
39IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_NamedResource)
40
41OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
42
43// Declare OCCT-specific OpenGL/GLSL shader variables
44Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
45{
46 "occModelWorldMatrix", // OpenGl_OCC_MODEL_WORLD_MATRIX
47 "occWorldViewMatrix", // OpenGl_OCC_WORLD_VIEW_MATRIX
48 "occProjectionMatrix", // OpenGl_OCC_PROJECTION_MATRIX
49 "occModelWorldMatrixInverse", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
50 "occWorldViewMatrixInverse", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
51 "occProjectionMatrixInverse", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
52 "occModelWorldMatrixTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
53 "occWorldViewMatrixTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
54 "occProjectionMatrixTranspose", // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
55 "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
56 "occWorldViewMatrixInverseTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
57 "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
58
59 "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
60 "occClipPlaneChains", // OpenGl_OCC_CLIP_PLANE_CHAINS
61 "occClipPlaneCount", // OpenGl_OCC_CLIP_PLANE_COUNT
62
63 "occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT
64 "occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES
65 "occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS
66 "occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT
67
68 "occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE
69 "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
70 "occFrontMaterial", // OpenGl_OCCT_FRONT_MATERIAL
71 "occBackMaterial", // OpenGl_OCCT_BACK_MATERIAL
72 "occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF
73 "occColor", // OpenGl_OCCT_COLOR
74
75 "occOitOutput", // OpenGl_OCCT_OIT_OUTPUT
76 "occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR
77
78 "occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D
79 "occPointSize", // OpenGl_OCCT_POINT_SIZE
80
81 "occViewport", // OpenGl_OCCT_VIEWPORT
82 "occLineWidth", // OpenGl_OCCT_LINE_WIDTH
83 "occLineFeather", // OpenGl_OCCT_LINE_FEATHER
84 "occWireframeColor", // OpenGl_OCCT_WIREFRAME_COLOR
85 "occIsQuadMode", // OpenGl_OCCT_QUAD_MODE_STATE
86
87 "occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE
88 "occSilhouetteThickness" // OpenGl_OCCT_SILHOUETTE_THICKNESS
89};
90
91namespace
92{
93 //! Convert Graphic3d_TypeOfShaderObject enumeration into OpenGL enumeration.
94 static GLenum shaderTypeToGl (Graphic3d_TypeOfShaderObject theType)
95 {
96 switch (theType)
97 {
98 case Graphic3d_TOS_VERTEX: return GL_VERTEX_SHADER;
99 case Graphic3d_TOS_FRAGMENT: return GL_FRAGMENT_SHADER;
100 case Graphic3d_TOS_GEOMETRY: return GL_GEOMETRY_SHADER;
101 case Graphic3d_TOS_TESS_CONTROL: return GL_TESS_CONTROL_SHADER;
102 case Graphic3d_TOS_TESS_EVALUATION: return GL_TESS_EVALUATION_SHADER;
103 case Graphic3d_TOS_COMPUTE: return GL_COMPUTE_SHADER;
104 }
105 return 0;
106 }
107}
108
109// =======================================================================
110// function : OpenGl_VariableSetterSelector
111// purpose : Creates new variable setter selector
112// =======================================================================
113OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
114{
115 // Note: Add new variable setters here
116 mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
117 (Graphic3d_UniformValueTypeID<int>::ID, new OpenGl_VariableSetter<int>())
118 (Graphic3d_UniformValueTypeID<float>::ID, new OpenGl_VariableSetter<float>())
119 (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID, new OpenGl_VariableSetter<OpenGl_Vec2>())
120 (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID, new OpenGl_VariableSetter<OpenGl_Vec3>())
121 (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID, new OpenGl_VariableSetter<OpenGl_Vec4>())
122 (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
123 (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
124 (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
125}
126
127// =======================================================================
128// function : ~OpenGl_VariableSetterSelector
129// purpose : Releases memory resources of variable setter selector
130// =======================================================================
131OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
132{
133 for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
134 {
135 delete anIt.Value();
136 }
137
138 mySetterList.Clear();
139}
140
141// =======================================================================
142// function : Set
143// purpose : Sets generic variable to specified shader program
144// =======================================================================
145void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)& theCtx,
146 const Handle(Graphic3d_ShaderVariable)& theVariable,
147 OpenGl_ShaderProgram* theProgram) const
148{
149 Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
150 "The type of user-defined uniform variable is not supported...", );
151
152 mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
153}
154
155// =======================================================================
156// function : OpenGl_ShaderProgram
157// purpose : Creates uninitialized shader program
158// =======================================================================
159OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy,
160 const TCollection_AsciiString& theId)
161: OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : theId),
162 myProgramID (NO_PROGRAM),
163 myProxy (theProxy),
164 myShareCount(1),
165 myNbLightsMax (0),
166 myNbClipPlanesMax (0),
167 myNbFragOutputs (1),
168 myHasAlphaTest (false),
169 myHasWeightOitOutput (false),
170 myHasTessShader (false)
171{
172 memset (myCurrentState, 0, sizeof (myCurrentState));
173}
174
175// =======================================================================
176// function : Initialize
177// purpose : Initializes program object with the list of shader objects
178// =======================================================================
179Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& theCtx,
180 const Graphic3d_ShaderObjectList& theShaders)
181{
182 myHasTessShader = false;
183 if (theCtx.IsNull() || !Create (theCtx))
184 {
185 return Standard_False;
186 }
187
188 TCollection_AsciiString aHeaderVer = !myProxy.IsNull() ? myProxy->Header() : TCollection_AsciiString();
189 int aShaderMask = 0;
190 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
191 {
192 aShaderMask |= anIter.Value()->Type();
193 }
194 myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0;
195 myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1;
196 myHasAlphaTest = !myProxy.IsNull() && myProxy->HasAlphaTest();
197 myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1;
198
199 // detect the minimum GLSL version required for defined Shader Objects
200#if defined(GL_ES_VERSION_2_0)
201 if (myHasTessShader)
202 {
203 if (!theCtx->IsGlGreaterEqual (3, 2))
204 {
205 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
206 "Error! Tessellation shader requires OpenGL ES 3.2+");
207 return false;
208 }
209 else if (aHeaderVer.IsEmpty())
210 {
211 aHeaderVer = "#version 320 es";
212 }
213 }
214 else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
215 {
216 switch (theCtx->hasGeometryStage)
217 {
218 case OpenGl_FeatureNotAvailable:
219 {
220 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
221 "Error! Geometry shader requires OpenGL ES 3.2+ or GL_EXT_geometry_shader");
222 return false;
223 }
224 case OpenGl_FeatureInExtensions:
225 {
226 if (aHeaderVer.IsEmpty())
227 {
228 aHeaderVer = "#version 310 es";
229 }
230 break;
231 }
232 case OpenGl_FeatureInCore:
233 {
234 if (aHeaderVer.IsEmpty())
235 {
236 aHeaderVer = "#version 320 es";
237 }
238 break;
239 }
240 }
241 }
242 else if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
243 {
244 if (!theCtx->IsGlGreaterEqual (3, 1))
245 {
246 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
247 "Error! Compute shaders require OpenGL ES 3.1+");
248 return false;
249 }
250 else if (aHeaderVer.IsEmpty())
251 {
252 aHeaderVer = "#version 310 es";
253 }
254 }
255#else
256 if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
257 {
258 if (!theCtx->IsGlGreaterEqual (4, 3))
259 {
260 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
261 "Error! Compute shaders require OpenGL 4.3+");
262 return 0;
263 }
264 else if (aHeaderVer.IsEmpty())
265 {
266 aHeaderVer = "#version 430";
267 }
268 }
269 else if (myHasTessShader)
270 {
271 if (!theCtx->IsGlGreaterEqual (4, 0))
272 {
273 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
274 "Error! Tessellation shaders require OpenGL 4.0+");
275 return 0;
276 }
277 else if (aHeaderVer.IsEmpty())
278 {
279 aHeaderVer = "#version 400";
280 }
281 }
282 else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
283 {
284 if (!theCtx->IsGlGreaterEqual (3, 2))
285 {
286 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
287 "Error! Geometry shaders require OpenGL 3.2+");
288 return 0;
289 }
290 else if (aHeaderVer.IsEmpty())
291 {
292 aHeaderVer = "#version 150";
293 }
294 }
295#endif
296
297 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
298 {
299 if (!anIter.Value()->IsDone())
300 {
301 const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
302 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
303 return Standard_False;
304 }
305
306 const GLenum aShaderType = shaderTypeToGl (anIter.Value()->Type());
307 if (aShaderType == 0)
308 {
309 return Standard_False;
310 }
311
312 Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (aShaderType);
313 if (!aShader->Create (theCtx))
314 {
315 aShader->Release (theCtx.operator->());
316 return Standard_False;
317 }
318
319 TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n";
320 if (myNbFragOutputs > 1)
321 {
322 if (theCtx->hasDrawBuffers)
323 {
324 anExtensions += "#define OCC_ENABLE_draw_buffers\n";
325 if (myHasWeightOitOutput)
326 {
327 anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
328 }
329 }
330 else
331 {
332 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
333 "Error! Multiple draw buffers required by the program, but aren't supported by OpenGL");
334 return Standard_False;
335 }
336
337 if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
338 {
339 if (theCtx->arbDrawBuffers)
340 {
341 anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
342 }
343 else if (theCtx->extDrawBuffers)
344 {
345 anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
346 }
347 }
348 }
349 if (myHasAlphaTest)
350 {
351 anExtensions += "#define OCC_ALPHA_TEST\n";
352 }
353
354 if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
355 {
356#if defined(GL_ES_VERSION_2_0)
357 if (theCtx->oesSampleVariables)
358 {
359 anExtensions += "#extension GL_OES_sample_variables : enable\n";
360 }
361#else
362 if (theCtx->arbSampleShading)
363 {
364 anExtensions += "#extension GL_ARB_sample_shading : enable\n";
365 }
366#endif
367 }
368#if defined(GL_ES_VERSION_2_0)
369 if (theCtx->hasGeometryStage == OpenGl_FeatureInExtensions)
370 {
371 anExtensions += "#extension GL_EXT_geometry_shader : enable\n"
372 "#extension GL_EXT_shader_io_blocks : enable\n";
373 }
374#endif
375
376 TCollection_AsciiString aPrecisionHeader;
377 if (anIter.Value()->Type() == Graphic3d_TOS_FRAGMENT)
378 {
379 #if defined(GL_ES_VERSION_2_0)
380 aPrecisionHeader = theCtx->hasHighp
381 ? "precision highp float;\n"
382 "precision highp int;\n"
383 : "precision mediump float;\n"
384 "precision mediump int;\n";
385 #endif
386 }
387
388 TCollection_AsciiString aHeaderType;
389 switch (anIter.Value()->Type())
390 {
391 case Graphic3d_TOS_COMPUTE: { aHeaderType = "#define COMPUTE_SHADER\n"; break; }
392 case Graphic3d_TOS_VERTEX: { aHeaderType = "#define VERTEX_SHADER\n"; break; }
393 case Graphic3d_TOS_TESS_CONTROL: { aHeaderType = "#define TESS_CONTROL_SHADER\n"; break; }
394 case Graphic3d_TOS_TESS_EVALUATION: { aHeaderType = "#define TESS_EVALUATION_SHADER\n"; break; }
395 case Graphic3d_TOS_GEOMETRY: { aHeaderType = "#define GEOMETRY_SHADER\n"; break; }
396 case Graphic3d_TOS_FRAGMENT: { aHeaderType = "#define FRAGMENT_SHADER\n"; break; }
397 }
398
399 TCollection_AsciiString aHeaderConstants;
400 myNbLightsMax = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0;
401 myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0;
402 aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n";
403 aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n";
404 aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n";
405
406 const TCollection_AsciiString aSource = aHeaderVer // #version - header defining GLSL version, should be first
407 + (!aHeaderVer.IsEmpty() ? "\n" : "")
408 + anExtensions // #extension - list of enabled extensions, should be second
409 + aPrecisionHeader // precision - default precision qualifiers, should be before any code
410 + aHeaderType // auxiliary macros defining a shader stage (type)
411 + aHeaderConstants
412 + Shaders_Declarations_glsl // common declarations (global constants and Vertex Shader inputs)
413 + Shaders_DeclarationsImpl_glsl
414 + anIter.Value()->Source(); // the source code itself (defining main() function)
415 if (!aShader->LoadAndCompile (theCtx, aSource))
416 {
417 aShader->Release (theCtx.operator->());
418 return Standard_False;
419 }
420
421 if (theCtx->caps->glslDumpLevel)
422 {
423 TCollection_AsciiString aShaderTypeMsg;
424 switch (anIter.Value()->Type())
425 {
426 case Graphic3d_TOS_COMPUTE: { aShaderTypeMsg = "Compute shader source code:\n"; break; }
427 case Graphic3d_TOS_VERTEX: { aShaderTypeMsg = "Vertex shader source code:\n"; break; }
428 case Graphic3d_TOS_TESS_CONTROL: { aShaderTypeMsg = "Tesselation control shader source code:\n"; break; }
429 case Graphic3d_TOS_TESS_EVALUATION: { aShaderTypeMsg = "Tesselation evaluation shader source code:\n"; break; }
430 case Graphic3d_TOS_GEOMETRY: { aShaderTypeMsg = "Geometry shader source code:\n"; break; }
431 case Graphic3d_TOS_FRAGMENT: { aShaderTypeMsg = "Fragment shader source code:\n"; break; }
432 }
433 TCollection_AsciiString anOutputSource = aSource;
434 if (theCtx->caps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short)
435 {
436 anOutputSource = aHeaderVer
437 + (!aHeaderVer.IsEmpty() ? "\n" : "")
438 + anExtensions
439 + aPrecisionHeader
440 + aHeaderType
441 + aHeaderConstants
442 + anIter.Value()->Source();
443 }
444 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_MEDIUM,
445 TCollection_ExtendedString (aShaderTypeMsg + anOutputSource));
446 }
447
448 if (!AttachShader (theCtx, aShader))
449 {
450 aShader->Release (theCtx.operator->());
451 return Standard_False;
452 }
453 }
454
455 // bind locations for pre-defined Vertex Attributes
456 SetAttributeName (theCtx, Graphic3d_TOA_POS, "occVertex");
457 SetAttributeName (theCtx, Graphic3d_TOA_NORM, "occNormal");
458 SetAttributeName (theCtx, Graphic3d_TOA_UV, "occTexCoord");
459 SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
460
461 // bind custom Vertex Attributes
462 if (!myProxy.IsNull())
463 {
464 for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
465 anAttribIter.More(); anAttribIter.Next())
466 {
467 SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
468 }
469 }
470
471 if (!Link (theCtx))
472 {
473 return Standard_False;
474 }
475
476 // set uniform defaults
477 const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
478 theCtx->core20fwd->glUseProgram (myProgramID);
479 if (const OpenGl_ShaderUniformLocation aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE))
480 {
481 SetUniform (theCtx, aLocTexEnable, 0); // Off
482 }
483 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occActiveSampler"))
484 {
485 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0));
486 }
487
488 const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
489 const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
490 for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
491 {
492 const TCollection_AsciiString aName = aSamplerNamePrefix + aUnitIter;
493 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, aName.ToCString()))
494 {
495 SetUniform (theCtx, aLocSampler, aUnitIter);
496 }
497 }
498
499 theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
500 return Standard_True;
501}
502
503// =======================================================================
504// function : ~OpenGl_ShaderProgram
505// purpose : Releases resources of shader program
506// =======================================================================
507OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
508{
509 Release (NULL);
510}
511
512// =======================================================================
513// function : AttachShader
514// purpose : Attaches shader object to the program object
515// =======================================================================
516Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)& theCtx,
517 const Handle(OpenGl_ShaderObject)& theShader)
518{
519 if (myProgramID == NO_PROGRAM || theShader.IsNull())
520 {
521 return Standard_False;
522 }
523
524 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
525 {
526 if (theShader == anIter.Value())
527 {
528 return Standard_False;
529 }
530 }
531
532 myShaderObjects.Append (theShader);
533 theCtx->core20fwd->glAttachShader (myProgramID, theShader->myShaderID);
534 return Standard_True;
535}
536
537// =======================================================================
538// function : DetachShader
539// purpose : Detaches shader object to the program object
540// =======================================================================
541Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)& theCtx,
542 const Handle(OpenGl_ShaderObject)& theShader)
543{
544 if (myProgramID == NO_PROGRAM
545 || theShader.IsNull())
546 {
547 return Standard_False;
548 }
549
550 OpenGl_ShaderList::Iterator anIter (myShaderObjects);
551 while (anIter.More())
552 {
553 if (theShader == anIter.Value())
554 {
555 myShaderObjects.Remove (anIter);
556 break;
557 }
558
559 anIter.Next();
560 }
561
562 if (!anIter.More())
563 {
564 return Standard_False;
565 }
566
567 theCtx->core20fwd->glDetachShader (myProgramID, theShader->myShaderID);
568 return Standard_True;
569}
570
571// =======================================================================
572// function : Link
573// purpose : Links the program object
574// =======================================================================
575Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCtx)
576{
577 if (myProgramID == NO_PROGRAM)
578 {
579 return Standard_False;
580 }
581
582 GLint aStatus = GL_FALSE;
583 theCtx->core20fwd->glLinkProgram (myProgramID);
584 theCtx->core20fwd->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
585 if (aStatus == GL_FALSE)
586 {
587 return Standard_False;
588 }
589
590 memset (myCurrentState, 0, sizeof (myCurrentState));
591 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
592 {
593 myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
594 }
595 return Standard_True;
596}
597
598// =======================================================================
599// function : Link
600// purpose :
601// =======================================================================
602Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx,
603 bool theIsVerbose)
604{
605 if (!theIsVerbose)
606 {
607 return link (theCtx);
608 }
609
610 if (!link (theCtx))
611 {
612 TCollection_AsciiString aLog;
613 FetchInfoLog (theCtx, aLog);
614 if (aLog.IsEmpty())
615 {
616 aLog = "Linker log is empty.";
617 }
618 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
619 TCollection_AsciiString ("Failed to link program object! Linker log:\n") + aLog);
620 return false;
621 }
622 else if (theCtx->caps->glslWarnings)
623 {
624 TCollection_AsciiString aLog;
625 FetchInfoLog (theCtx, aLog);
626 if (!aLog.IsEmpty()
627 && !aLog.IsEqual ("No errors.\n"))
628 {
629 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
630 TCollection_AsciiString ("GLSL linker log:\n") + aLog);
631 }
632 }
633 return true;
634}
635
636// =======================================================================
637// function : FetchInfoLog
638// purpose : Fetches information log of the last link operation
639// =======================================================================
640Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
641 TCollection_AsciiString& theOutput)
642{
643 if (myProgramID == NO_PROGRAM)
644 {
645 return Standard_False;
646 }
647
648 GLint aLength = 0;
649 theCtx->core20fwd->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
650 if (aLength > 0)
651 {
652 GLchar* aLog = (GLchar*) alloca (aLength);
653 memset (aLog, 0, aLength);
654 theCtx->core20fwd->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
655 theOutput = aLog;
656 }
657 return Standard_True;
658}
659
660// =======================================================================
661// function : ApplyVariables
662// purpose : Fetches uniform variables from proxy shader program
663// =======================================================================
664Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
665{
666 if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
667 {
668 return Standard_False;
669 }
670
671 for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
672 {
673 mySetterSelector.Set (theCtx, anIter.Value(), this);
674 }
675
676 myProxy->ClearVariables();
677 return Standard_True;
678}
679
680// =======================================================================
681// function : GetUniformLocation
682// purpose : Returns location (index) of the specific uniform variable
683// =======================================================================
684OpenGl_ShaderUniformLocation OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
685 const GLchar* theName) const
686{
687 return OpenGl_ShaderUniformLocation (myProgramID != NO_PROGRAM
688 ? theCtx->core20fwd->glGetUniformLocation (myProgramID, theName)
689 : INVALID_LOCATION);
690}
691
692// =======================================================================
693// function : GetAttributeLocation
694// purpose : Returns location (index) of the generic vertex attribute
695// =======================================================================
696GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
697 const GLchar* theName) const
698{
699 return myProgramID != NO_PROGRAM
700 ? theCtx->core20fwd->glGetAttribLocation (myProgramID, theName)
701 : INVALID_LOCATION;
702}
703
704// =======================================================================
705// function : GetUniform
706// purpose : Returns the value of the integer uniform variable
707// =======================================================================
708Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
709 const GLchar* theName,
710 OpenGl_Vec4i& theValue) const
711{
712 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
713}
714
715// =======================================================================
716// function : GetUniform
717// purpose : Returns the value of the integer uniform variable
718// =======================================================================
719Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
720 GLint theLocation,
721 OpenGl_Vec4i& theValue) const
722{
723 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
724 {
725 return Standard_False;
726 }
727
728 theCtx->core20fwd->glGetUniformiv (myProgramID, theLocation, theValue);
729 return Standard_True;
730}
731
732// =======================================================================
733// function : GetUniform
734// purpose : Returns the value of the floating-point uniform variable
735// =======================================================================
736Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
737 const GLchar* theName,
738 OpenGl_Vec4& theValue) const
739{
740 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
741}
742
743// =======================================================================
744// function : GetUniform
745// purpose : Returns the value of the floating-point uniform variable
746// =======================================================================
747Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
748 GLint theLocation,
749 OpenGl_Vec4& theValue) const
750{
751 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
752 {
753 return Standard_False;
754 }
755
756 theCtx->core20fwd->glGetUniformfv (myProgramID, theLocation, theValue);
757 return Standard_True;
758}
759
760// =======================================================================
761// function : GetAttribute
762// purpose : Returns the integer vertex attribute
763// =======================================================================
764Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
765 const GLchar* theName,
766 OpenGl_Vec4i& theValue) const
767{
768 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
769}
770
771// =======================================================================
772// function : GetAttribute
773// purpose : Returns the integer vertex attribute
774// =======================================================================
775Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
776 GLint theIndex,
777 OpenGl_Vec4i& theValue) const
778{
779 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
780 {
781 return Standard_False;
782 }
783
784 theCtx->core20fwd->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
785 return Standard_True;
786}
787
788// =======================================================================
789// function : GetAttribute
790// purpose : Returns the floating-point vertex attribute
791// =======================================================================
792Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
793 const GLchar* theName,
794 OpenGl_Vec4& theValue) const
795{
796 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
797}
798
799// =======================================================================
800// function : GetAttribute
801// purpose : Returns the floating-point vertex attribute
802// =======================================================================
803Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
804 GLint theIndex,
805 OpenGl_Vec4& theValue) const
806{
807 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
808 {
809 return Standard_False;
810 }
811
812 theCtx->core20fwd->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
813 return Standard_True;
814}
815
816// =======================================================================
817// function : SetAttributeName
818// purpose :
819// =======================================================================
820Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
821 GLint theIndex,
822 const GLchar* theName)
823{
824 theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
825 return Standard_True;
826}
827
828// =======================================================================
829// function : SetAttribute
830// purpose :
831// =======================================================================
832Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
833 const GLchar* theName,
834 GLfloat theValue)
835{
836 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
837}
838
839// =======================================================================
840// function : SetAttribute
841// purpose :
842// =======================================================================
843Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
844 GLint theIndex,
845 GLfloat theValue)
846{
847 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
848 {
849 return Standard_False;
850 }
851
852 theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
853 return Standard_True;
854}
855
856// =======================================================================
857// function : SetAttribute
858// purpose :
859// =======================================================================
860Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
861 const GLchar* theName,
862 const OpenGl_Vec2& theValue)
863{
864 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
865}
866
867// =======================================================================
868// function : SetAttribute
869// purpose :
870// =======================================================================
871Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
872 GLint theIndex,
873 const OpenGl_Vec2& theValue)
874{
875 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
876 {
877 return Standard_False;
878 }
879
880 theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
881 return Standard_True;
882}
883
884// =======================================================================
885// function : SetAttribute
886// purpose :
887// =======================================================================
888Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
889 const GLchar* theName,
890 const OpenGl_Vec3& theValue)
891{
892 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
893}
894
895// =======================================================================
896// function : SetAttribute
897// purpose :
898// =======================================================================
899Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
900 GLint theIndex,
901 const OpenGl_Vec3& theValue)
902{
903 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
904 {
905 return Standard_False;
906 }
907
908 theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
909 return Standard_True;
910}
911
912// =======================================================================
913// function : SetAttribute
914// purpose :
915// =======================================================================
916Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
917 const GLchar* theName,
918 const OpenGl_Vec4& theValue)
919{
920 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
921}
922
923// =======================================================================
924// function : SetAttribute
925// purpose :
926// =======================================================================
927Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
928 GLint theIndex,
929 const OpenGl_Vec4& theValue)
930{
931 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
932 {
933 return Standard_False;
934 }
935
936 theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
937 return Standard_True;
938}
939
940// =======================================================================
941// function : SetUniform
942// purpose : Specifies the value of the integer uniform variable
943// =======================================================================
944Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
945 const GLchar* theName,
946 GLint theValue)
947{
948 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
949}
950
951// =======================================================================
952// function : SetUniform
953// purpose : Specifies the value of the integer uniform variable
954// =======================================================================
955Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
956 GLint theLocation,
957 GLint theValue)
958{
959 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
960 {
961 return Standard_False;
962 }
963
964 theCtx->core20fwd->glUniform1i (theLocation, theValue);
965 return Standard_True;
966}
967
968// =======================================================================
969// function : SetUniform
970// purpose :
971// =======================================================================
972Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
973 const GLchar* theName,
974 const OpenGl_Vec2u& theValue)
975{
976 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
977}
978
979// =======================================================================
980// function : SetUniform
981// purpose :
982// =======================================================================
983Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
984 GLint theLocation,
985 const OpenGl_Vec2u& theValue)
986{
987 if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
988 {
989 return Standard_False;
990 }
991
992#if !defined(GL_ES_VERSION_2_0)
993 theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
994 return Standard_True;
995#else
996 (void )theValue;
997 return Standard_False;
998#endif
999}
1000
1001// =======================================================================
1002// function : SetUniform
1003// purpose :
1004// =======================================================================
1005Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1006 const GLchar* theName,
1007 const GLsizei theCount,
1008 const OpenGl_Vec2u* theValue)
1009{
1010 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
1011}
1012
1013// =======================================================================
1014// function : SetUniform
1015// purpose :
1016// =======================================================================
1017Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1018 GLint theLocation,
1019 const GLsizei theCount,
1020 const OpenGl_Vec2u* theValue)
1021{
1022 if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1023 {
1024 return Standard_False;
1025 }
1026
1027#if !defined(GL_ES_VERSION_2_0)
1028 theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
1029 return Standard_True;
1030#else
1031 (void )theCount;
1032 (void )theValue;
1033 return Standard_False;
1034#endif
1035}
1036
1037// =======================================================================
1038// function : SetUniform
1039// purpose : Specifies the value of the floating-point uniform variable
1040// =======================================================================
1041Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1042 const GLchar* theName,
1043 GLfloat theValue)
1044{
1045 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1046}
1047
1048// =======================================================================
1049// function : SetUniform
1050// purpose : Specifies the value of the floating-point uniform variable
1051// =======================================================================
1052Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1053 GLint theLocation,
1054 GLfloat theValue)
1055{
1056 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1057 {
1058 return Standard_False;
1059 }
1060
1061 theCtx->core20fwd->glUniform1f (theLocation, theValue);
1062 return Standard_True;
1063}
1064
1065// =======================================================================
1066// function : SetUniform
1067// purpose : Specifies the value of the integer uniform 2D vector
1068// =======================================================================
1069Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1070 const GLchar* theName,
1071 const OpenGl_Vec2i& theValue)
1072{
1073 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1074}
1075
1076// =======================================================================
1077// function : SetUniform
1078// purpose : Specifies the value of the integer uniform 2D vector
1079// =======================================================================
1080Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1081 GLint theLocation,
1082 const OpenGl_Vec2i& theValue)
1083{
1084 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1085 {
1086 return Standard_False;
1087 }
1088
1089 theCtx->core20fwd->glUniform2iv (theLocation, 1, theValue);
1090 return Standard_True;
1091}
1092
1093// =======================================================================
1094// function : SetUniform
1095// purpose : Specifies the value of the integer uniform 3D vector
1096// =======================================================================
1097Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1098 const GLchar* theName,
1099 const OpenGl_Vec3i& theValue)
1100{
1101 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1102}
1103
1104// =======================================================================
1105// function : SetUniform
1106// purpose : Specifies the value of the integer uniform 3D vector
1107// =======================================================================
1108Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1109 GLint theLocation,
1110 const OpenGl_Vec3i& theValue)
1111{
1112 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1113 {
1114 return Standard_False;
1115 }
1116
1117 theCtx->core20fwd->glUniform3iv (theLocation, 1, theValue);
1118 return Standard_True;
1119}
1120
1121// =======================================================================
1122// function : SetUniform
1123// purpose : Specifies the value of the integer uniform 4D vector
1124// =======================================================================
1125Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1126 const GLchar* theName,
1127 const OpenGl_Vec4i& theValue)
1128{
1129 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1130}
1131
1132// =======================================================================
1133// function : SetUniform
1134// purpose : Specifies the value of the integer uniform 4D vector
1135// =======================================================================
1136Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1137 GLint theLocation,
1138 const OpenGl_Vec4i& theValue)
1139{
1140 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1141 {
1142 return Standard_False;
1143 }
1144
1145 theCtx->core20fwd->glUniform4iv (theLocation, 1, theValue);
1146 return Standard_True;
1147}
1148
1149// =======================================================================
1150// function : SetUniform
1151// purpose : Specifies the value of the floating-point uniform 2D vector
1152// =======================================================================
1153Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1154 const GLchar* theName,
1155 const OpenGl_Vec2& theValue)
1156{
1157 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1158}
1159
1160// =======================================================================
1161// function : SetUniform
1162// purpose : Specifies the value of the floating-point uniform 2D vector
1163// =======================================================================
1164Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1165 GLint theLocation,
1166 const OpenGl_Vec2& theValue)
1167{
1168 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1169 {
1170 return Standard_False;
1171 }
1172
1173 theCtx->core20fwd->glUniform2fv (theLocation, 1, theValue);
1174 return Standard_True;
1175}
1176
1177// =======================================================================
1178// function : SetUniform
1179// purpose : Specifies the value of the floating-point uniform 3D vector
1180// =======================================================================
1181Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1182 const GLchar* theName,
1183 const OpenGl_Vec3& theValue)
1184{
1185 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1186}
1187
1188// =======================================================================
1189// function : SetUniform
1190// purpose : Specifies the value of the floating-point uniform 3D vector
1191// =======================================================================
1192Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1193 GLint theLocation,
1194 const OpenGl_Vec3& theValue)
1195{
1196 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1197 {
1198 return Standard_False;
1199 }
1200
1201 theCtx->core20fwd->glUniform3fv (theLocation, 1, theValue);
1202 return Standard_True;
1203}
1204
1205// =======================================================================
1206// function : SetUniform
1207// purpose : Specifies the value of the floating-point uniform 4D vector
1208// =======================================================================
1209Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1210 const GLchar* theName,
1211 const OpenGl_Vec4& theValue)
1212{
1213 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1214}
1215
1216// =======================================================================
1217// function : SetUniform
1218// purpose : Specifies the value of the floating-point uniform 4D vector
1219// =======================================================================
1220Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1221 GLint theLocation,
1222 const OpenGl_Vec4& theValue)
1223{
1224 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1225 {
1226 return Standard_False;
1227 }
1228
1229 theCtx->core20fwd->glUniform4fv (theLocation, 1, theValue);
1230 return Standard_True;
1231}
1232
1233// =======================================================================
1234// function : SetUniform
1235// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1236// =======================================================================
1237Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1238 const GLchar* theName,
1239 const OpenGl_Mat4& theValue,
1240 GLboolean theTranspose)
1241{
1242 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1243}
1244
1245// =======================================================================
1246// function : SetUniform
1247// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1248// =======================================================================
1249Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1250 GLint theLocation,
1251 const OpenGl_Mat4& theValue,
1252 GLboolean theTranspose)
1253{
1254 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1255 {
1256 return Standard_False;
1257 }
1258
1259 theCtx->core20fwd->glUniformMatrix4fv (theLocation, 1, GL_FALSE, theTranspose ? theValue.Transposed() : theValue);
1260 return Standard_True;
1261}
1262
1263// =======================================================================
1264// function : SetUniform
1265// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1266// =======================================================================
1267Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1268 const GLchar* theName,
1269 const OpenGl_Matrix& theValue,
1270 GLboolean theTranspose)
1271{
1272 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1273}
1274
1275// =======================================================================
1276// function : SetUniform
1277// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1278// =======================================================================
1279Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1280 GLint theLocation,
1281 const OpenGl_Matrix& theValue,
1282 GLboolean theTranspose)
1283{
1284 return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose);
1285}
1286
1287// =======================================================================
1288// function : SetUniform
1289// purpose : Specifies the value of the float uniform array
1290// =======================================================================
1291Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1292 GLint theLocation,
1293 GLuint theCount,
1294 const Standard_ShortReal* theData)
1295{
1296 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1297 {
1298 return Standard_False;
1299 }
1300
1301 theCtx->core20fwd->glUniform1fv (theLocation, theCount, theData);
1302 return Standard_True;
1303}
1304
1305// =======================================================================
1306// function : SetUniform
1307// purpose : Specifies the value of the float2 uniform array
1308// =======================================================================
1309Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1310 GLint theLocation,
1311 GLuint theCount,
1312 const OpenGl_Vec2* theData)
1313{
1314 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1315 {
1316 return Standard_False;
1317 }
1318
1319 theCtx->core20fwd->glUniform2fv (theLocation, theCount, theData[0].GetData());
1320 return Standard_True;
1321}
1322
1323// =======================================================================
1324// function : SetUniform
1325// purpose : Specifies the value of the float3 uniform array
1326// =======================================================================
1327Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1328 GLint theLocation,
1329 GLuint theCount,
1330 const OpenGl_Vec3* theData)
1331{
1332 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1333 {
1334 return Standard_False;
1335 }
1336
1337 theCtx->core20fwd->glUniform3fv (theLocation, theCount, theData[0].GetData());
1338 return Standard_True;
1339}
1340
1341// =======================================================================
1342// function : SetUniform
1343// purpose : Specifies the value of the float4 uniform array
1344// =======================================================================
1345Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1346 GLint theLocation,
1347 GLuint theCount,
1348 const OpenGl_Vec4* theData)
1349{
1350 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1351 {
1352 return Standard_False;
1353 }
1354
1355 theCtx->core20fwd->glUniform4fv (theLocation, theCount, theData[0].GetData());
1356 return Standard_True;
1357}
1358
1359// =======================================================================
1360// function : SetUniform
1361// purpose : Specifies the value of the integer uniform array
1362// =======================================================================
1363Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1364 GLint theLocation,
1365 GLuint theCount,
1366 const Standard_Integer* theData)
1367{
1368 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1369 {
1370 return Standard_False;
1371 }
1372
1373 theCtx->core20fwd->glUniform1iv (theLocation, theCount, theData);
1374 return Standard_True;
1375}
1376
1377// =======================================================================
1378// function : SetUniform
1379// purpose : Specifies the value of the int2 uniform array
1380// =======================================================================
1381Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1382 GLint theLocation,
1383 GLuint theCount,
1384 const OpenGl_Vec2i* theData)
1385{
1386 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1387 {
1388 return Standard_False;
1389 }
1390
1391 theCtx->core20fwd->glUniform2iv (theLocation, theCount, theData[0].GetData());
1392 return Standard_True;
1393}
1394
1395// =======================================================================
1396// function : SetUniform
1397// purpose : Specifies the value of the int3 uniform array
1398// =======================================================================
1399Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1400 GLint theLocation,
1401 GLuint theCount,
1402 const OpenGl_Vec3i* theData)
1403{
1404 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1405 {
1406 return Standard_False;
1407 }
1408
1409 theCtx->core20fwd->glUniform3iv (theLocation, theCount, theData[0].GetData());
1410 return Standard_True;
1411}
1412
1413// =======================================================================
1414// function : SetUniform
1415// purpose : Specifies the value of the int4 uniform array
1416// =======================================================================
1417Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1418 GLint theLocation,
1419 GLuint theCount,
1420 const OpenGl_Vec4i* theData)
1421{
1422 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1423 {
1424 return Standard_False;
1425 }
1426
1427 theCtx->core20fwd->glUniform4iv (theLocation, theCount, theData[0].GetData());
1428 return Standard_True;
1429}
1430
1431// =======================================================================
1432// function : SetSampler
1433// purpose : Specifies the value of the sampler uniform variable
1434// =======================================================================
1435Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1436 const GLchar* theName,
1437 const Graphic3d_TextureUnit theTextureUnit)
1438{
1439 return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1440}
1441
1442// =======================================================================
1443// function : SetSampler
1444// purpose : Specifies the value of the sampler uniform variable
1445// =======================================================================
1446Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1447 GLint theLocation,
1448 const Graphic3d_TextureUnit theTextureUnit)
1449{
1450 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1451 {
1452 return Standard_False;
1453 }
1454
1455 theCtx->core20fwd->glUniform1i (theLocation, theTextureUnit);
1456 return Standard_True;
1457}
1458
1459// =======================================================================
1460// function : Create
1461// purpose : Creates new empty shader program of specified type
1462// =======================================================================
1463Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1464{
1465 if (myProgramID == NO_PROGRAM
1466 && theCtx->core20fwd != NULL)
1467 {
1468 myProgramID = theCtx->core20fwd->glCreateProgram();
1469 }
1470
1471 return myProgramID != NO_PROGRAM;
1472}
1473
1474// =======================================================================
1475// function : Release
1476// purpose : Destroys shader program
1477// =======================================================================
1478void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
1479{
1480 if (myProgramID == NO_PROGRAM)
1481 {
1482 return;
1483 }
1484
1485 Standard_ASSERT_RETURN (theCtx != NULL,
1486 "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1487
1488 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1489 {
1490 if (!anIter.Value().IsNull())
1491 {
1492 anIter.ChangeValue()->Release (theCtx);
1493 anIter.ChangeValue().Nullify();
1494 }
1495 }
1496
1497 if (theCtx->core20fwd != NULL
1498 && theCtx->IsValid())
1499 {
1500 theCtx->core20fwd->glDeleteProgram (myProgramID);
1501 }
1502
1503 myProgramID = NO_PROGRAM;
1504}
1505
1506// =======================================================================
1507// function : UpdateDebugDump
1508// purpose :
1509// =======================================================================
1510Standard_Boolean OpenGl_ShaderProgram::UpdateDebugDump (const Handle(OpenGl_Context)& theCtx,
1511 const TCollection_AsciiString& theFolder,
1512 Standard_Boolean theToBeautify,
1513 Standard_Boolean theToReset)
1514{
1515 if (myProgramID == NO_PROGRAM)
1516 {
1517 return Standard_False;
1518 }
1519
1520 TCollection_AsciiString aFolder = theFolder;
1521 if (aFolder.IsEmpty())
1522 {
1523 OSD_Environment aShaderVar ("CSF_ShadersDirectoryDump");
1524 aFolder = aShaderVar.Value();
1525 if (aFolder.IsEmpty())
1526 {
1527 aFolder = ".";
1528 }
1529 }
1530
1531 bool hasUpdates = false;
1532 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1533 {
1534 if (!anIter.Value().IsNull())
1535 {
1536 // desktop OpenGL (but not OpenGL ES) allows multiple shaders of the same stage to be attached,
1537 // but here we expect only single source per stage
1538 hasUpdates = anIter.ChangeValue()->updateDebugDump (theCtx, myResourceId, aFolder, theToBeautify, theToReset) || hasUpdates;
1539 }
1540 }
1541 if (hasUpdates)
1542 {
1543 return Link (theCtx);
1544 }
1545 return Standard_False;
1546}