0024323: TKOpenGl - spot light sources are not handled in Phong GLSL program
[occt.git] / src / OpenGl / OpenGl_ShaderProgram.cxx
CommitLineData
30f0ad28 1// Created on: 2013-09-19
2// Created by: Denis BOGOLEPOV
3// Copyright (c) 2013 OPEN CASCADE SAS
4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
30f0ad28 6//
973c2be1 7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public version 2.1 as published
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
19#include <Standard_Assert.hxx>
20#include <Standard_Atomic.hxx>
21#include <TCollection_ExtendedString.hxx>
22
23#include <OpenGl_Context.hxx>
24#include <OpenGl_ShaderProgram.hxx>
25#include <OpenGl_ShaderManager.hxx>
26
27IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
28IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
29
30OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
31
32// Declare OCCT-specific OpenGL/GLSL shader variables
33Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
34{
12381341 35 "occModelWorldMatrix", // OpenGl_OCC_MODEL_WORLD_MATRIX
36 "occWorldViewMatrix", // OpenGl_OCC_WORLD_VIEW_MATRIX
37 "occProjectionMatrix", // OpenGl_OCC_PROJECTION_MATRIX
38 "occModelWorldMatrixInverse", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
39 "occWorldViewMatrixInverse", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
40 "occProjectionMatrixInverse", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
41 "occModelWorldMatrixTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
42 "occWorldViewMatrixTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
43 "occProjectionMatrixTranspose", // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
44 "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
45 "occWorldViewMatrixInverseTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
46 "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
47
48 "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
49 "occClipPlaneSpaces", // OpenGl_OCC_CLIP_PLANE_SPACES
50
51 "occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT
52 "occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES
53 "occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS
54 "occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT
55
56 "occActiveSampler", // OpenGl_OCCT_ACTIVE_SAMPLER
57 "occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE
58 "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
59 "occFrontMaterial", // OpenGl_OCCT_FRONT_MATERIAL
60 "occBackMaterial" // OpenGl_OCCT_BACK_MATERIAL
30f0ad28 61
62};
63
64// =======================================================================
65// function : OpenGl_VariableSetterSelector
66// purpose : Creates new variable setter selector
67// =======================================================================
68OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
69{
70 // Note: Add new variable setters here
71 mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
72 (Graphic3d_UniformValueTypeID<int>::ID, new OpenGl_VariableSetter<int>())
73 (Graphic3d_UniformValueTypeID<float>::ID, new OpenGl_VariableSetter<float>())
74 (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID, new OpenGl_VariableSetter<OpenGl_Vec2>())
75 (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID, new OpenGl_VariableSetter<OpenGl_Vec3>())
76 (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID, new OpenGl_VariableSetter<OpenGl_Vec4>())
77 (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
78 (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
79 (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
80}
81
82// =======================================================================
83// function : ~OpenGl_VariableSetterSelector
84// purpose : Releases memory resources of variable setter selector
85// =======================================================================
86OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
87{
88 for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
89 {
90 delete anIt.Value();
91 }
92
93 mySetterList.Clear();
94}
95
96// =======================================================================
97// function : Set
98// purpose : Sets generic variable to specified shader program
99// =======================================================================
100void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)& theCtx,
101 const Handle(Graphic3d_ShaderVariable)& theVariable,
102 OpenGl_ShaderProgram* theProgram) const
103{
104 Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
105 "The type of user-defined uniform variable is not supported...", );
106
107 mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
108}
109
110// =======================================================================
111// function : OpenGl_ShaderProgram
112// purpose : Creates uninitialized shader program
113// =======================================================================
114OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
115: myProgramID (NO_PROGRAM),
392ac980 116 myProxy (theProxy),
117 myShareCount(1)
30f0ad28 118{
119 memset (myCurrentState, 0, sizeof (myCurrentState));
120 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
121 {
122 myStateLocations[aVar] = INVALID_LOCATION;
123 }
124}
125
126// =======================================================================
127// function : Initialize
128// purpose : Initializes program object with the list of shader objects
129// =======================================================================
130Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& theCtx,
131 const Graphic3d_ShaderObjectList& theShaders)
132{
133 if (theCtx.IsNull() || !Create (theCtx))
134 {
135 return Standard_False;
136 }
137
12381341 138 OSD_File aDeclFile (Graphic3d_ShaderProgram::ShadersFolder() + "/Declarations.glsl");
139 OSD_File aDeclImplFile (Graphic3d_ShaderProgram::ShadersFolder() + "/DeclarationsImpl.glsl");
140 if (!aDeclFile.Exists()
141 || !aDeclImplFile.Exists())
30f0ad28 142 {
392ac980 143 const TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
30f0ad28 144 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
145 GL_DEBUG_TYPE_ERROR_ARB,
146 0,
147 GL_DEBUG_SEVERITY_HIGH_ARB,
148 aMsg);
30f0ad28 149 return Standard_False;
150 }
151
152 TCollection_AsciiString aDeclarations;
30f0ad28 153 aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
bd0b3e60 154 aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
30f0ad28 155 aDeclFile.Close();
156
12381341 157 TCollection_AsciiString aDeclImpl;
158 aDeclImplFile.Open (OSD_ReadOnly, OSD_Protection());
159 aDeclImplFile.Read (aDeclImpl, (int)aDeclImplFile.Size());
160 aDeclImplFile.Close();
161 aDeclarations += aDeclImpl;
162
30f0ad28 163 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
164 anIter.More(); anIter.Next())
165 {
166 if (!anIter.Value()->IsDone())
167 {
392ac980 168 const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
30f0ad28 169 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
170 GL_DEBUG_TYPE_ERROR_ARB,
171 0,
172 GL_DEBUG_SEVERITY_HIGH_ARB,
173 aMsg);
30f0ad28 174 return Standard_False;
175 }
176
177 Handle(OpenGl_ShaderObject) aShader;
178
179 // Note: Add support of other shader types here
180 switch (anIter.Value()->Type())
181 {
182 case Graphic3d_TOS_VERTEX:
183 aShader = new OpenGl_ShaderObject (GL_VERTEX_SHADER);
184 break;
185 case Graphic3d_TOS_FRAGMENT:
186 aShader = new OpenGl_ShaderObject (GL_FRAGMENT_SHADER);
187 break;
188 }
189
190 // Is unsupported shader type?
191 if (aShader.IsNull())
192 {
193 TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
30f0ad28 194 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
195 GL_DEBUG_TYPE_ERROR_ARB,
196 0,
197 GL_DEBUG_SEVERITY_HIGH_ARB,
198 aMsg);
30f0ad28 199 return Standard_False;
200 }
201
202 if (!aShader->Create (theCtx))
203 {
392ac980 204 aShader->Release (theCtx.operator->());
30f0ad28 205 return Standard_False;
206 }
207
208 TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
30f0ad28 209 if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
210 {
211 aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
212 }
213
214 if (!aShader->LoadSource (theCtx, aSource))
215 {
392ac980 216 const TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
30f0ad28 217 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
218 GL_DEBUG_TYPE_ERROR_ARB,
219 0,
220 GL_DEBUG_SEVERITY_HIGH_ARB,
221 aMsg);
392ac980 222 aShader->Release (theCtx.operator->());
30f0ad28 223 return Standard_False;
224 }
225
226 if (!aShader->Compile (theCtx))
227 {
392ac980 228 TCollection_AsciiString aLog;
229 aShader->FetchInfoLog (theCtx, aLog);
230 if (aLog.IsEmpty())
231 {
232 aLog = "Compilation log is empty.";
233 }
30f0ad28 234 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
235 GL_DEBUG_TYPE_ERROR_ARB,
236 0,
237 GL_DEBUG_SEVERITY_HIGH_ARB,
392ac980 238 TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
239 aShader->Release (theCtx.operator->());
240 return Standard_False;
241 }
242 else if (theCtx->caps->glslWarnings)
243 {
244 TCollection_AsciiString aLog;
245 aShader->FetchInfoLog (theCtx, aLog);
246 if (!aLog.IsEmpty()
247 && !aLog.IsEqual ("No errors.\n"))
30f0ad28 248 {
392ac980 249 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
250 GL_DEBUG_TYPE_PORTABILITY_ARB,
251 0,
252 GL_DEBUG_SEVERITY_LOW_ARB,
253 TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
30f0ad28 254 }
30f0ad28 255 }
256
257 if (!AttachShader (theCtx, aShader))
258 {
392ac980 259 aShader->Release (theCtx.operator->());
30f0ad28 260 return Standard_False;
261 }
262 }
263
264 if (!Link (theCtx))
265 {
392ac980 266 TCollection_AsciiString aLog;
267 FetchInfoLog (theCtx, aLog);
268 if (aLog.IsEmpty())
269 {
270 aLog = "Linker log is empty.";
271 }
30f0ad28 272 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
273 GL_DEBUG_TYPE_ERROR_ARB,
274 0,
275 GL_DEBUG_SEVERITY_HIGH_ARB,
12381341 276 TCollection_ExtendedString ("Failed to link program object! Linker log:\n") + aLog);
392ac980 277 return Standard_False;
278 }
279 else if (theCtx->caps->glslWarnings)
280 {
281 TCollection_AsciiString aLog;
282 FetchInfoLog (theCtx, aLog);
283 if (!aLog.IsEmpty()
284 && !aLog.IsEqual ("No errors.\n"))
30f0ad28 285 {
392ac980 286 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
287 GL_DEBUG_TYPE_PORTABILITY_ARB,
288 0,
289 GL_DEBUG_SEVERITY_LOW_ARB,
290 TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
30f0ad28 291 }
30f0ad28 292 }
293
294 return Standard_True;
295}
296
297// =======================================================================
298// function : ~OpenGl_ShaderProgram
299// purpose : Releases resources of shader program
300// =======================================================================
301OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
302{
303 Release (NULL);
304}
305
306// =======================================================================
307// function : AttachShader
308// purpose : Attaches shader object to the program object
309// =======================================================================
310Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)& theCtx,
311 const Handle(OpenGl_ShaderObject)& theShader)
312{
313 if (myProgramID == NO_PROGRAM || theShader.IsNull())
314 {
315 return Standard_False;
316 }
317
318 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
319 {
320 if (theShader == anIter.Value())
321 {
322 return Standard_False;
323 }
324 }
325
326 myShaderObjects.Append (theShader);
327 theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID);
328 return Standard_True;
329}
330
331// =======================================================================
332// function : DetachShader
333// purpose : Detaches shader object to the program object
334// =======================================================================
335Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)& theCtx,
336 const Handle(OpenGl_ShaderObject)& theShader)
337{
338 if (myProgramID == NO_PROGRAM
339 || theShader.IsNull())
340 {
341 return Standard_False;
342 }
343
344 OpenGl_ShaderList::Iterator anIter (myShaderObjects);
345 while (anIter.More())
346 {
347 if (theShader == anIter.Value())
348 {
349 myShaderObjects.Remove (anIter);
350 break;
351 }
352
353 anIter.Next();
354 }
355
356 if (!anIter.More())
357 {
358 return Standard_False;
359 }
360
361 theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID);
362 return Standard_True;
363}
364
365// =======================================================================
366// function : Link
367// purpose : Links the program object
368// =======================================================================
369Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx)
370{
371 if (myProgramID == NO_PROGRAM)
372 {
373 return Standard_False;
374 }
375
376 theCtx->core20->glLinkProgram (myProgramID);
377
378 GLint aStatus = GL_FALSE;
379 theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
380
381 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
382 {
383 myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
384 }
385
386 return aStatus != GL_FALSE;
387}
388
389// =======================================================================
390// function : FetchInfoLog
391// purpose : Fetches information log of the last link operation
392// =======================================================================
393Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
394 TCollection_AsciiString& theOutput)
395{
396 if (myProgramID == NO_PROGRAM)
397 {
398 return Standard_False;
399 }
400
401 GLint aLength = 0;
402 theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
403 if (aLength > 0)
404 {
405 GLchar* aLog = (GLchar*) alloca (aLength);
406 memset (aLog, 0, aLength);
407 theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
408 theOutput = aLog;
409 }
410 return Standard_True;
411}
412
413// =======================================================================
414// function : Bind
415// purpose : Sets the program object as part of current rendering state
416// =======================================================================
417void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const
418{
419 if (myProgramID == NO_PROGRAM)
420 {
421 return;
422 }
423
424 theCtx->core20->glUseProgram (myProgramID);
425 theCtx->ShaderManager()->myIsPP = Standard_True;
426}
427
428// =======================================================================
429// function : ApplyVariables
430// purpose : Fetches uniform variables from proxy shader program
431// =======================================================================
432Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
433{
434 if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
435 {
436 return Standard_False;
437 }
438
439 for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
440 {
441 mySetterSelector.Set (theCtx, anIter.Value(), this);
442 }
443
444 myProxy->ClearVariables();
445 return Standard_True;
446}
447
448// =======================================================================
449// function : BindWithVariables
450// purpose : Binds the program object and applies variables
451// =======================================================================
452Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx)
453{
454 Bind (theCtx);
455 return ApplyVariables (theCtx);
456}
457
458// =======================================================================
459// function : Unbind
460// purpose : Reverts to fixed-function graphics pipeline (FFP)
461// =======================================================================
462void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx)
463{
464 if (theCtx->ShaderManager()->myIsPP)
465 {
466 theCtx->core20->glUseProgram (NO_PROGRAM);
467 theCtx->ShaderManager()->myIsPP = Standard_False;
468 }
469}
470
471// =======================================================================
472// function : ActiveState
473// purpose : Returns index of last modification for specified state type
474// =======================================================================
475Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
476{
477 if (theType < MaxStateTypes)
478 {
479 return myCurrentState[theType];
480 }
481 return 0;
482}
483
484// =======================================================================
485// function : UpdateState
486// purpose : Updates index of last modification for specified state type
487// =======================================================================
488void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
489 const Standard_Size theIndex)
490{
491 if (theType < MaxStateTypes)
492 {
493 myCurrentState[theType] = theIndex;
494 }
495}
496
497// =======================================================================
498// function : GetUniformLocation
499// purpose : Returns location (index) of the specific uniform variable
500// =======================================================================
501GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
502 const GLchar* theName) const
503{
504 return myProgramID != NO_PROGRAM
505 ? theCtx->core20->glGetUniformLocation (myProgramID, theName)
506 : INVALID_LOCATION;
507}
508
509// =======================================================================
510// function : GetAttributeLocation
511// purpose : Returns location (index) of the generic vertex attribute
512// =======================================================================
513GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
514 const GLchar* theName) const
515{
516 return myProgramID != NO_PROGRAM
517 ? theCtx->core20->glGetAttribLocation (myProgramID, theName)
518 : INVALID_LOCATION;
519}
520
521// =======================================================================
522// function : GetStateLocation
523// purpose : Returns location of the OCCT state uniform variable
524// =======================================================================
525GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
526{
527 if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
528 {
529 return myStateLocations[theVariable];
530 }
531 return INVALID_LOCATION;
532}
533
534// =======================================================================
535// function : GetUniform
536// purpose : Returns the value of the integer uniform variable
537// =======================================================================
538Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
539 const GLchar* theName,
540 OpenGl_Vec4i& theValue) const
541{
542 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
543}
544
545// =======================================================================
546// function : GetUniform
547// purpose : Returns the value of the integer uniform variable
548// =======================================================================
549Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
550 GLint theLocation,
551 OpenGl_Vec4i& theValue) const
552{
553 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
554 {
555 return Standard_False;
556 }
557
558 theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue);
559 return Standard_True;
560}
561
562// =======================================================================
563// function : GetUniform
564// purpose : Returns the value of the floating-point uniform variable
565// =======================================================================
566Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
567 const GLchar* theName,
568 OpenGl_Vec4& theValue) const
569{
570 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
571}
572
573// =======================================================================
574// function : GetUniform
575// purpose : Returns the value of the floating-point uniform variable
576// =======================================================================
577Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
578 GLint theLocation,
579 OpenGl_Vec4& theValue) const
580{
581 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
582 {
583 return Standard_False;
584 }
585
586 theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue);
587 return Standard_True;
588}
589
590// =======================================================================
591// function : GetAttribute
592// purpose : Returns the integer vertex attribute
593// =======================================================================
594Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
595 const GLchar* theName,
596 OpenGl_Vec4i& theValue) const
597{
598 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
599}
600
601// =======================================================================
602// function : GetAttribute
603// purpose : Returns the integer vertex attribute
604// =======================================================================
605Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
606 GLint theIndex,
607 OpenGl_Vec4i& theValue) const
608{
609 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
610 {
611 return Standard_False;
612 }
613
614 theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
615 return Standard_True;
616}
617
618// =======================================================================
619// function : GetAttribute
620// purpose : Returns the floating-point vertex attribute
621// =======================================================================
622Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
623 const GLchar* theName,
624 OpenGl_Vec4& theValue) const
625{
626 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
627}
628
629// =======================================================================
630// function : GetAttribute
631// purpose : Returns the floating-point vertex attribute
632// =======================================================================
633Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
634 GLint theIndex,
635 OpenGl_Vec4& theValue) const
636{
637 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
638 {
639 return Standard_False;
640 }
641
642 theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
643 return Standard_True;
644}
645
646// =======================================================================
647// function : SetUniform
648// purpose : Specifies the value of the integer uniform variable
649// =======================================================================
650Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
651 const GLchar* theName,
652 GLint theValue)
653{
654 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
655}
656
657// =======================================================================
658// function : SetUniform
659// purpose : Specifies the value of the integer uniform variable
660// =======================================================================
661Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
662 GLint theLocation,
663 GLint theValue)
664{
665 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
666 {
667 return Standard_False;
668 }
669
670 theCtx->core20->glUniform1i (theLocation, theValue);
671 return Standard_True;
672}
673
674// =======================================================================
675// function : SetUniform
676// purpose : Specifies the value of the floating-point uniform variable
677// =======================================================================
678Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
679 const GLchar* theName,
680 GLfloat theValue)
681{
682 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
683}
684
685// =======================================================================
686// function : SetUniform
687// purpose : Specifies the value of the floating-point uniform variable
688// =======================================================================
689Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
690 GLint theLocation,
691 GLfloat theValue)
692{
693 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
694 {
695 return Standard_False;
696 }
697
698 theCtx->core20->glUniform1f (theLocation, theValue);
699 return Standard_True;
700}
701
702// =======================================================================
703// function : SetUniform
704// purpose : Specifies the value of the integer uniform 2D vector
705// =======================================================================
706Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
707 const GLchar* theName,
708 const OpenGl_Vec2i& theValue)
709{
710 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
711}
712
713// =======================================================================
714// function : SetUniform
715// purpose : Specifies the value of the integer uniform 2D vector
716// =======================================================================
717Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
718 GLint theLocation,
719 const OpenGl_Vec2i& theValue)
720{
721 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
722 {
723 return Standard_False;
724 }
725
726 theCtx->core20->glUniform2iv (theLocation, 1, theValue);
727 return Standard_True;
728}
729
730// =======================================================================
731// function : SetUniform
732// purpose : Specifies the value of the integer uniform 3D vector
733// =======================================================================
734Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
735 const GLchar* theName,
736 const OpenGl_Vec3i& theValue)
737{
738 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
739}
740
741// =======================================================================
742// function : SetUniform
743// purpose : Specifies the value of the integer uniform 3D vector
744// =======================================================================
745Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
746 GLint theLocation,
747 const OpenGl_Vec3i& theValue)
748{
749 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
750 {
751 return Standard_False;
752 }
753
754 theCtx->core20->glUniform3iv (theLocation, 1, theValue);
755 return Standard_True;
756}
757
758// =======================================================================
759// function : SetUniform
760// purpose : Specifies the value of the integer uniform 4D vector
761// =======================================================================
762Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
763 const GLchar* theName,
764 const OpenGl_Vec4i& theValue)
765{
766 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
767}
768
769// =======================================================================
770// function : SetUniform
771// purpose : Specifies the value of the integer uniform 4D vector
772// =======================================================================
773Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
774 GLint theLocation,
775 const OpenGl_Vec4i& theValue)
776{
777 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
778 {
779 return Standard_False;
780 }
781
782 theCtx->core20->glUniform4iv (theLocation, 1, theValue);
783 return Standard_True;
784}
785
786// =======================================================================
787// function : SetUniform
788// purpose : Specifies the value of the floating-point uniform 2D vector
789// =======================================================================
790Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
791 const GLchar* theName,
792 const OpenGl_Vec2& theValue)
793{
794 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
795}
796
797// =======================================================================
798// function : SetUniform
799// purpose : Specifies the value of the floating-point uniform 2D vector
800// =======================================================================
801Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
802 GLint theLocation,
803 const OpenGl_Vec2& theValue)
804{
805 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
806 {
807 return Standard_False;
808 }
809
810 theCtx->core20->glUniform2fv (theLocation, 1, theValue);
811 return Standard_True;
812}
813
814// =======================================================================
815// function : SetUniform
816// purpose : Specifies the value of the floating-point uniform 3D vector
817// =======================================================================
818Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
819 const GLchar* theName,
820 const OpenGl_Vec3& theValue)
821{
822 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
823}
824
825// =======================================================================
826// function : SetUniform
827// purpose : Specifies the value of the floating-point uniform 3D vector
828// =======================================================================
829Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
830 GLint theLocation,
831 const OpenGl_Vec3& theValue)
832{
833 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
834 {
835 return Standard_False;
836 }
837
838 theCtx->core20->glUniform3fv (theLocation, 1, theValue);
839 return Standard_True;
840}
841
842// =======================================================================
843// function : SetUniform
844// purpose : Specifies the value of the floating-point uniform 4D vector
845// =======================================================================
846Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
847 const GLchar* theName,
848 const OpenGl_Vec4& theValue)
849{
850 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
851}
852
853// =======================================================================
854// function : SetUniform
855// purpose : Specifies the value of the floating-point uniform 4D vector
856// =======================================================================
857Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
858 GLint theLocation,
859 const OpenGl_Vec4& theValue)
860{
861 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
862 {
863 return Standard_False;
864 }
865
866 theCtx->core20->glUniform4fv (theLocation, 1, theValue);
867 return Standard_True;
868}
869
870// =======================================================================
871// function : SetUniform
872// purpose : Specifies the value of the floating-point uniform 4x4 matrix
873// =======================================================================
874Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
875 const GLchar* theName,
876 const OpenGl_Matrix& theValue,
877 GLboolean theTranspose)
878{
879 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
880}
881
882// =======================================================================
883// function : SetUniform
884// purpose : Specifies the value of the floating-point uniform 4x4 matrix
885// =======================================================================
886Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
887 GLint theLocation,
888 const OpenGl_Matrix& theValue,
889 GLboolean theTranspose)
890{
891 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
892 {
893 return Standard_False;
894 }
895
896 theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat);
897 return Standard_True;
898}
899
900// =======================================================================
901// function : SetUniform
902// purpose : Specifies the value of the floating-point uniform 4x4 matrix
903// =======================================================================
904Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
905 const GLchar* theName,
906 const Tmatrix3& theValue,
907 GLboolean theTranspose)
908{
909 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
910}
911
912// =======================================================================
913// function : SetUniform
914// purpose : Specifies the value of the floating-point uniform 4x4 matrix
915// =======================================================================
916Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
917 GLint theLocation,
918 const Tmatrix3& theValue,
919 GLboolean theTranspose)
920{
921 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
922 {
923 return Standard_False;
924 }
925
926 theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue);
927 return Standard_True;
928}
929
4fe9ad57 930// =======================================================================
931// function : SetUniform
932// purpose : Specifies the value of the float uniform array
933// =======================================================================
934Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
935 GLint theLocation,
936 GLuint theCount,
937 const Standard_ShortReal* theData)
938{
939 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
940 {
941 return Standard_False;
942 }
943
944 theCtx->core20->glUniform1fv (theLocation, theCount, theData);
945 return Standard_True;
946}
947
948// =======================================================================
949// function : SetUniform
950// purpose : Specifies the value of the float2 uniform array
951// =======================================================================
952Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
953 GLint theLocation,
954 GLuint theCount,
955 const OpenGl_Vec2* theData)
956{
957 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
958 {
959 return Standard_False;
960 }
961
962 theCtx->core20->glUniform2fv (theLocation, theCount, theData[0].GetData());
963 return Standard_True;
964}
965
966// =======================================================================
967// function : SetUniform
968// purpose : Specifies the value of the float3 uniform array
969// =======================================================================
970Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
971 GLint theLocation,
972 GLuint theCount,
973 const OpenGl_Vec3* theData)
974{
975 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
976 {
977 return Standard_False;
978 }
979
980 theCtx->core20->glUniform3fv (theLocation, theCount, theData[0].GetData());
981 return Standard_True;
982}
983
984// =======================================================================
985// function : SetUniform
986// purpose : Specifies the value of the float4 uniform array
987// =======================================================================
988Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
989 GLint theLocation,
990 GLuint theCount,
991 const OpenGl_Vec4* theData)
992{
993 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
994 {
995 return Standard_False;
996 }
997
998 theCtx->core20->glUniform4fv (theLocation, theCount, theData[0].GetData());
999 return Standard_True;
1000}
1001
1002// =======================================================================
1003// function : SetUniform
1004// purpose : Specifies the value of the integer uniform array
1005// =======================================================================
1006Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1007 GLint theLocation,
1008 GLuint theCount,
1009 const Standard_Integer* theData)
1010{
1011 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1012 {
1013 return Standard_False;
1014 }
1015
1016 theCtx->core20->glUniform1iv (theLocation, theCount, theData);
1017 return Standard_True;
1018}
1019
1020// =======================================================================
1021// function : SetUniform
1022// purpose : Specifies the value of the int2 uniform array
1023// =======================================================================
1024Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1025 GLint theLocation,
1026 GLuint theCount,
1027 const OpenGl_Vec2i* theData)
1028{
1029 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1030 {
1031 return Standard_False;
1032 }
1033
1034 theCtx->core20->glUniform2iv (theLocation, theCount, theData[0].GetData());
1035 return Standard_True;
1036}
1037
1038// =======================================================================
1039// function : SetUniform
1040// purpose : Specifies the value of the int3 uniform array
1041// =======================================================================
1042Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1043 GLint theLocation,
1044 GLuint theCount,
1045 const OpenGl_Vec3i* theData)
1046{
1047 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1048 {
1049 return Standard_False;
1050 }
1051
1052 theCtx->core20->glUniform3iv (theLocation, theCount, theData[0].GetData());
1053 return Standard_True;
1054}
1055
1056// =======================================================================
1057// function : SetUniform
1058// purpose : Specifies the value of the int4 uniform array
1059// =======================================================================
1060Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1061 GLint theLocation,
1062 GLuint theCount,
1063 const OpenGl_Vec4i* theData)
1064{
1065 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1066 {
1067 return Standard_False;
1068 }
1069
1070 theCtx->core20->glUniform4iv (theLocation, theCount, theData[0].GetData());
1071 return Standard_True;
1072}
1073
30f0ad28 1074// =======================================================================
1075// function : SetSampler
1076// purpose : Specifies the value of the sampler uniform variable
1077// =======================================================================
1078Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1079 const GLchar* theName,
1080 const GLenum theTextureUnit)
1081{
1082 return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1083}
1084
1085// =======================================================================
1086// function : SetSampler
1087// purpose : Specifies the value of the sampler uniform variable
1088// =======================================================================
1089Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1090 GLint theLocation,
1091 const GLenum theTextureUnit)
1092{
1093 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1094 {
1095 return Standard_False;
1096 }
1097
1098 theCtx->core20->glUniform1i (theLocation, theTextureUnit);
1099 return Standard_True;
1100}
1101
1102// =======================================================================
1103// function : Create
1104// purpose : Creates new empty shader program of specified type
1105// =======================================================================
1106Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1107{
1108 if (myProgramID == NO_PROGRAM
1109 && theCtx->core20 != NULL)
1110 {
1111 myProgramID = theCtx->core20->glCreateProgram();
1112 }
1113
1114 return myProgramID != NO_PROGRAM;
1115}
1116
1117// =======================================================================
1118// function : Release
1119// purpose : Destroys shader program
1120// =======================================================================
1121void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx)
1122{
1123 if (myProgramID == NO_PROGRAM)
1124 {
1125 return;
1126 }
1127
1128 Standard_ASSERT_RETURN (theCtx != NULL,
1129 "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1130
1131 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1132 {
1133 anIter.ChangeValue()->Release (theCtx);
1134 anIter.ChangeValue().Nullify();
1135 }
1136
ec2eeb2d 1137 if (theCtx->core20 != NULL
1138 && theCtx->IsValid())
30f0ad28 1139 {
1140 theCtx->core20->glDeleteProgram (myProgramID);
1141 }
1142
1143 myProgramID = NO_PROGRAM;
1144}