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