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