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