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