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