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