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