0025282: Visualization, OpenGl_PrimitiveArray - provide built-in GLSL programs as...
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
CommitLineData
30f0ad28 1// Created on: 2013-09-26
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 <typeinfo>
17
18#include <OpenGl_AspectFace.hxx>
19#include <OpenGl_AspectLine.hxx>
20#include <OpenGl_AspectMarker.hxx>
21#include <OpenGl_AspectText.hxx>
22#include <OpenGl_Clipping.hxx>
23#include <OpenGl_Context.hxx>
24#include <OpenGl_ShaderManager.hxx>
25#include <OpenGl_ShaderProgram.hxx>
0adbd30f 26#include <OpenGl_Workspace.hxx>
30f0ad28 27
28IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
29IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
30
8625ef7e 31namespace
32{
33
34#define EOL "\n"
35
36//! Auxiliary function to transform normal
37const char THE_FUNC_transformNormal[] =
38 EOL"vec3 transformNormal (in vec3 theNormal)"
39 EOL"{"
40 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
41 EOL" * occModelWorldMatrixInverseTranspose"
42 EOL" * vec4 (theNormal, 0.0);"
43 EOL" return normalize (aResult.xyz);"
44 EOL"}";
45
46//! Global shader variable for color definition with lighting enabled.
47const char THE_FUNC_lightDef[] =
48 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
49 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
50 EOL"vec3 Specular;"; //!< Specular contribution of light sources
51
52//! Computes illumination from light sources
53const char THE_FUNC_computeLighting[] =
54 EOL"vec4 computeLighting (in vec3 theNormal,"
55 EOL" in vec3 theView,"
56 EOL" in vec4 thePoint,"
57 EOL" in bool theIsFront)"
58 EOL"{"
59 // clear the light intensity accumulators
60 EOL" Ambient = occLightAmbient.rgb;"
61 EOL" Diffuse = vec3 (0.0);"
62 EOL" Specular = vec3 (0.0);"
63 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
64 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
65 EOL" {"
66 EOL" int aType = occLight_Type (anIndex);"
67 EOL" if (aType == OccLightType_Direct)"
68 EOL" {"
69 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
70 EOL" }"
71 EOL" else if (aType == OccLightType_Point)"
72 EOL" {"
73 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
74 EOL" }"
75 EOL" else if (aType == OccLightType_Spot)"
76 EOL" {"
77 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
78 EOL" }"
79 EOL" }"
80 EOL
81 EOL" vec4 aMaterialAmbient = theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();"
82 EOL" vec4 aMaterialDiffuse = theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();"
83 EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
84 EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
85 EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
86 EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
87 EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
88 EOL" + aMaterialEmission;"
89 EOL"}";
90
91//! Function computes contribution of isotropic point light source
92const char THE_FUNC_pointLight[] =
93 EOL"void pointLight (in int theId,"
94 EOL" in vec3 theNormal,"
95 EOL" in vec3 theView,"
96 EOL" in vec3 thePoint,"
97 EOL" in bool theIsFront)"
98 EOL"{"
99 EOL" vec3 aLight = occLight_Position (theId).xyz;"
100 EOL" if (occLight_IsHeadlight (theId) == 0)"
101 EOL" {"
102 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
103 EOL" }"
104 EOL" aLight -= thePoint;"
105 EOL
106 EOL" float aDist = length (aLight);"
107 EOL" aLight = aLight * (1.0 / aDist);"
108 EOL
109 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
110 EOL" + occLight_LinearAttenuation (theId) * aDist);"
111 EOL
112 EOL" vec3 aHalf = normalize (aLight + theView);"
113 EOL
114 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
115 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
116 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
117 EOL
118 EOL" float aSpecl = 0.0;"
119 EOL" if (aNdotL > 0.0)"
120 EOL" {"
121 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
122 EOL" }"
123 EOL
124 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
125 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
126 EOL"}";
127
128//! Function computes contribution of spotlight source
129const char THE_FUNC_spotLight[] =
130 EOL"void spotLight (in int theId,"
131 EOL" in vec3 theNormal,"
132 EOL" in vec3 theView,"
133 EOL" in vec3 thePoint,"
134 EOL" in bool theIsFront)"
135 EOL"{"
136 EOL" vec3 aLight = occLight_Position (theId).xyz;"
137 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
138 EOL" if (occLight_IsHeadlight (theId) == 0)"
139 EOL" {"
140 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
141 EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
142 EOL" }"
143 EOL" aLight -= thePoint;"
144 EOL
145 EOL" float aDist = length (aLight);"
146 EOL" aLight = aLight * (1.0 / aDist);"
147 EOL
148 EOL" aSpotDir = normalize (aSpotDir);"
149 // light cone
150 EOL" float aCosA = dot (aSpotDir, -aLight);"
151 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
152 EOL" {"
153 EOL" return;"
154 EOL" }"
155 EOL
156 EOL" float anExponent = occLight_SpotExponent (theId);"
157 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
158 EOL" + occLight_LinearAttenuation (theId) * aDist);"
159 EOL" if (anExponent > 0.0)"
160 EOL" {"
161 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
162 EOL" }"
163 EOL
164 EOL" vec3 aHalf = normalize (aLight + theView);"
165 EOL
166 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
167 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
168 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
169 EOL
170 EOL" float aSpecl = 0.0;"
171 EOL" if (aNdotL > 0.0)"
172 EOL" {"
173 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
174 EOL" }"
175 EOL
176 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
177 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
178 EOL"}";
179
180//! Function computes contribution of directional light source
181const char THE_FUNC_directionalLight[] =
182 EOL"void directionalLight (in int theId,"
183 EOL" in vec3 theNormal,"
184 EOL" in vec3 theView,"
185 EOL" in bool theIsFront)"
186 EOL"{"
187 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
188 EOL" if (occLight_IsHeadlight (theId) == 0)"
189 EOL" {"
190 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
191 EOL" }"
192 EOL
193 EOL" vec3 aHalf = normalize (aLight + theView);"
194 EOL
195 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
196 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
197 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
198 EOL
199 EOL" float aSpecl = 0.0;"
200 EOL" if (aNdotL > 0.0)"
201 EOL" {"
202 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
203 EOL" }"
204 EOL
205 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
206 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
207 EOL"}";
208
209//! Process clipping planes in Fragment Shader.
210//! Should be added at the beginning of the main() function.
211const char THE_FRAG_CLIP_PLANES[] =
212 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
213 EOL" {"
214 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
215 EOL" int aClipSpace = occClipPlaneSpaces[aPlaneIter];"
216 EOL" if (aClipSpace == OccEquationCoords_World)"
217 EOL" {"
218 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)"
219 EOL" {"
220 EOL" discard;"
221 EOL" }"
222 EOL" }"
223 EOL" else if (aClipSpace == OccEquationCoords_View)"
224 EOL" {"
225 EOL" if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)"
226 EOL" {"
227 EOL" discard;"
228 EOL" }"
229 EOL" }"
230 EOL" }";
231
232}
233
30f0ad28 234// =======================================================================
235// function : OpenGl_ShaderManager
236// purpose : Creates new empty shader manager
237// =======================================================================
238OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
8625ef7e 239: myShadingModel (Visual3d_TOM_VERTEX),
240 myContext (theContext),
e6804ff7 241 myLastView (NULL)
30f0ad28 242{
8625ef7e 243 myLightPrograms = myGouraudPrograms;
30f0ad28 244}
245
246// =======================================================================
247// function : ~OpenGl_ShaderManager
248// purpose : Releases resources of shader manager
249// =======================================================================
250OpenGl_ShaderManager::~OpenGl_ShaderManager()
251{
252 myProgramList.Clear();
253}
254
255// =======================================================================
256// function : Create
257// purpose : Creates new shader program
258// =======================================================================
8625ef7e 259Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
260 TCollection_AsciiString& theShareKey,
261 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 262{
392ac980 263 theProgram.Nullify();
264 if (theProxy.IsNull())
30f0ad28 265 {
8625ef7e 266 return Standard_False;
30f0ad28 267 }
392ac980 268
269 theShareKey = theProxy->GetId();
270 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
271 {
05dd08ce 272 if (theProgram->Share())
273 {
274 myProgramList.Append (theProgram);
275 }
8625ef7e 276 return Standard_True;
392ac980 277 }
278
279 theProgram = new OpenGl_ShaderProgram (theProxy);
280 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
30f0ad28 281 {
392ac980 282 theProgram->Release (myContext);
283 theShareKey.Clear();
284 theProgram.Nullify();
8625ef7e 285 return Standard_False;
30f0ad28 286 }
30f0ad28 287
392ac980 288 myProgramList.Append (theProgram);
289 myContext->ShareResource (theShareKey, theProgram);
8625ef7e 290 return Standard_True;
30f0ad28 291}
292
293// =======================================================================
294// function : Unregister
295// purpose : Removes specified shader program from the manager
296// =======================================================================
392ac980 297void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
298 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 299{
300 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
301 {
302 if (anIt.Value() == theProgram)
303 {
392ac980 304 if (!theProgram->UnShare())
305 {
306 theShareKey.Clear();
307 theProgram.Nullify();
308 return;
309 }
310
30f0ad28 311 myProgramList.Remove (anIt);
392ac980 312 myMaterialStates.UnBind (theProgram);
30f0ad28 313 break;
314 }
315 }
316
317 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
318 if (anID.IsEmpty())
319 {
320 myContext->DelayedRelease (theProgram);
321 theProgram.Nullify();
322 }
323 else
324 {
325 theProgram.Nullify();
05dd08ce 326 myContext->ReleaseResource (anID, Standard_True);
30f0ad28 327 }
328}
329
330// =======================================================================
331// function : ShaderPrograms
332// purpose : Returns list of registered shader programs
333// =======================================================================
334const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
335{
336 return myProgramList;
337}
338
339// =======================================================================
340// function : Empty
341// purpose : Returns true if no program objects are attached
342// =======================================================================
343Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
344{
345 return myProgramList.IsEmpty();
346}
347
348// =======================================================================
349// function : UpdateLightSourceStateTo
350// purpose : Updates state of OCCT light sources
351// =======================================================================
352void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
353{
354 myLightSourceState.Set (theLights);
355 myLightSourceState.Update();
356}
357
358// =======================================================================
359// function : SetProjectionState
360// purpose : Sets new state of OCCT projection transform
361// =======================================================================
b5ac8292 362void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3* theProjectionMatrix)
30f0ad28 363{
364 myProjectionState.Set (theProjectionMatrix);
365 myProjectionState.Update();
366}
367
368// =======================================================================
369// function : SetModelWorldState
370// purpose : Sets new state of OCCT model-world transform
371// =======================================================================
b5ac8292 372void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
30f0ad28 373{
374 myModelWorldState.Set (theModelWorldMatrix);
375 myModelWorldState.Update();
376}
377
378// =======================================================================
379// function : SetWorldViewState
380// purpose : Sets new state of OCCT world-view transform
381// =======================================================================
b5ac8292 382void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
30f0ad28 383{
384 myWorldViewState.Set (theWorldViewMatrix);
385 myWorldViewState.Update();
386}
387
388// =======================================================================
389// function : RevertProjectionStateTo
390// purpose : Reverts state of OCCT projection transform
391// =======================================================================
b5ac8292 392void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3* theProjectionMatrix)
30f0ad28 393{
394 myProjectionState.Set (theProjectionMatrix);
395 myProjectionState.Revert();
396}
397
398// =======================================================================
399// function : RevertModelWorldStateTo
400// purpose : Reverts state of OCCT model-world transform
401// =======================================================================
b5ac8292 402void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
30f0ad28 403{
404 myModelWorldState.Set (theModelWorldMatrix);
405 myModelWorldState.Revert();
406}
407
408// =======================================================================
409// function : RevertWorldViewStateTo
410// purpose : Reverts state of OCCT world-view transform
411// =======================================================================
b5ac8292 412void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
30f0ad28 413{
414 myWorldViewState.Set (theWorldViewMatrix);
415 myWorldViewState.Revert();
416}
417
418// =======================================================================
419// function : LightSourceState
420// purpose : Returns current state of OCCT light sources
421// =======================================================================
422const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
423{
424 return myLightSourceState;
425}
426
427// =======================================================================
428// function : ProjectionState
429// purpose : Returns current state of OCCT projection transform
430// =======================================================================
431const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
432{
433 return myProjectionState;
434}
435
436// =======================================================================
437// function : ModelWorldState
438// purpose : Returns current state of OCCT model-world transform
439// =======================================================================
440const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
441{
442 return myModelWorldState;
443}
444
445// =======================================================================
446// function : WorldViewState
447// purpose : Returns current state of OCCT world-view transform
448// =======================================================================
449const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
450{
451 return myWorldViewState;
452}
453
4fe9ad57 454//! Packed properties of light source
455class OpenGl_ShaderLightParameters
456{
457public:
458
459 OpenGl_Vec4 Color;
460 OpenGl_Vec4 Position;
461 OpenGl_Vec4 Direction;
462 OpenGl_Vec4 Parameters;
463
464 //! Returns packed (serialized) representation of light source properties
0adbd30f 465 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
01eaf654 466 static Standard_Integer NbOfVec4() { return 4; }
4fe9ad57 467
468};
469
470//! Packed light source type information
471class OpenGl_ShaderLightType
472{
473public:
474
475 Standard_Integer Type;
476 Standard_Integer IsHeadlight;
477
478 //! Returns packed (serialized) representation of light source type
0adbd30f 479 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
01eaf654 480 static Standard_Integer NbOfVec2i() { return 1; }
4fe9ad57 481
482};
483
30f0ad28 484// =======================================================================
485// function : PushLightSourceState
486// purpose : Pushes state of OCCT light sources to the program
487// =======================================================================
488void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
489{
12381341 490 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
491 || !theProgram->IsValid())
30f0ad28 492 {
493 return;
494 }
30f0ad28 495
01eaf654 496 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
497 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
498 {
499 aLightTypeArray[aLightIt].Type = -1;
500 }
501
12381341 502 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
503 if (aLightsDefNb < 1)
504 {
30f0ad28 505 theProgram->SetUniform (myContext,
12381341 506 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
507 0);
30f0ad28 508 theProgram->SetUniform (myContext,
12381341 509 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
510 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
01eaf654 511 theProgram->SetUniform (myContext,
512 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
513 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
514 aLightTypeArray[0].Packed());
12381341 515 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
0c4033b4 516 delete[] aLightTypeArray;
12381341 517 return;
518 }
30f0ad28 519
4fe9ad57 520 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
30f0ad28 521
12381341 522 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
523 Standard_Integer aLightsNb = 0;
524 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
525 {
526 const OpenGl_Light& aLight = anIter.Value();
527 if (aLight.Type == Visual3d_TOLS_AMBIENT)
30f0ad28 528 {
12381341 529 anAmbient += aLight.Color;
530 continue;
531 }
532 else if (aLightsNb >= OpenGLMaxLights)
533 {
534 continue;
535 }
30f0ad28 536
4fe9ad57 537 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
538 aLightType.Type = aLight.Type;
539 aLightType.IsHeadlight = aLight.IsHeadlight;
30f0ad28 540
4fe9ad57 541 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
542 aLightParams.Color = aLight.Color;
543 aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
544 ? -aLight.Direction
545 : aLight.Position;
12381341 546 if (aLight.Type == Visual3d_TOLS_SPOT)
547 {
4fe9ad57 548 aLightParams.Direction = aLight.Direction;
30f0ad28 549 }
4fe9ad57 550 aLightParams.Parameters = aLight.Params;
12381341 551 ++aLightsNb;
552 }
30f0ad28 553
12381341 554 theProgram->SetUniform (myContext,
555 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
556 aLightsNb);
557 theProgram->SetUniform (myContext,
558 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
559 anAmbient);
01eaf654 560 theProgram->SetUniform (myContext,
561 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
562 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
563 aLightTypeArray[0].Packed());
12381341 564 if (aLightsNb > 0)
565 {
4fe9ad57 566 theProgram->SetUniform (myContext,
567 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
568 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
569 aLightParamsArray[0].Packed());
30f0ad28 570 }
4fe9ad57 571 delete[] aLightParamsArray;
572 delete[] aLightTypeArray;
30f0ad28 573
574 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
575}
576
577// =======================================================================
578// function : PushProjectionState
579// purpose : Pushes state of OCCT projection transform to the program
580// =======================================================================
581void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
582{
583 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
584 {
585 return;
586 }
587
588 theProgram->SetUniform (myContext,
589 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
590 myProjectionState.ProjectionMatrix());
591
592 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
593 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
594 {
595 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
596 }
597
598 theProgram->SetUniform (myContext,
599 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
600 myProjectionState.ProjectionMatrix(), true);
601
602 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
603 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
604 {
605 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
606 }
607
608 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
609}
610
611// =======================================================================
612// function : PushModelWorldState
613// purpose : Pushes state of OCCT model-world transform to the program
614// =======================================================================
615void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
616{
617 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
618 {
619 return;
620 }
621
622 theProgram->SetUniform (myContext,
623 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
624 myModelWorldState.ModelWorldMatrix());
625
626 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
627 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
628 {
629 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
630 }
631
632 theProgram->SetUniform (myContext,
633 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
634 myModelWorldState.ModelWorldMatrix(), true);
635
636 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
637 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
638 {
639 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
640 }
641
642 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
643}
644
645// =======================================================================
646// function : PushWorldViewState
647// purpose : Pushes state of OCCT world-view transform to the program
648// =======================================================================
649void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
650{
651 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
652 {
653 return;
654 }
655
656 theProgram->SetUniform (myContext,
657 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
658 myWorldViewState.WorldViewMatrix());
659
660 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
661 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
662 {
663 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
664 }
665
666 theProgram->SetUniform (myContext,
667 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
668 myWorldViewState.WorldViewMatrix(), true);
669
670 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
671 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
672 {
673 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
674 }
675
676 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
677}
678
679// =======================================================================
680// function : UpdateClippingState
681// purpose : Updates state of OCCT clipping planes
682// =======================================================================
683void OpenGl_ShaderManager::UpdateClippingState()
684{
685 myClippingState.Update();
686}
687
688// =======================================================================
689// function : RevertClippingState
690// purpose : Reverts state of OCCT clipping planes
691// =======================================================================
692void OpenGl_ShaderManager::RevertClippingState()
693{
694 myClippingState.Revert();
695}
696
697// =======================================================================
698// function : PushClippingState
699// purpose : Pushes state of OCCT clipping planes to the program
700// =======================================================================
701void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
702{
703 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
704 {
705 return;
706 }
707
12381341 708 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
709 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
710 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
711 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
712 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
713 {
714 return;
715 }
716
5495fa7e 717 GLint aPlanesNb = 0;
51b10cd4 718 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 719 anIter.More(); anIter.Next())
30f0ad28 720 {
721 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
722 if (!myContext->Clipping().IsEnabled (aPlane))
723 {
724 continue;
725 }
726
12381341 727 ++aPlanesNb;
728 }
729 if (aPlanesNb < 1)
730 {
731 return;
732 }
733
5495fa7e 734 const Standard_Size MAX_CLIP_PLANES = 8;
735 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
736 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
12381341 737 GLuint aPlaneId = 0;
51b10cd4 738 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 739 anIter.More(); anIter.Next())
740 {
741 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
742 if (!myContext->Clipping().IsEnabled (aPlane))
30f0ad28 743 {
12381341 744 continue;
30f0ad28 745 }
746
12381341 747 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
748 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
749 (float) anEquation.y(),
750 (float) anEquation.z(),
751 (float) anEquation.w());
752 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
753 ++aPlaneId;
30f0ad28 754 }
5495fa7e 755
756 theProgram->SetUniform (myContext,
757 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
758 aPlanesNb);
759 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
760 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
4fe9ad57 761
12381341 762 delete[] anEquations;
763 delete[] aSpaces;
30f0ad28 764}
765
766// =======================================================================
767// function : UpdateMaterialStateTo
768// purpose : Updates state of OCCT material for specified program
769// =======================================================================
770void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
771 const OpenGl_Element* theAspect)
772{
773 if (myMaterialStates.IsBound (theProgram))
774 {
595a42a4 775 OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
776 aState.Set (theAspect);
777 aState.Update();
30f0ad28 778 }
779 else
780 {
595a42a4 781 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
782 myMaterialStates.ChangeFind (theProgram).Update();
30f0ad28 783 }
30f0ad28 784}
785
786// =======================================================================
787// function : ResetMaterialStates
788// purpose : Resets state of OCCT material for all programs
789// =======================================================================
790void OpenGl_ShaderManager::ResetMaterialStates()
791{
792 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
793 {
794 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
795 }
796}
797
798// =======================================================================
799// function : MaterialState
800// purpose : Returns state of OCCT material for specified program
801// =======================================================================
802const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
803{
804 if (!myMaterialStates.IsBound (theProgram))
805 return NULL;
806
807 return &myMaterialStates.Find (theProgram);
808}
809
810namespace
811{
812
813static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
814
815// =======================================================================
816// function : PushAspectFace
817// purpose :
818// =======================================================================
819static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
820 const Handle(OpenGl_ShaderProgram)& theProgram,
821 const OpenGl_AspectFace* theAspect)
822{
823 theProgram->SetUniform (theCtx,
824 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
825 theAspect->DoTextureMap());
30f0ad28 826 theProgram->SetUniform (theCtx,
827 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
828 0 /* GL_TEXTURE0 */);
30f0ad28 829 theProgram->SetUniform (theCtx,
830 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
831 theAspect->DistinguishingMode());
832
0adbd30f 833 OpenGl_Material aParams;
12381341 834 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
30f0ad28 835 {
12381341 836 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
837 ? OpenGl_OCCT_FRONT_MATERIAL
838 : OpenGl_OCCT_BACK_MATERIAL);
839 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
30f0ad28 840 {
12381341 841 continue;
30f0ad28 842 }
30f0ad28 843
0adbd30f 844 aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
845 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
846 aParams.Packed());
30f0ad28 847 }
848}
849
850// =======================================================================
851// function : PushAspectLine
852// purpose :
853// =======================================================================
854static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
855 const Handle(OpenGl_ShaderProgram)& theProgram,
856 const OpenGl_AspectLine* theAspect)
857{
858 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
859 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
860
861 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
862 theAspect->Color().rgb[1],
863 theAspect->Color().rgb[2],
864 theAspect->Color().rgb[3]);
12381341 865 OpenGl_Vec4 aParams[5];
866 aParams[0] = THE_COLOR_BLACK_VEC4;
867 aParams[1] = THE_COLOR_BLACK_VEC4;
868 aParams[2] = aDiffuse;
869 aParams[3] = THE_COLOR_BLACK_VEC4;
870 aParams[4].x() = 0.0f; // shininess
871 aParams[4].y() = 0.0f; // transparency
4fe9ad57 872 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
873 5, aParams);
30f0ad28 874}
875
876// =======================================================================
877// function : PushAspectText
878// purpose :
879// =======================================================================
880static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
881 const Handle(OpenGl_ShaderProgram)& theProgram,
882 const OpenGl_AspectText* theAspect)
883{
884 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
885 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
886 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
887
888 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
889 theAspect->Color().rgb[1],
890 theAspect->Color().rgb[2],
891 theAspect->Color().rgb[3]);
892 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
893 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
894 {
895 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
896 theAspect->SubtitleColor().rgb[1],
897 theAspect->SubtitleColor().rgb[2],
898 theAspect->SubtitleColor().rgb[3]);
899 }
900
12381341 901 OpenGl_Vec4 aParams[5];
902 aParams[0] = THE_COLOR_BLACK_VEC4;
903 aParams[1] = THE_COLOR_BLACK_VEC4;
904 aParams[2] = aDiffuse;
905 aParams[3] = THE_COLOR_BLACK_VEC4;
906 aParams[4].x() = 0.0f; // shininess
907 aParams[4].y() = 0.0f; // transparency
4fe9ad57 908 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
909 5, aParams);
30f0ad28 910}
911
912// =======================================================================
913// function : PushAspectMarker
914// purpose :
915// =======================================================================
916static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
917 const Handle(OpenGl_ShaderProgram)& theProgram,
918 const OpenGl_AspectMarker* theAspect)
919{
920 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
921 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
922 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
923
924 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
925 theAspect->Color().rgb[1],
926 theAspect->Color().rgb[2],
927 theAspect->Color().rgb[3]);
12381341 928 OpenGl_Vec4 aParams[5];
929 aParams[0] = THE_COLOR_BLACK_VEC4;
930 aParams[1] = THE_COLOR_BLACK_VEC4;
931 aParams[2] = aDiffuse;
932 aParams[3] = THE_COLOR_BLACK_VEC4;
933 aParams[4].x() = 0.0f; // shininess
934 aParams[4].y() = 0.0f; // transparency
4fe9ad57 935 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
936 5, aParams);
30f0ad28 937}
938
939}; // nameless namespace
940
941// =======================================================================
942// function : PushMaterialState
943// purpose : Pushes current state of OCCT material to the program
944// =======================================================================
945void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
946{
947 if (!myMaterialStates.IsBound (theProgram))
948 {
949 return;
950 }
951
952 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
953 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
954 {
955 return;
956 }
957
958 if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
959 {
960 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
961 }
962 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
963 {
964 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
965 }
966 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
967 {
968 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
969 }
970 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
971 {
972 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
973 }
974
975 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
976}
977
978// =======================================================================
979// function : PushWorldViewState
980// purpose : Pushes state of OCCT graphics parameters to the program
981// =======================================================================
982void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
983{
984 PushClippingState (theProgram);
985 PushMaterialState (theProgram);
986 PushWorldViewState (theProgram);
987 PushModelWorldState (theProgram);
988 PushProjectionState (theProgram);
989 PushLightSourceState (theProgram);
12381341 990}
8625ef7e 991
992// =======================================================================
993// function : prepareStdProgramFont
994// purpose :
995// =======================================================================
996Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
997{
998 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
999 TCollection_AsciiString aSrcVert =
1000 EOL"void main()"
1001 EOL"{"
1002 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1003 EOL"}";
1004
1005 TCollection_AsciiString aSrcFrag =
1006 EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }"
1007 EOL"void main()"
1008 EOL"{"
1009 EOL" vec4 aColor = occColor;"
1010 EOL" aColor.a *= getAlpha();"
1011 EOL" if (aColor.a <= 0.285) discard;"
1012 EOL" gl_FragColor = aColor;"
1013 EOL"}";
1014
1015 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1016 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1017 TCollection_AsciiString aKey;
1018 if (!Create (aProgramSrc, aKey, myFontProgram))
1019 {
1020 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1021 return Standard_False;
1022 }
1023 return Standard_True;
1024}
1025
1026// =======================================================================
1027// function : prepareStdProgramFlat
1028// purpose :
1029// =======================================================================
1030Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1031 const Standard_Integer theBits)
1032{
1033 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1034 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1035 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1036 TCollection_AsciiString aSrcFragMainGetColor = EOL" gl_FragColor = getColor();";
1037 if ((theBits & OpenGl_PO_Point) != 0)
1038 {
1039 #if defined(GL_ES_VERSION_2_0)
1040 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1041 #endif
1042 if ((theBits & OpenGl_PO_TextureA) != 0)
1043 {
1044 aSrcFragGetColor =
1045 EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }"
1046 EOL"vec4 getColor(void)"
1047 EOL"{"
1048 EOL" vec4 aColor = occColor;"
1049 EOL" aColor.a *= getAlpha();"
1050 EOL" return aColor;"
1051 EOL"}";
1052
1053 aSrcFragMainGetColor =
1054 EOL" vec4 aColor = getColor();"
1055 EOL" if (aColor.a <= 0.1) discard;"
1056 EOL" gl_FragColor = aColor;";
1057 }
1058 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1059 {
1060 aSrcFragGetColor =
1061 EOL"vec4 getColor(void) { return texture2D(occActiveSampler, gl_PointCoord); }";
1062 aSrcFragMainGetColor =
1063 EOL" vec4 aColor = getColor();"
1064 EOL" if (aColor.a <= 0.1) discard;"
1065 EOL" gl_FragColor = aColor;";
1066 }
1067 }
1068 if ((theBits & OpenGl_PO_VertColor) != 0)
1069 {
1070 aSrcVertExtraOut += EOL"varying vec4 VertColor;";
1071 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1072 aSrcFragExtraOut += EOL"varying vec4 VertColor;";
1073 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1074 }
1075 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1076 {
1077 const char THE_POS_VARY[] =
1078 EOL"varying vec4 PositionWorld;"
1079 EOL"varying vec4 Position;";
1080
1081 aSrcVertExtraOut += THE_POS_VARY;
1082 aSrcFragExtraOut += THE_POS_VARY;
1083 aSrcVertExtraMain +=
1084 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1085 EOL" Position = occWorldViewMatrix * PositionWorld;";
1086 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1087 }
1088
1089 aSrcVert =
1090 aSrcVertExtraOut
1091 + EOL"void main()"
1092 EOL"{"
1093 + aSrcVertExtraMain
1094 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1095 EOL"}";
1096
1097 aSrcFrag =
1098 aSrcFragExtraOut
1099 + aSrcFragGetColor
1100 + EOL"void main()"
1101 EOL"{"
1102 + aSrcFragExtraMain
1103 + aSrcFragMainGetColor
1104 + EOL"}";
1105
1106 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1107 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1108
1109 TCollection_AsciiString aKey;
1110 if (!Create (aProgramSrc, aKey, theProgram))
1111 {
1112 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1113 return Standard_False;
1114 }
1115 return Standard_True;
1116}
1117
1118// =======================================================================
1119// function : prepareStdProgramGouraud
1120// purpose :
1121// =======================================================================
1122Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1123 const Standard_Integer theBits)
1124{
1125 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1126 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1127 if ((theBits & OpenGl_PO_Point) != 0)
1128 {
1129 #if defined(GL_ES_VERSION_2_0)
1130 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1131 #endif
1132 }
1133 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1134 {
1135 const char THE_POS_VARY[] =
1136 EOL"varying vec4 PositionWorld;"
1137 EOL"varying vec4 Position;";
1138
1139 aSrcVertExtraOut += THE_POS_VARY;
1140 aSrcFragExtraOut += THE_POS_VARY;
1141 aSrcVertExtraMain +=
1142 EOL" PositionWorld = aPositionWorld;"
1143 EOL" Position = aPosition;";
1144 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1145 }
1146
1147 aSrcVert = TCollection_AsciiString()
1148 + THE_FUNC_transformNormal
1149 + EOL
1150 + THE_FUNC_lightDef
1151 + THE_FUNC_pointLight
1152 + THE_FUNC_spotLight
1153 + THE_FUNC_directionalLight
1154 + EOL
1155 + THE_FUNC_computeLighting
1156 + EOL
1157 EOL"varying vec4 FrontColor;"
1158 EOL"varying vec4 BackColor;"
1159 EOL
1160 + aSrcVertExtraOut
1161 + EOL"void main()"
1162 EOL"{"
1163 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1164 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1165 EOL" vec3 aNormal = transformNormal (occNormal);"
1166 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1167 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1168 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1169 + aSrcVertExtraMain
1170 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1171 EOL"}";
1172
1173 aSrcFrag = TCollection_AsciiString()
1174 + EOL"varying vec4 FrontColor;"
1175 EOL"varying vec4 BackColor;"
1176 + aSrcFragExtraOut
1177 + EOL"void main()"
1178 EOL"{"
1179 + aSrcFragExtraMain
1180 + EOL" gl_FragColor = gl_FrontFacing ? FrontColor : BackColor;"
1181 EOL"}";
1182
1183 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1184 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1185 TCollection_AsciiString aKey;
1186 if (!Create (aProgramSrc, aKey, theProgram))
1187 {
1188 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1189 return Standard_False;
1190 }
1191 return Standard_True;
1192}
1193
1194// =======================================================================
1195// function : prepareStdProgramPhong
1196// purpose :
1197// =======================================================================
1198Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1199 const Standard_Integer theBits)
1200{
1201 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1202 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraMain;
1203 if ((theBits & OpenGl_PO_Point) != 0)
1204 {
1205 #if defined(GL_ES_VERSION_2_0)
1206 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1207 #endif
1208 }
1209 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1210 {
1211 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1212 }
1213
1214 aSrcVert = TCollection_AsciiString()
1215 + THE_FUNC_transformNormal
1216 + EOL
1217 EOL"varying vec4 PositionWorld;"
1218 EOL"varying vec4 Position;"
1219 EOL"varying vec3 Normal;"
1220 EOL"varying vec3 View;"
1221 EOL
1222 + aSrcVertExtraOut
1223 + EOL"void main()"
1224 EOL"{"
1225 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1226 EOL" Position = occWorldViewMatrix * PositionWorld;"
1227 EOL" Normal = transformNormal (occNormal);"
1228 EOL" View = vec3 (0.0, 0.0, 1.0);"
1229 + aSrcVertExtraMain
1230 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1231 EOL"}";
1232
1233 aSrcFrag = TCollection_AsciiString()
1234 + EOL"varying vec4 PositionWorld;"
1235 EOL"varying vec4 Position;"
1236 EOL"varying vec3 Normal;"
1237 EOL"varying vec3 View;"
1238 + EOL
1239 + THE_FUNC_lightDef
1240 + THE_FUNC_pointLight
1241 + THE_FUNC_spotLight
1242 + THE_FUNC_directionalLight
1243 + EOL
1244 + THE_FUNC_computeLighting
1245 + EOL
1246 EOL"void main()"
1247 EOL"{"
1248 + aSrcFragExtraMain
1249 + EOL" gl_FragColor = computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing);"
1250 EOL"}";
1251
1252 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1253 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1254 TCollection_AsciiString aKey;
1255 if (!Create (aProgramSrc, aKey, theProgram))
1256 {
1257 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1258 return Standard_False;
1259 }
1260 return Standard_True;
1261}
1262
1263// =======================================================================
1264// function : bindProgramWithState
1265// purpose :
1266// =======================================================================
1267Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1268 const OpenGl_Element* theAspect)
1269{
1270 if (!myContext->BindProgram (theProgram))
1271 {
1272 return Standard_False;
1273 }
1274 theProgram->ApplyVariables (myContext);
1275
1276 const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1277 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1278 {
1279 UpdateMaterialStateTo (theProgram, theAspect);
1280 }
1281
1282 PushState (theProgram);
1283 return Standard_True;
1284}