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