0027110: Regression: Draw command "parameters" can not compute parameter on the line.
[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
e135a155 18#include <Graphic3d_TextureParams.hxx>
30f0ad28 19#include <OpenGl_AspectFace.hxx>
20#include <OpenGl_AspectLine.hxx>
21#include <OpenGl_AspectMarker.hxx>
22#include <OpenGl_AspectText.hxx>
23#include <OpenGl_Clipping.hxx>
24#include <OpenGl_Context.hxx>
25#include <OpenGl_ShaderManager.hxx>
26#include <OpenGl_ShaderProgram.hxx>
0adbd30f 27#include <OpenGl_Workspace.hxx>
30f0ad28 28
ac116c22 29#include <TCollection_ExtendedString.hxx>
30
256f9ac0 31
ec357c5c 32
30f0ad28 33
92efcf78 34IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
35
8625ef7e 36namespace
37{
38
39#define EOL "\n"
40
79f4f036 41//! Definition of TexCoord varying.
4e1523ef 42const char THE_VARY_TexCoord_OUT[] =
79f4f036 43 EOL"THE_SHADER_OUT vec4 TexCoord;";
4e1523ef 44const char THE_VARY_TexCoord_IN[] =
79f4f036 45 EOL"THE_SHADER_IN vec4 TexCoord;";
46//! Compute TexCoord value in Vertex Shader
47const char THE_VARY_TexCoord_Trsf[] =
48 EOL" float aRotSin = occTextureTrsf_RotationSin();"
49 EOL" float aRotCos = occTextureTrsf_RotationCos();"
50 EOL" vec2 aTex2 = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
51 EOL" vec2 aCopy = aTex2;"
52 EOL" aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
53 EOL" aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
54 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
6c6aadb1 55
8625ef7e 56//! Auxiliary function to transform normal
57const char THE_FUNC_transformNormal[] =
58 EOL"vec3 transformNormal (in vec3 theNormal)"
59 EOL"{"
60 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
61 EOL" * occModelWorldMatrixInverseTranspose"
62 EOL" * vec4 (theNormal, 0.0);"
63 EOL" return normalize (aResult.xyz);"
64 EOL"}";
65
66//! Global shader variable for color definition with lighting enabled.
67const char THE_FUNC_lightDef[] =
68 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
69 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
70 EOL"vec3 Specular;"; //!< Specular contribution of light sources
71
8625ef7e 72//! Function computes contribution of isotropic point light source
73const char THE_FUNC_pointLight[] =
74 EOL"void pointLight (in int theId,"
75 EOL" in vec3 theNormal,"
76 EOL" in vec3 theView,"
77 EOL" in vec3 thePoint,"
78 EOL" in bool theIsFront)"
79 EOL"{"
80 EOL" vec3 aLight = occLight_Position (theId).xyz;"
81 EOL" if (occLight_IsHeadlight (theId) == 0)"
82 EOL" {"
83 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
84 EOL" }"
85 EOL" aLight -= thePoint;"
86 EOL
87 EOL" float aDist = length (aLight);"
88 EOL" aLight = aLight * (1.0 / aDist);"
89 EOL
90 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
91 EOL" + occLight_LinearAttenuation (theId) * aDist);"
92 EOL
93 EOL" vec3 aHalf = normalize (aLight + theView);"
94 EOL
95 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
96 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
97 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
98 EOL
99 EOL" float aSpecl = 0.0;"
100 EOL" if (aNdotL > 0.0)"
101 EOL" {"
102 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
103 EOL" }"
104 EOL
105 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
106 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
107 EOL"}";
108
109//! Function computes contribution of spotlight source
110const char THE_FUNC_spotLight[] =
111 EOL"void spotLight (in int theId,"
112 EOL" in vec3 theNormal,"
113 EOL" in vec3 theView,"
114 EOL" in vec3 thePoint,"
115 EOL" in bool theIsFront)"
116 EOL"{"
117 EOL" vec3 aLight = occLight_Position (theId).xyz;"
118 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
119 EOL" if (occLight_IsHeadlight (theId) == 0)"
120 EOL" {"
121 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
122 EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
123 EOL" }"
124 EOL" aLight -= thePoint;"
125 EOL
126 EOL" float aDist = length (aLight);"
127 EOL" aLight = aLight * (1.0 / aDist);"
128 EOL
129 EOL" aSpotDir = normalize (aSpotDir);"
130 // light cone
131 EOL" float aCosA = dot (aSpotDir, -aLight);"
132 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
133 EOL" {"
134 EOL" return;"
135 EOL" }"
136 EOL
137 EOL" float anExponent = occLight_SpotExponent (theId);"
138 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
139 EOL" + occLight_LinearAttenuation (theId) * aDist);"
140 EOL" if (anExponent > 0.0)"
141 EOL" {"
142 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
143 EOL" }"
144 EOL
145 EOL" vec3 aHalf = normalize (aLight + theView);"
146 EOL
147 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
148 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
149 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
150 EOL
151 EOL" float aSpecl = 0.0;"
152 EOL" if (aNdotL > 0.0)"
153 EOL" {"
154 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
155 EOL" }"
156 EOL
157 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
158 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
159 EOL"}";
160
161//! Function computes contribution of directional light source
162const char THE_FUNC_directionalLight[] =
163 EOL"void directionalLight (in int theId,"
164 EOL" in vec3 theNormal,"
165 EOL" in vec3 theView,"
166 EOL" in bool theIsFront)"
167 EOL"{"
168 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
169 EOL" if (occLight_IsHeadlight (theId) == 0)"
170 EOL" {"
171 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
172 EOL" }"
173 EOL
174 EOL" vec3 aHalf = normalize (aLight + theView);"
175 EOL
176 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
177 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
178 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
179 EOL
180 EOL" float aSpecl = 0.0;"
181 EOL" if (aNdotL > 0.0)"
182 EOL" {"
183 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
184 EOL" }"
185 EOL
186 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
187 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
188 EOL"}";
189
190//! Process clipping planes in Fragment Shader.
191//! Should be added at the beginning of the main() function.
192const char THE_FRAG_CLIP_PLANES[] =
193 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
194 EOL" {"
195 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
196 EOL" int aClipSpace = occClipPlaneSpaces[aPlaneIter];"
197 EOL" if (aClipSpace == OccEquationCoords_World)"
198 EOL" {"
199 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)"
200 EOL" {"
201 EOL" discard;"
202 EOL" }"
203 EOL" }"
204 EOL" else if (aClipSpace == OccEquationCoords_View)"
205 EOL" {"
206 EOL" if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)"
207 EOL" {"
208 EOL" discard;"
209 EOL" }"
210 EOL" }"
211 EOL" }";
212
213}
214
30f0ad28 215// =======================================================================
216// function : OpenGl_ShaderManager
217// purpose : Creates new empty shader manager
218// =======================================================================
219OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
c357e426 220: myShadingModel (Graphic3d_TOSM_VERTEX),
8625ef7e 221 myContext (theContext),
e6804ff7 222 myLastView (NULL)
30f0ad28 223{
256f9ac0 224 //
30f0ad28 225}
226
227// =======================================================================
228// function : ~OpenGl_ShaderManager
229// purpose : Releases resources of shader manager
230// =======================================================================
231OpenGl_ShaderManager::~OpenGl_ShaderManager()
232{
233 myProgramList.Clear();
234}
235
05e2200b 236// =======================================================================
237// function : clear
238// purpose :
239// =======================================================================
240void OpenGl_ShaderManager::clear()
241{
242 myProgramList.Clear();
243 myLightPrograms.Nullify();
244 myFlatPrograms = OpenGl_SetOfShaderPrograms();
245 myMapOfLightPrograms.Clear();
246 myFontProgram.Nullify();
b86bb3df 247 myBlitProgram.Nullify();
f978241f 248 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
249 {
250 myStereoPrograms[aModeIter].Nullify();
251 }
05e2200b 252 switchLightPrograms();
253}
254
30f0ad28 255// =======================================================================
256// function : Create
257// purpose : Creates new shader program
258// =======================================================================
8625ef7e 259Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
260 TCollection_AsciiString& theShareKey,
261 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 262{
392ac980 263 theProgram.Nullify();
264 if (theProxy.IsNull())
30f0ad28 265 {
8625ef7e 266 return Standard_False;
30f0ad28 267 }
392ac980 268
269 theShareKey = theProxy->GetId();
270 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
271 {
05dd08ce 272 if (theProgram->Share())
273 {
274 myProgramList.Append (theProgram);
275 }
8625ef7e 276 return Standard_True;
392ac980 277 }
278
279 theProgram = new OpenGl_ShaderProgram (theProxy);
280 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
30f0ad28 281 {
392ac980 282 theProgram->Release (myContext);
283 theShareKey.Clear();
284 theProgram.Nullify();
8625ef7e 285 return Standard_False;
30f0ad28 286 }
30f0ad28 287
392ac980 288 myProgramList.Append (theProgram);
289 myContext->ShareResource (theShareKey, theProgram);
8625ef7e 290 return Standard_True;
30f0ad28 291}
292
293// =======================================================================
294// function : Unregister
295// purpose : Removes specified shader program from the manager
296// =======================================================================
392ac980 297void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
298 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 299{
300 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
301 {
302 if (anIt.Value() == theProgram)
303 {
392ac980 304 if (!theProgram->UnShare())
305 {
306 theShareKey.Clear();
307 theProgram.Nullify();
308 return;
309 }
310
30f0ad28 311 myProgramList.Remove (anIt);
392ac980 312 myMaterialStates.UnBind (theProgram);
30f0ad28 313 break;
314 }
315 }
316
317 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
318 if (anID.IsEmpty())
319 {
320 myContext->DelayedRelease (theProgram);
321 theProgram.Nullify();
322 }
323 else
324 {
325 theProgram.Nullify();
05dd08ce 326 myContext->ReleaseResource (anID, Standard_True);
30f0ad28 327 }
328}
329
330// =======================================================================
331// function : ShaderPrograms
332// purpose : Returns list of registered shader programs
333// =======================================================================
334const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
335{
336 return myProgramList;
337}
338
339// =======================================================================
340// function : Empty
341// purpose : Returns true if no program objects are attached
342// =======================================================================
343Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
344{
345 return myProgramList.IsEmpty();
346}
347
256f9ac0 348// =======================================================================
349// function : switchLightPrograms
350// purpose :
351// =======================================================================
352void OpenGl_ShaderManager::switchLightPrograms()
353{
c357e426 354 TCollection_AsciiString aKey (myShadingModel == Graphic3d_TOSM_FRAGMENT ? "p_" : "g_");
256f9ac0 355 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
356 if (aLights != NULL)
357 {
358 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
359 {
360 switch (aLightIter.Value().Type)
361 {
c357e426 362 case Graphic3d_TOLS_AMBIENT:
256f9ac0 363 break; // skip ambient
c357e426 364 case Graphic3d_TOLS_DIRECTIONAL:
256f9ac0 365 aKey += "d";
366 break;
c357e426 367 case Graphic3d_TOLS_POSITIONAL:
256f9ac0 368 aKey += "p";
369 break;
c357e426 370 case Graphic3d_TOLS_SPOT:
256f9ac0 371 aKey += "s";
372 break;
373 }
374 }
375 }
376
377 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
378 {
379 myLightPrograms = new OpenGl_SetOfShaderPrograms();
380 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
381 }
382}
383
30f0ad28 384// =======================================================================
385// function : UpdateLightSourceStateTo
386// purpose : Updates state of OCCT light sources
387// =======================================================================
388void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
389{
390 myLightSourceState.Set (theLights);
391 myLightSourceState.Update();
256f9ac0 392 switchLightPrograms();
393}
394
395// =======================================================================
396// function : SetShadingModel
397// purpose :
398// =======================================================================
c357e426 399void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
256f9ac0 400{
401 myShadingModel = theModel;
402 switchLightPrograms();
30f0ad28 403}
404
405// =======================================================================
406// function : SetProjectionState
407// purpose : Sets new state of OCCT projection transform
408// =======================================================================
c827ea3a 409void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
30f0ad28 410{
411 myProjectionState.Set (theProjectionMatrix);
412 myProjectionState.Update();
413}
414
415// =======================================================================
416// function : SetModelWorldState
417// purpose : Sets new state of OCCT model-world transform
418// =======================================================================
c827ea3a 419void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
30f0ad28 420{
421 myModelWorldState.Set (theModelWorldMatrix);
422 myModelWorldState.Update();
423}
424
425// =======================================================================
426// function : SetWorldViewState
427// purpose : Sets new state of OCCT world-view transform
428// =======================================================================
c827ea3a 429void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
30f0ad28 430{
431 myWorldViewState.Set (theWorldViewMatrix);
432 myWorldViewState.Update();
433}
434
30f0ad28 435// =======================================================================
436// function : LightSourceState
437// purpose : Returns current state of OCCT light sources
438// =======================================================================
439const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
440{
441 return myLightSourceState;
442}
443
444// =======================================================================
445// function : ProjectionState
446// purpose : Returns current state of OCCT projection transform
447// =======================================================================
448const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
449{
450 return myProjectionState;
451}
452
453// =======================================================================
454// function : ModelWorldState
455// purpose : Returns current state of OCCT model-world transform
456// =======================================================================
457const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
458{
459 return myModelWorldState;
460}
461
462// =======================================================================
463// function : WorldViewState
464// purpose : Returns current state of OCCT world-view transform
465// =======================================================================
466const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
467{
468 return myWorldViewState;
469}
470
4fe9ad57 471//! Packed properties of light source
472class OpenGl_ShaderLightParameters
473{
474public:
475
476 OpenGl_Vec4 Color;
477 OpenGl_Vec4 Position;
478 OpenGl_Vec4 Direction;
479 OpenGl_Vec4 Parameters;
480
481 //! Returns packed (serialized) representation of light source properties
0adbd30f 482 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
01eaf654 483 static Standard_Integer NbOfVec4() { return 4; }
4fe9ad57 484
485};
486
487//! Packed light source type information
488class OpenGl_ShaderLightType
489{
490public:
491
492 Standard_Integer Type;
493 Standard_Integer IsHeadlight;
494
495 //! Returns packed (serialized) representation of light source type
0adbd30f 496 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
01eaf654 497 static Standard_Integer NbOfVec2i() { return 1; }
4fe9ad57 498
499};
500
30f0ad28 501// =======================================================================
502// function : PushLightSourceState
503// purpose : Pushes state of OCCT light sources to the program
504// =======================================================================
505void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
506{
12381341 507 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
508 || !theProgram->IsValid())
30f0ad28 509 {
510 return;
511 }
30f0ad28 512
01eaf654 513 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
514 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
515 {
516 aLightTypeArray[aLightIt].Type = -1;
517 }
518
12381341 519 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
520 if (aLightsDefNb < 1)
521 {
30f0ad28 522 theProgram->SetUniform (myContext,
12381341 523 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
524 0);
30f0ad28 525 theProgram->SetUniform (myContext,
12381341 526 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
527 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
01eaf654 528 theProgram->SetUniform (myContext,
529 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
530 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
531 aLightTypeArray[0].Packed());
12381341 532 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
0c4033b4 533 delete[] aLightTypeArray;
12381341 534 return;
535 }
30f0ad28 536
4fe9ad57 537 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
30f0ad28 538
12381341 539 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
540 Standard_Integer aLightsNb = 0;
541 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
542 {
543 const OpenGl_Light& aLight = anIter.Value();
c357e426 544 if (aLight.Type == Graphic3d_TOLS_AMBIENT)
30f0ad28 545 {
12381341 546 anAmbient += aLight.Color;
547 continue;
548 }
549 else if (aLightsNb >= OpenGLMaxLights)
550 {
551 continue;
552 }
30f0ad28 553
4fe9ad57 554 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
555 aLightType.Type = aLight.Type;
556 aLightType.IsHeadlight = aLight.IsHeadlight;
30f0ad28 557
4fe9ad57 558 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
559 aLightParams.Color = aLight.Color;
c357e426 560 aLightParams.Position = aLight.Type == Graphic3d_TOLS_DIRECTIONAL
4fe9ad57 561 ? -aLight.Direction
562 : aLight.Position;
c357e426 563 if (aLight.Type == Graphic3d_TOLS_SPOT)
12381341 564 {
4fe9ad57 565 aLightParams.Direction = aLight.Direction;
30f0ad28 566 }
4fe9ad57 567 aLightParams.Parameters = aLight.Params;
12381341 568 ++aLightsNb;
569 }
30f0ad28 570
12381341 571 theProgram->SetUniform (myContext,
572 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
573 aLightsNb);
574 theProgram->SetUniform (myContext,
575 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
576 anAmbient);
01eaf654 577 theProgram->SetUniform (myContext,
578 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
579 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
580 aLightTypeArray[0].Packed());
12381341 581 if (aLightsNb > 0)
582 {
4fe9ad57 583 theProgram->SetUniform (myContext,
584 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
585 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
586 aLightParamsArray[0].Packed());
30f0ad28 587 }
4fe9ad57 588 delete[] aLightParamsArray;
589 delete[] aLightTypeArray;
30f0ad28 590
591 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
592}
593
594// =======================================================================
595// function : PushProjectionState
596// purpose : Pushes state of OCCT projection transform to the program
597// =======================================================================
598void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
599{
600 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
601 {
602 return;
603 }
604
605 theProgram->SetUniform (myContext,
606 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
607 myProjectionState.ProjectionMatrix());
608
609 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
610 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
611 {
612 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
613 }
614
615 theProgram->SetUniform (myContext,
616 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
617 myProjectionState.ProjectionMatrix(), true);
618
619 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
620 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
621 {
622 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
623 }
624
625 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
626}
627
628// =======================================================================
629// function : PushModelWorldState
630// purpose : Pushes state of OCCT model-world transform to the program
631// =======================================================================
632void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
633{
634 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
635 {
636 return;
637 }
638
639 theProgram->SetUniform (myContext,
640 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
641 myModelWorldState.ModelWorldMatrix());
642
643 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
644 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
645 {
646 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
647 }
648
649 theProgram->SetUniform (myContext,
650 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
651 myModelWorldState.ModelWorldMatrix(), true);
652
653 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
654 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
655 {
656 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
657 }
658
659 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
660}
661
662// =======================================================================
663// function : PushWorldViewState
664// purpose : Pushes state of OCCT world-view transform to the program
665// =======================================================================
666void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
667{
668 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
669 {
670 return;
671 }
672
673 theProgram->SetUniform (myContext,
674 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
675 myWorldViewState.WorldViewMatrix());
676
677 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
678 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
679 {
680 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
681 }
682
683 theProgram->SetUniform (myContext,
684 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
685 myWorldViewState.WorldViewMatrix(), true);
686
687 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
688 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
689 {
690 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
691 }
692
693 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
694}
695
696// =======================================================================
697// function : UpdateClippingState
698// purpose : Updates state of OCCT clipping planes
699// =======================================================================
700void OpenGl_ShaderManager::UpdateClippingState()
701{
702 myClippingState.Update();
703}
704
705// =======================================================================
706// function : RevertClippingState
707// purpose : Reverts state of OCCT clipping planes
708// =======================================================================
709void OpenGl_ShaderManager::RevertClippingState()
710{
711 myClippingState.Revert();
712}
713
714// =======================================================================
715// function : PushClippingState
716// purpose : Pushes state of OCCT clipping planes to the program
717// =======================================================================
718void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
719{
720 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
721 {
722 return;
723 }
724
12381341 725 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
726 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
727 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
728 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
729 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
730 {
731 return;
732 }
733
5495fa7e 734 GLint aPlanesNb = 0;
51b10cd4 735 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 736 anIter.More(); anIter.Next())
30f0ad28 737 {
738 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
739 if (!myContext->Clipping().IsEnabled (aPlane))
740 {
741 continue;
742 }
743
12381341 744 ++aPlanesNb;
745 }
746 if (aPlanesNb < 1)
747 {
748 return;
749 }
750
5495fa7e 751 const Standard_Size MAX_CLIP_PLANES = 8;
752 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
753 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
12381341 754 GLuint aPlaneId = 0;
51b10cd4 755 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 756 anIter.More(); anIter.Next())
757 {
758 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
759 if (!myContext->Clipping().IsEnabled (aPlane))
30f0ad28 760 {
12381341 761 continue;
30f0ad28 762 }
763
12381341 764 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
765 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
766 (float) anEquation.y(),
767 (float) anEquation.z(),
768 (float) anEquation.w());
769 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
770 ++aPlaneId;
30f0ad28 771 }
5495fa7e 772
773 theProgram->SetUniform (myContext,
774 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
775 aPlanesNb);
776 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
777 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
4fe9ad57 778
12381341 779 delete[] anEquations;
780 delete[] aSpaces;
30f0ad28 781}
782
783// =======================================================================
784// function : UpdateMaterialStateTo
785// purpose : Updates state of OCCT material for specified program
786// =======================================================================
787void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
788 const OpenGl_Element* theAspect)
789{
790 if (myMaterialStates.IsBound (theProgram))
791 {
595a42a4 792 OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
793 aState.Set (theAspect);
794 aState.Update();
30f0ad28 795 }
796 else
797 {
595a42a4 798 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
799 myMaterialStates.ChangeFind (theProgram).Update();
30f0ad28 800 }
30f0ad28 801}
802
803// =======================================================================
804// function : ResetMaterialStates
805// purpose : Resets state of OCCT material for all programs
806// =======================================================================
807void OpenGl_ShaderManager::ResetMaterialStates()
808{
809 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
810 {
811 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
812 }
813}
814
815// =======================================================================
816// function : MaterialState
817// purpose : Returns state of OCCT material for specified program
818// =======================================================================
819const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
820{
821 if (!myMaterialStates.IsBound (theProgram))
822 return NULL;
823
824 return &myMaterialStates.Find (theProgram);
825}
826
e135a155 827// =======================================================================
828// function : SurfaceDetailState
829// purpose : Returns current state of OCCT surface detail
830// =======================================================================
831const OpenGl_SurfaceDetailState& OpenGl_ShaderManager::SurfaceDetailState() const
832{
833 return mySurfaceDetailState;
834}
835
836// =======================================================================
837// function : UpdateSurfaceDetailStateTo
838// purpose : Updates state of OCCT surface detail
839// =======================================================================
c357e426 840void OpenGl_ShaderManager::UpdateSurfaceDetailStateTo (const Graphic3d_TypeOfSurfaceDetail theDetail)
e135a155 841{
842 mySurfaceDetailState.Set (theDetail);
843 mySurfaceDetailState.Update();
844}
845
30f0ad28 846namespace
847{
848
849static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
850
851// =======================================================================
852// function : PushAspectFace
853// purpose :
854// =======================================================================
855static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
856 const Handle(OpenGl_ShaderProgram)& theProgram,
857 const OpenGl_AspectFace* theAspect)
858{
859 theProgram->SetUniform (theCtx,
860 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
861 theAspect->DoTextureMap());
30f0ad28 862 theProgram->SetUniform (theCtx,
863 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
864 0 /* GL_TEXTURE0 */);
30f0ad28 865 theProgram->SetUniform (theCtx,
866 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
867 theAspect->DistinguishingMode());
868
0adbd30f 869 OpenGl_Material aParams;
12381341 870 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
30f0ad28 871 {
12381341 872 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
873 ? OpenGl_OCCT_FRONT_MATERIAL
874 : OpenGl_OCCT_BACK_MATERIAL);
875 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
30f0ad28 876 {
12381341 877 continue;
30f0ad28 878 }
30f0ad28 879
363bc51b 880 const OPENGL_SURF_PROP& aProp = anIndex == 0 || theAspect->DistinguishingMode() != TOn
881 ? theAspect->IntFront()
882 : theAspect->IntBack();
883 aParams.Init (aProp);
884 aParams.Diffuse.a() = aProp.trans;
0adbd30f 885 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
886 aParams.Packed());
30f0ad28 887 }
888}
889
890// =======================================================================
891// function : PushAspectLine
892// purpose :
893// =======================================================================
894static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
895 const Handle(OpenGl_ShaderProgram)& theProgram,
896 const OpenGl_AspectLine* theAspect)
897{
898 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
899 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
900
901 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
902 theAspect->Color().rgb[1],
903 theAspect->Color().rgb[2],
904 theAspect->Color().rgb[3]);
12381341 905 OpenGl_Vec4 aParams[5];
906 aParams[0] = THE_COLOR_BLACK_VEC4;
907 aParams[1] = THE_COLOR_BLACK_VEC4;
908 aParams[2] = aDiffuse;
909 aParams[3] = THE_COLOR_BLACK_VEC4;
910 aParams[4].x() = 0.0f; // shininess
911 aParams[4].y() = 0.0f; // transparency
4fe9ad57 912 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
913 5, aParams);
30f0ad28 914}
915
916// =======================================================================
917// function : PushAspectText
918// purpose :
919// =======================================================================
920static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
921 const Handle(OpenGl_ShaderProgram)& theProgram,
922 const OpenGl_AspectText* theAspect)
923{
924 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
925 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
926 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
927
928 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
929 theAspect->Color().rgb[1],
930 theAspect->Color().rgb[2],
931 theAspect->Color().rgb[3]);
932 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
933 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
934 {
935 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
936 theAspect->SubtitleColor().rgb[1],
937 theAspect->SubtitleColor().rgb[2],
938 theAspect->SubtitleColor().rgb[3]);
939 }
940
12381341 941 OpenGl_Vec4 aParams[5];
942 aParams[0] = THE_COLOR_BLACK_VEC4;
943 aParams[1] = THE_COLOR_BLACK_VEC4;
944 aParams[2] = aDiffuse;
945 aParams[3] = THE_COLOR_BLACK_VEC4;
946 aParams[4].x() = 0.0f; // shininess
947 aParams[4].y() = 0.0f; // transparency
4fe9ad57 948 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
949 5, aParams);
30f0ad28 950}
951
952// =======================================================================
953// function : PushAspectMarker
954// purpose :
955// =======================================================================
956static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
957 const Handle(OpenGl_ShaderProgram)& theProgram,
958 const OpenGl_AspectMarker* theAspect)
959{
960 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
961 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
962 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
963
964 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
965 theAspect->Color().rgb[1],
966 theAspect->Color().rgb[2],
967 theAspect->Color().rgb[3]);
12381341 968 OpenGl_Vec4 aParams[5];
969 aParams[0] = THE_COLOR_BLACK_VEC4;
970 aParams[1] = THE_COLOR_BLACK_VEC4;
971 aParams[2] = aDiffuse;
972 aParams[3] = THE_COLOR_BLACK_VEC4;
973 aParams[4].x() = 0.0f; // shininess
974 aParams[4].y() = 0.0f; // transparency
4fe9ad57 975 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
976 5, aParams);
30f0ad28 977}
978
a3f6f591 979} // nameless namespace
30f0ad28 980
981// =======================================================================
982// function : PushMaterialState
983// purpose : Pushes current state of OCCT material to the program
984// =======================================================================
985void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
986{
987 if (!myMaterialStates.IsBound (theProgram))
988 {
989 return;
990 }
991
992 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
993 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
994 {
995 return;
996 }
997
c7854818 998 const OpenGl_Element* anAspect = aState.Aspect();
999 if (typeid (*anAspect) == typeid (OpenGl_AspectFace))
30f0ad28 1000 {
c7854818 1001 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (anAspect));
30f0ad28 1002 }
c7854818 1003 else if (typeid (*anAspect) == typeid (OpenGl_AspectLine))
30f0ad28 1004 {
c7854818 1005 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (anAspect));
30f0ad28 1006 }
c7854818 1007 else if (typeid (*anAspect) == typeid (OpenGl_AspectText))
30f0ad28 1008 {
c7854818 1009 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (anAspect));
30f0ad28 1010 }
c7854818 1011 else if (typeid (*anAspect) == typeid (OpenGl_AspectMarker))
30f0ad28 1012 {
c7854818 1013 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (anAspect));
30f0ad28 1014 }
1015
1016 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
1017}
1018
1019// =======================================================================
e135a155 1020// function : PushState
30f0ad28 1021// purpose : Pushes state of OCCT graphics parameters to the program
1022// =======================================================================
1023void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1024{
1025 PushClippingState (theProgram);
1026 PushMaterialState (theProgram);
1027 PushWorldViewState (theProgram);
1028 PushModelWorldState (theProgram);
05e2200b 1029 PushProjectionState (theProgram);
30f0ad28 1030 PushLightSourceState (theProgram);
12381341 1031}
8625ef7e 1032
1033// =======================================================================
1034// function : prepareStdProgramFont
1035// purpose :
1036// =======================================================================
1037Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1038{
1039 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
b990e557 1040 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
79f4f036 1041 + EOL"THE_SHADER_OUT vec2 TexCoord;"
1042 EOL"void main()"
b990e557 1043 EOL"{"
1044 EOL" TexCoord = occTexCoord.st;"
1045 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1046 EOL"}";
1047
4e1523ef 1048 TCollection_AsciiString
1049 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
1050#if !defined(GL_ES_VERSION_2_0)
1051 if (myContext->core11 == NULL)
1052 {
1053 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
1054 }
1055#endif
1056
b990e557 1057 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
79f4f036 1058 + EOL"THE_SHADER_IN vec2 TexCoord;"
4e1523ef 1059 + aSrcGetAlpha
1060 + EOL"void main()"
b990e557 1061 EOL"{"
1062 EOL" vec4 aColor = occColor;"
1063 EOL" aColor.a *= getAlpha();"
1064 EOL" if (aColor.a <= 0.285) discard;"
4e1523ef 1065 EOL" occFragColor = aColor;"
b990e557 1066 EOL"}";
8625ef7e 1067
4e1523ef 1068#if !defined(GL_ES_VERSION_2_0)
1069 if (myContext->core32 != NULL)
1070 {
1071 aProgramSrc->SetHeader ("#version 150");
1072 }
1073#endif
8625ef7e 1074 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1075 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1076 TCollection_AsciiString aKey;
1077 if (!Create (aProgramSrc, aKey, myFontProgram))
1078 {
1079 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1080 return Standard_False;
1081 }
1082 return Standard_True;
1083}
1084
1085// =======================================================================
b86bb3df 1086// function : prepareStdProgramFboBlit
1087// purpose :
1088// =======================================================================
1089Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1090{
1091 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1092 TCollection_AsciiString aSrcVert =
1093 EOL"THE_SHADER_OUT vec2 TexCoord;"
1094 EOL"void main()"
1095 EOL"{"
1096 EOL" TexCoord = occVertex.zw;"
1097 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1098 EOL"}";
1099
1100 TCollection_AsciiString aSrcFrag =
1101 EOL"uniform sampler2D uColorSampler;"
1102 EOL"uniform sampler2D uDepthSampler;"
1103 EOL
1104 EOL"THE_SHADER_IN vec2 TexCoord;"
1105 EOL
1106 EOL"void main()"
1107 EOL"{"
1108 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1109 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1110 EOL"}";
1111
1112#if defined(GL_ES_VERSION_2_0)
1113 if (myContext->IsGlGreaterEqual (3, 0))
1114 {
1115 aProgramSrc->SetHeader ("#version 300 es");
1116 }
1117 else
1118 {
1119 // there is no way to draw into depth buffer
1120 aSrcFrag =
1121 EOL"uniform sampler2D uColorSampler;"
1122 EOL
1123 EOL"THE_SHADER_IN vec2 TexCoord;"
1124 EOL
1125 EOL"void main()"
1126 EOL"{"
1127 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1128 EOL"}";
1129 }
4e1523ef 1130#else
1131 if (myContext->core32 != NULL)
1132 {
1133 aProgramSrc->SetHeader ("#version 150");
1134 }
b86bb3df 1135#endif
b86bb3df 1136 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1137 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1138 TCollection_AsciiString aKey;
1139 if (!Create (aProgramSrc, aKey, myBlitProgram))
1140 {
1141 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1142 return Standard_False;
1143 }
1144
1145 myContext->BindProgram (myBlitProgram);
1146 myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
1147 myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
1148 myContext->BindProgram (NULL);
1149 return Standard_True;
1150}
1151
1152// =======================================================================
8625ef7e 1153// function : prepareStdProgramFlat
1154// purpose :
1155// =======================================================================
1156Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1157 const Standard_Integer theBits)
1158{
1159 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
e135a155 1160 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
8625ef7e 1161 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
4e1523ef 1162 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
8625ef7e 1163 if ((theBits & OpenGl_PO_Point) != 0)
1164 {
1165 #if defined(GL_ES_VERSION_2_0)
1166 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1167 #endif
1168 if ((theBits & OpenGl_PO_TextureA) != 0)
1169 {
4e1523ef 1170 TCollection_AsciiString
1171 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).a; }";
1172 #if !defined(GL_ES_VERSION_2_0)
1173 if (myContext->core11 == NULL)
1174 {
1175 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).r; }";
1176 }
15478b1b 1177 else if (myContext->IsGlGreaterEqual (2, 1))
1178 {
1179 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1180 }
4e1523ef 1181 #endif
1182
1183 aSrcFragGetColor = aSrcGetAlpha
1184 + EOL"vec4 getColor(void)"
8625ef7e 1185 EOL"{"
1186 EOL" vec4 aColor = occColor;"
1187 EOL" aColor.a *= getAlpha();"
1188 EOL" return aColor;"
1189 EOL"}";
1190
1191 aSrcFragMainGetColor =
1192 EOL" vec4 aColor = getColor();"
1193 EOL" if (aColor.a <= 0.1) discard;"
4e1523ef 1194 EOL" occFragColor = aColor;";
8625ef7e 1195 }
1196 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1197 {
1198 aSrcFragGetColor =
4e1523ef 1199 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, gl_PointCoord); }";
8625ef7e 1200 aSrcFragMainGetColor =
1201 EOL" vec4 aColor = getColor();"
1202 EOL" if (aColor.a <= 0.1) discard;"
4e1523ef 1203 EOL" occFragColor = aColor;";
15478b1b 1204 #if !defined(GL_ES_VERSION_2_0)
1205 if (myContext->core11 != NULL
1206 && myContext->IsGlGreaterEqual (2, 1))
1207 {
1208 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1209 }
1210 #endif
8625ef7e 1211 }
1212 }
6c6aadb1 1213 else
1214 {
1215 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1216 {
4e1523ef 1217 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1218 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1219 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1220
1221 aSrcFragGetColor =
79f4f036 1222 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w); }";
6c6aadb1 1223 }
e135a155 1224 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1225 {
1226 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1227 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1228
1229 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1230
1231 aSrcVertExtraMain +=
1232 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1233 EOL" vec3 aNormal = transformNormal (occNormal);"
1234 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1235 EOL" aReflect.z += 1.0;"
1236 EOL" TexCoord = aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5);";
1237
1238 aSrcFragGetColor =
1239 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1240 }
6c6aadb1 1241 }
8625ef7e 1242 if ((theBits & OpenGl_PO_VertColor) != 0)
1243 {
4e1523ef 1244 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
8625ef7e 1245 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
4e1523ef 1246 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
8625ef7e 1247 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1248 }
1249 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1250 {
4e1523ef 1251 aSrcVertExtraOut +=
1252 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1253 EOL"THE_SHADER_OUT vec4 Position;";
1254 aSrcFragExtraOut +=
1255 EOL"THE_SHADER_IN vec4 PositionWorld;"
1256 EOL"THE_SHADER_IN vec4 Position;";
8625ef7e 1257 aSrcVertExtraMain +=
1258 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1259 EOL" Position = occWorldViewMatrix * PositionWorld;";
1260 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1261 }
1262
ac116c22 1263 TCollection_AsciiString aSrcVertEndMain;
1264 if ((theBits & OpenGl_PO_StippleLine) != 0)
1265 {
959a265a 1266 bool hasGlslBitOps = false;
ac116c22 1267 #if defined(GL_ES_VERSION_2_0)
1268 if (myContext->IsGlGreaterEqual (3, 0))
1269 {
1270 aProgramSrc->SetHeader ("#version 300 es");
959a265a 1271 hasGlslBitOps = true;
ac116c22 1272 }
1273 #else
959a265a 1274 if (myContext->IsGlGreaterEqual (3, 0))
1275 {
1276 aProgramSrc->SetHeader ("#version 130");
1277 hasGlslBitOps = true;
1278 }
1279 else if(myContext->CheckExtension("GL_EXT_gpu_shader4"))
ac116c22 1280 {
959a265a 1281 aProgramSrc->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1282 hasGlslBitOps = true;
ac116c22 1283 }
1284 #endif
1285
959a265a 1286 if (hasGlslBitOps)
ac116c22 1287 {
1288 aSrcVertExtraOut +=
1289 EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1290 aSrcFragExtraOut +=
1291 EOL"THE_SHADER_IN vec2 ScreenSpaceCoord;"
1292 EOL"uniform int uPattern;"
1293 EOL"uniform float uFactor;";
1294 aSrcVertEndMain =
1295 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1296 aSrcFragMainGetColor =
1297 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1298 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1299 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1300 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1301 EOL" vec4 aColor = getColor();"
1302 EOL" if (aColor.a <= 0.1) discard;"
1303 EOL" occFragColor = aColor;";
1304 }
1305 else
1306 {
1307 const TCollection_ExtendedString aWarnMessage =
1308 "Warning: stipple lines in GLSL will be ignored.";
3b523c4c 1309 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1310 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
ac116c22 1311 }
1312 }
1313
8625ef7e 1314 aSrcVert =
e135a155 1315 aSrcVertExtraFunc
1316 + aSrcVertExtraOut
8625ef7e 1317 + EOL"void main()"
1318 EOL"{"
1319 + aSrcVertExtraMain
1320 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
ac116c22 1321 + aSrcVertEndMain
1322 + EOL"}";
8625ef7e 1323
1324 aSrcFrag =
1325 aSrcFragExtraOut
1326 + aSrcFragGetColor
1327 + EOL"void main()"
1328 EOL"{"
1329 + aSrcFragExtraMain
1330 + aSrcFragMainGetColor
1331 + EOL"}";
1332
4e1523ef 1333#if !defined(GL_ES_VERSION_2_0)
1334 if (myContext->core32 != NULL)
1335 {
1336 aProgramSrc->SetHeader ("#version 150");
1337 }
1338#endif
8625ef7e 1339 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1340 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1341
1342 TCollection_AsciiString aKey;
1343 if (!Create (aProgramSrc, aKey, theProgram))
1344 {
1345 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1346 return Standard_False;
1347 }
1348 return Standard_True;
1349}
1350
256f9ac0 1351// =======================================================================
1352// function : stdComputeLighting
1353// purpose :
1354// =======================================================================
abdf0b10 1355TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
256f9ac0 1356{
c357e426 1357 bool aLightsMap[Graphic3d_TOLS_SPOT + 1] = { false, false, false, false };
256f9ac0 1358 TCollection_AsciiString aLightsFunc, aLightsLoop;
1359 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1360 if (aLights != NULL)
1361 {
1362 Standard_Integer anIndex = 0;
1363 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1364 {
1365 switch (aLightIter.Value().Type)
1366 {
c357e426 1367 case Graphic3d_TOLS_AMBIENT:
256f9ac0 1368 --anIndex;
1369 break; // skip ambient
c357e426 1370 case Graphic3d_TOLS_DIRECTIONAL:
256f9ac0 1371 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1372 break;
c357e426 1373 case Graphic3d_TOLS_POSITIONAL:
256f9ac0 1374 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1375 break;
c357e426 1376 case Graphic3d_TOLS_SPOT:
256f9ac0 1377 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1378 break;
1379 }
1380
1381 bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
1382 if (aTypeBit)
1383 {
1384 continue;
1385 }
1386
1387 aTypeBit = true;
1388 switch (aLightIter.Value().Type)
1389 {
c357e426 1390 case Graphic3d_TOLS_AMBIENT: break;
1391 case Graphic3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
1392 case Graphic3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break;
1393 case Graphic3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break;
256f9ac0 1394 }
1395 }
1396 }
1397
abdf0b10 1398 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1399 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1400 if (theHasVertColor)
1401 {
1402 aGetMatAmbient = "getVertColor();";
1403 aGetMatDiffuse = "getVertColor();";
1404 }
1405
256f9ac0 1406 return TCollection_AsciiString()
1407 + THE_FUNC_lightDef
1408 + aLightsFunc
1409 + EOL
1410 EOL"vec4 computeLighting (in vec3 theNormal,"
1411 EOL" in vec3 theView,"
1412 EOL" in vec4 thePoint,"
1413 EOL" in bool theIsFront)"
1414 EOL"{"
1415 EOL" Ambient = occLightAmbient.rgb;"
1416 EOL" Diffuse = vec3 (0.0);"
1417 EOL" Specular = vec3 (0.0);"
1418 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1419 + aLightsLoop
363bc51b 1420 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
1421 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
1422 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1423 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1424 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
1425 EOL" + Diffuse * aMatDiffuse.rgb"
1426 EOL" + Specular * aMatSpecular.rgb"
1427 EOL" + aMatEmission.rgb;"
1428 EOL" return vec4 (aColor, aMatDiffuse.a);"
256f9ac0 1429 EOL"}";
1430}
1431
8625ef7e 1432// =======================================================================
1433// function : prepareStdProgramGouraud
1434// purpose :
1435// =======================================================================
1436Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1437 const Standard_Integer theBits)
1438{
1439 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
abdf0b10 1440 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
6c6aadb1 1441 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
8625ef7e 1442 if ((theBits & OpenGl_PO_Point) != 0)
1443 {
1444 #if defined(GL_ES_VERSION_2_0)
1445 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1446 #endif
1447 }
abdf0b10 1448 if ((theBits & OpenGl_PO_VertColor) != 0)
1449 {
1450 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1451 }
6c6aadb1 1452 if ((theBits & OpenGl_PO_Point) != 0)
1453 {
1454 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1455 {
1456 aSrcFragGetColor =
1457 EOL"vec4 getColor(void)"
1458 EOL"{"
1459 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
4e1523ef 1460 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
6c6aadb1 1461 EOL"}";
15478b1b 1462 #if !defined(GL_ES_VERSION_2_0)
1463 if (myContext->core11 != NULL
1464 && myContext->IsGlGreaterEqual (2, 1))
1465 {
1466 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1467 }
1468 #endif
6c6aadb1 1469 }
1470 }
1471 else
1472 {
1473 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1474 {
4e1523ef 1475 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1476 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1477 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1478
1479 aSrcFragGetColor =
1480 EOL"vec4 getColor(void)"
1481 EOL"{"
1482 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
79f4f036 1483 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1484 EOL"}";
1485 }
1486 }
8625ef7e 1487 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1488 {
4e1523ef 1489 aSrcVertExtraOut +=
1490 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1491 EOL"THE_SHADER_OUT vec4 Position;";
1492 aSrcFragExtraOut +=
1493 EOL"THE_SHADER_IN vec4 PositionWorld;"
1494 EOL"THE_SHADER_IN vec4 Position;";
8625ef7e 1495 aSrcVertExtraMain +=
1496 EOL" PositionWorld = aPositionWorld;"
1497 EOL" Position = aPosition;";
1498 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1499 }
1500
abdf0b10 1501 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1502 aSrcVert = TCollection_AsciiString()
1503 + THE_FUNC_transformNormal
1504 + EOL
abdf0b10 1505 + aSrcVertColor
256f9ac0 1506 + aLights
8625ef7e 1507 + EOL
4e1523ef 1508 EOL"THE_SHADER_OUT vec4 FrontColor;"
1509 EOL"THE_SHADER_OUT vec4 BackColor;"
8625ef7e 1510 EOL
1511 + aSrcVertExtraOut
1512 + EOL"void main()"
1513 EOL"{"
1514 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1515 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1516 EOL" vec3 aNormal = transformNormal (occNormal);"
1517 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1518 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1519 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1520 + aSrcVertExtraMain
1521 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1522 EOL"}";
1523
1524 aSrcFrag = TCollection_AsciiString()
4e1523ef 1525 + EOL"THE_SHADER_IN vec4 FrontColor;"
1526 EOL"THE_SHADER_IN vec4 BackColor;"
8625ef7e 1527 + aSrcFragExtraOut
6c6aadb1 1528 + aSrcFragGetColor
8625ef7e 1529 + EOL"void main()"
1530 EOL"{"
1531 + aSrcFragExtraMain
4e1523ef 1532 + EOL" occFragColor = getColor();"
8625ef7e 1533 EOL"}";
1534
4e1523ef 1535#if !defined(GL_ES_VERSION_2_0)
1536 if (myContext->core32 != NULL)
1537 {
1538 aProgramSrc->SetHeader ("#version 150");
1539 }
1540#endif
8625ef7e 1541 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1542 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1543 TCollection_AsciiString aKey;
1544 if (!Create (aProgramSrc, aKey, theProgram))
1545 {
1546 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1547 return Standard_False;
1548 }
1549 return Standard_True;
1550}
1551
1552// =======================================================================
1553// function : prepareStdProgramPhong
1554// purpose :
1555// =======================================================================
1556Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1557 const Standard_Integer theBits)
1558{
6c6aadb1 1559 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1560
8625ef7e 1561 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
6c6aadb1 1562 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1563 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
8625ef7e 1564 if ((theBits & OpenGl_PO_Point) != 0)
1565 {
1566 #if defined(GL_ES_VERSION_2_0)
1567 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1568 #endif
1569 }
abdf0b10 1570 if ((theBits & OpenGl_PO_VertColor) != 0)
1571 {
7e859dff 1572 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1573 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1574 aSrcFragGetVertColor = EOL"THE_SHADER_IN vec4 VertColor;"
1575 EOL"vec4 getVertColor(void) { return VertColor; }";
abdf0b10 1576 }
6c6aadb1 1577
1578 if ((theBits & OpenGl_PO_Point) != 0)
1579 {
1580 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1581 {
1582 aSrcFragGetColor =
1583 EOL"vec4 getColor(void)"
1584 EOL"{"
1585 EOL" vec4 aColor = " thePhongCompLight ";"
4e1523ef 1586 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
6c6aadb1 1587 EOL"}";
15478b1b 1588 #if !defined(GL_ES_VERSION_2_0)
1589 if (myContext->core11 != NULL
1590 && myContext->IsGlGreaterEqual (2, 1))
1591 {
1592 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1593 }
1594 #endif
6c6aadb1 1595 }
1596 }
1597 else
1598 {
1599 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1600 {
4e1523ef 1601 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1602 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1603 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1604
1605 aSrcFragGetColor =
1606 EOL"vec4 getColor(void)"
1607 EOL"{"
1608 EOL" vec4 aColor = " thePhongCompLight ";"
79f4f036 1609 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1610 EOL"}";
1611 }
1612 }
1613
8625ef7e 1614 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1615 {
1616 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1617 }
1618
1619 aSrcVert = TCollection_AsciiString()
1620 + THE_FUNC_transformNormal
1621 + EOL
4e1523ef 1622 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1623 EOL"THE_SHADER_OUT vec4 Position;"
1624 EOL"THE_SHADER_OUT vec3 Normal;"
1625 EOL"THE_SHADER_OUT vec3 View;"
8625ef7e 1626 EOL
1627 + aSrcVertExtraOut
1628 + EOL"void main()"
1629 EOL"{"
1630 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1631 EOL" Position = occWorldViewMatrix * PositionWorld;"
1632 EOL" Normal = transformNormal (occNormal);"
1633 EOL" View = vec3 (0.0, 0.0, 1.0);"
1634 + aSrcVertExtraMain
1635 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1636 EOL"}";
1637
abdf0b10 1638 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1639 aSrcFrag = TCollection_AsciiString()
4e1523ef 1640 + EOL"THE_SHADER_IN vec4 PositionWorld;"
1641 EOL"THE_SHADER_IN vec4 Position;"
1642 EOL"THE_SHADER_IN vec3 Normal;"
1643 EOL"THE_SHADER_IN vec3 View;"
8625ef7e 1644 + EOL
6c6aadb1 1645 + aSrcFragExtraOut
1646 + aSrcFragGetVertColor
256f9ac0 1647 + aLights
6c6aadb1 1648 + aSrcFragGetColor
8625ef7e 1649 + EOL
1650 EOL"void main()"
1651 EOL"{"
1652 + aSrcFragExtraMain
4e1523ef 1653 + EOL" occFragColor = getColor();"
8625ef7e 1654 EOL"}";
1655
4e1523ef 1656#if !defined(GL_ES_VERSION_2_0)
1657 if (myContext->core32 != NULL)
1658 {
1659 aProgramSrc->SetHeader ("#version 150");
1660 }
1661#endif
8625ef7e 1662 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1663 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1664 TCollection_AsciiString aKey;
1665 if (!Create (aProgramSrc, aKey, theProgram))
1666 {
1667 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1668 return Standard_False;
1669 }
1670 return Standard_True;
1671}
1672
38a0206f 1673// =======================================================================
f978241f 1674// function : prepareStdProgramStereo
38a0206f 1675// purpose :
1676// =======================================================================
f978241f 1677Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1678 const Graphic3d_StereoMode theStereoMode)
38a0206f 1679{
1680 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1681 TCollection_AsciiString aSrcVert =
1682 EOL"THE_SHADER_OUT vec2 TexCoord;"
1683 EOL"void main()"
1684 EOL"{"
1685 EOL" TexCoord = occVertex.zw;"
1686 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1687 EOL"}";
1688
f978241f 1689 TCollection_AsciiString aSrcFrag;
1690 switch (theStereoMode)
1691 {
1692 case Graphic3d_StereoMode_Anaglyph:
1693 {
1694 aSrcFrag =
1695 EOL"uniform sampler2D uLeftSampler;"
1696 EOL"uniform sampler2D uRightSampler;"
1697 EOL
1698 EOL"uniform mat4 uMultL;"
1699 EOL"uniform mat4 uMultR;"
1700 EOL
1701 EOL"vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
1702 EOL"vec4 THE_POW_DOWN = 1.0 / THE_POW_UP;"
1703 EOL
1704 EOL"THE_SHADER_IN vec2 TexCoord;"
1705 EOL
1706 EOL"void main()"
1707 EOL"{"
1708 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1709 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1710 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
1711 EOL" aColorR = pow (aColorR, THE_POW_UP);"
1712 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
1713 EOL" occFragColor = pow (aColor, THE_POW_DOWN);"
1714 EOL"}";
1715 break;
1716 }
1717 case Graphic3d_StereoMode_RowInterlaced:
1718 {
1719 aSrcFrag =
1720 EOL"uniform sampler2D uLeftSampler;"
1721 EOL"uniform sampler2D uRightSampler;"
1722 EOL
1723 EOL"THE_SHADER_IN vec2 TexCoord;"
1724 EOL
1725 EOL"void main()"
1726 EOL"{"
1727 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1728 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 1729 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
f978241f 1730 EOL" {"
1731 EOL" occFragColor = aColorL;"
1732 EOL" }"
1733 EOL" else"
1734 EOL" {"
1735 EOL" occFragColor = aColorR;"
1736 EOL" }"
1737 EOL"}";
1738 break;
1739 }
1740 case Graphic3d_StereoMode_ColumnInterlaced:
1741 {
1742 aSrcFrag =
1743 EOL"uniform sampler2D uLeftSampler;"
1744 EOL"uniform sampler2D uRightSampler;"
1745 EOL
1746 EOL"THE_SHADER_IN vec2 TexCoord;"
1747 EOL
1748 EOL"void main()"
1749 EOL"{"
1750 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1751 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 1752 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
f978241f 1753 EOL" {"
1754 EOL" occFragColor = aColorL;"
1755 EOL" }"
1756 EOL" else"
1757 EOL" {"
1758 EOL" occFragColor = aColorR;"
1759 EOL" }"
1760 EOL"}";
1761 break;
1762 }
1763 case Graphic3d_StereoMode_ChessBoard:
1764 {
1765 aSrcFrag =
1766 EOL"uniform sampler2D uLeftSampler;"
1767 EOL"uniform sampler2D uRightSampler;"
1768 EOL
1769 EOL"THE_SHADER_IN vec2 TexCoord;"
1770 EOL
1771 EOL"void main()"
1772 EOL"{"
1773 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1774 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 1775 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
1776 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
f978241f 1777 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
1778 EOL" {"
1779 EOL" occFragColor = aColorL;"
1780 EOL" }"
1781 EOL" else"
1782 EOL" {"
1783 EOL" occFragColor = aColorR;"
1784 EOL" }"
1785 EOL"}";
1786 break;
1787 }
1788 case Graphic3d_StereoMode_SideBySide:
1789 {
1790 aSrcFrag =
1791 EOL"uniform sampler2D uLeftSampler;"
1792 EOL"uniform sampler2D uRightSampler;"
1793 EOL
1794 EOL"THE_SHADER_IN vec2 TexCoord;"
1795 EOL
1796 EOL"void main()"
1797 EOL"{"
1798 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
1799 EOL" if (TexCoord.x > 0.5)"
1800 EOL" {"
1801 EOL" aTexCoord.x -= 1.0;"
1802 EOL" }"
1803 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1804 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1805 EOL" if (TexCoord.x <= 0.5)"
1806 EOL" {"
1807 EOL" occFragColor = aColorL;"
1808 EOL" }"
1809 EOL" else"
1810 EOL" {"
1811 EOL" occFragColor = aColorR;"
1812 EOL" }"
1813 EOL"}";
1814 break;
1815 }
1816 case Graphic3d_StereoMode_OverUnder:
1817 {
1818 aSrcFrag =
1819 EOL"uniform sampler2D uLeftSampler;"
1820 EOL"uniform sampler2D uRightSampler;"
1821 EOL
1822 EOL"THE_SHADER_IN vec2 TexCoord;"
1823 EOL
1824 EOL"void main()"
1825 EOL"{"
1826 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
1827 EOL" if (TexCoord.y > 0.5)"
1828 EOL" {"
1829 EOL" aTexCoord.y -= 1.0;"
1830 EOL" }"
1831 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1832 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1833 EOL" if (TexCoord.y <= 0.5)"
1834 EOL" {"
1835 EOL" occFragColor = aColorL;"
1836 EOL" }"
1837 EOL" else"
1838 EOL" {"
1839 EOL" occFragColor = aColorR;"
1840 EOL" }"
1841 EOL"}";
1842 break;
1843 }
1844 case Graphic3d_StereoMode_QuadBuffer:
1845 case Graphic3d_StereoMode_SoftPageFlip:
1846 default:
1847 {
1848 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
1849 if (!aProgram.IsNull())
1850 {
1851 return aProgram->IsValid();
1852 }*/
1853 aSrcFrag =
1854 EOL"uniform sampler2D uLeftSampler;"
1855 EOL"uniform sampler2D uRightSampler;"
1856 EOL
1857 EOL"THE_SHADER_IN vec2 TexCoord;"
1858 EOL
1859 EOL"void main()"
1860 EOL"{"
1861 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1862 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1863 EOL" aColorL.b = 0.0;"
1864 EOL" aColorL.g = 0.0;"
1865 EOL" aColorR.r = 0.0;"
1866 EOL" occFragColor = aColorL + aColorR;"
1867 EOL"}";
1868 break;
1869 }
1870 }
38a0206f 1871
1872#if !defined(GL_ES_VERSION_2_0)
1873 if (myContext->core32 != NULL)
1874 {
1875 aProgramSrc->SetHeader ("#version 150");
1876 }
1877#endif
1878
1879 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1880 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1881 TCollection_AsciiString aKey;
f978241f 1882 if (!Create (aProgramSrc, aKey, theProgram))
38a0206f 1883 {
f978241f 1884 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
38a0206f 1885 return Standard_False;
1886 }
1887
f978241f 1888 myContext->BindProgram (theProgram);
1889 theProgram->SetSampler (myContext, "uLeftSampler", 0);
1890 theProgram->SetSampler (myContext, "uRightSampler", 1);
38a0206f 1891 myContext->BindProgram (NULL);
1892 return Standard_True;
1893}
1894
8625ef7e 1895// =======================================================================
1896// function : bindProgramWithState
1897// purpose :
1898// =======================================================================
1899Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1900 const OpenGl_Element* theAspect)
1901{
1902 if (!myContext->BindProgram (theProgram))
1903 {
1904 return Standard_False;
1905 }
1906 theProgram->ApplyVariables (myContext);
1907
1908 const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1909 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1910 {
1911 UpdateMaterialStateTo (theProgram, theAspect);
1912 }
1913
1914 PushState (theProgram);
1915 return Standard_True;
1916}