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