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