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