0027789: Visualization, TKOpenGl - improve compatibility with new OpenGL ES devices
[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" {"
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
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" {"
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
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),
e6804ff7 261 myLastView (NULL)
30f0ad28 262{
256f9ac0 263 //
30f0ad28 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
05e2200b 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();
b86bb3df 286 myBlitProgram.Nullify();
f978241f 287 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
288 {
289 myStereoPrograms[aModeIter].Nullify();
290 }
05e2200b 291 switchLightPrograms();
292}
293
30f0ad28 294// =======================================================================
295// function : Create
296// purpose : Creates new shader program
297// =======================================================================
8625ef7e 298Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
299 TCollection_AsciiString& theShareKey,
300 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 301{
392ac980 302 theProgram.Nullify();
303 if (theProxy.IsNull())
30f0ad28 304 {
8625ef7e 305 return Standard_False;
30f0ad28 306 }
392ac980 307
308 theShareKey = theProxy->GetId();
309 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
310 {
05dd08ce 311 if (theProgram->Share())
312 {
313 myProgramList.Append (theProgram);
314 }
8625ef7e 315 return Standard_True;
392ac980 316 }
317
318 theProgram = new OpenGl_ShaderProgram (theProxy);
319 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
30f0ad28 320 {
392ac980 321 theProgram->Release (myContext);
322 theShareKey.Clear();
323 theProgram.Nullify();
8625ef7e 324 return Standard_False;
30f0ad28 325 }
30f0ad28 326
392ac980 327 myProgramList.Append (theProgram);
328 myContext->ShareResource (theShareKey, theProgram);
8625ef7e 329 return Standard_True;
30f0ad28 330}
331
332// =======================================================================
333// function : Unregister
334// purpose : Removes specified shader program from the manager
335// =======================================================================
392ac980 336void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
337 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 338{
339 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
340 {
341 if (anIt.Value() == theProgram)
342 {
392ac980 343 if (!theProgram->UnShare())
344 {
345 theShareKey.Clear();
346 theProgram.Nullify();
347 return;
348 }
349
30f0ad28 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();
05dd08ce 364 myContext->ReleaseResource (anID, Standard_True);
30f0ad28 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
256f9ac0 386// =======================================================================
387// function : switchLightPrograms
388// purpose :
389// =======================================================================
390void OpenGl_ShaderManager::switchLightPrograms()
391{
c357e426 392 TCollection_AsciiString aKey (myShadingModel == Graphic3d_TOSM_FRAGMENT ? "p_" : "g_");
256f9ac0 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 {
c357e426 400 case Graphic3d_TOLS_AMBIENT:
256f9ac0 401 break; // skip ambient
c357e426 402 case Graphic3d_TOLS_DIRECTIONAL:
256f9ac0 403 aKey += "d";
404 break;
c357e426 405 case Graphic3d_TOLS_POSITIONAL:
256f9ac0 406 aKey += "p";
407 break;
c357e426 408 case Graphic3d_TOLS_SPOT:
256f9ac0 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
30f0ad28 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();
256f9ac0 430 switchLightPrograms();
431}
432
433// =======================================================================
434// function : SetShadingModel
435// purpose :
436// =======================================================================
c357e426 437void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
256f9ac0 438{
439 myShadingModel = theModel;
440 switchLightPrograms();
30f0ad28 441}
442
443// =======================================================================
444// function : SetProjectionState
445// purpose : Sets new state of OCCT projection transform
446// =======================================================================
c827ea3a 447void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
30f0ad28 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// =======================================================================
c827ea3a 457void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
30f0ad28 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// =======================================================================
c827ea3a 467void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
30f0ad28 468{
469 myWorldViewState.Set (theWorldViewMatrix);
470 myWorldViewState.Update();
471}
472
30f0ad28 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
4fe9ad57 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
0adbd30f 520 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
01eaf654 521 static Standard_Integer NbOfVec4() { return 4; }
4fe9ad57 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
0adbd30f 534 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
01eaf654 535 static Standard_Integer NbOfVec2i() { return 1; }
4fe9ad57 536
537};
538
30f0ad28 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{
12381341 545 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
546 || !theProgram->IsValid())
30f0ad28 547 {
548 return;
549 }
30f0ad28 550
01eaf654 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
12381341 557 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
558 if (aLightsDefNb < 1)
559 {
30f0ad28 560 theProgram->SetUniform (myContext,
12381341 561 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
562 0);
30f0ad28 563 theProgram->SetUniform (myContext,
12381341 564 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
565 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
01eaf654 566 theProgram->SetUniform (myContext,
567 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
568 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
569 aLightTypeArray[0].Packed());
12381341 570 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
0c4033b4 571 delete[] aLightTypeArray;
12381341 572 return;
573 }
30f0ad28 574
4fe9ad57 575 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
30f0ad28 576
12381341 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();
c357e426 582 if (aLight.Type == Graphic3d_TOLS_AMBIENT)
30f0ad28 583 {
12381341 584 anAmbient += aLight.Color;
585 continue;
586 }
587 else if (aLightsNb >= OpenGLMaxLights)
588 {
589 continue;
590 }
30f0ad28 591
4fe9ad57 592 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
593 aLightType.Type = aLight.Type;
594 aLightType.IsHeadlight = aLight.IsHeadlight;
30f0ad28 595
4fe9ad57 596 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
597 aLightParams.Color = aLight.Color;
c357e426 598 aLightParams.Position = aLight.Type == Graphic3d_TOLS_DIRECTIONAL
4fe9ad57 599 ? -aLight.Direction
600 : aLight.Position;
c357e426 601 if (aLight.Type == Graphic3d_TOLS_SPOT)
12381341 602 {
4fe9ad57 603 aLightParams.Direction = aLight.Direction;
30f0ad28 604 }
4fe9ad57 605 aLightParams.Parameters = aLight.Params;
12381341 606 ++aLightsNb;
607 }
30f0ad28 608
12381341 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);
01eaf654 615 theProgram->SetUniform (myContext,
616 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
617 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
618 aLightTypeArray[0].Packed());
12381341 619 if (aLightsNb > 0)
620 {
4fe9ad57 621 theProgram->SetUniform (myContext,
622 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
623 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
624 aLightParamsArray[0].Packed());
30f0ad28 625 }
4fe9ad57 626 delete[] aLightParamsArray;
627 delete[] aLightTypeArray;
30f0ad28 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
12381341 763 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
764 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
89a929ea 765 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
12381341 766 {
767 return;
768 }
769
5495fa7e 770 GLint aPlanesNb = 0;
51b10cd4 771 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 772 anIter.More(); anIter.Next())
30f0ad28 773 {
774 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
775 if (!myContext->Clipping().IsEnabled (aPlane))
776 {
777 continue;
778 }
779
12381341 780 ++aPlanesNb;
781 }
782 if (aPlanesNb < 1)
783 {
784 return;
785 }
786
89a929ea 787 OpenGl_Vec4 anEquations[THE_MAX_CLIP_PLANES];
12381341 788 GLuint aPlaneId = 0;
51b10cd4 789 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 790 anIter.More(); anIter.Next())
791 {
792 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
793 if (!myContext->Clipping().IsEnabled (aPlane))
30f0ad28 794 {
12381341 795 continue;
30f0ad28 796 }
89a929ea 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 }
30f0ad28 804
12381341 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());
12381341 810 ++aPlaneId;
30f0ad28 811 }
5495fa7e 812
813 theProgram->SetUniform (myContext,
814 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
815 aPlanesNb);
89a929ea 816 theProgram->SetUniform (myContext, aLocEquations, THE_MAX_CLIP_PLANES, anEquations);
30f0ad28 817}
818
30f0ad28 819// =======================================================================
e135a155 820// function : PushState
30f0ad28 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);
30f0ad28 826 PushWorldViewState (theProgram);
827 PushModelWorldState (theProgram);
05e2200b 828 PushProjectionState (theProgram);
30f0ad28 829 PushLightSourceState (theProgram);
12381341 830}
8625ef7e 831
832// =======================================================================
833// function : prepareStdProgramFont
834// purpose :
835// =======================================================================
836Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
837{
838 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
b990e557 839 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
79f4f036 840 + EOL"THE_SHADER_OUT vec2 TexCoord;"
841 EOL"void main()"
b990e557 842 EOL"{"
843 EOL" TexCoord = occTexCoord.st;"
844 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
845 EOL"}";
846
4e1523ef 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
b990e557 856 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
79f4f036 857 + EOL"THE_SHADER_IN vec2 TexCoord;"
4e1523ef 858 + aSrcGetAlpha
859 + EOL"void main()"
b990e557 860 EOL"{"
861 EOL" vec4 aColor = occColor;"
862 EOL" aColor.a *= getAlpha();"
863 EOL" if (aColor.a <= 0.285) discard;"
4e1523ef 864 EOL" occFragColor = aColor;"
b990e557 865 EOL"}";
8625ef7e 866
4e1523ef 867#if !defined(GL_ES_VERSION_2_0)
868 if (myContext->core32 != NULL)
869 {
870 aProgramSrc->SetHeader ("#version 150");
871 }
872#endif
8625ef7e 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// =======================================================================
b86bb3df 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 }
4e1523ef 929#else
930 if (myContext->core32 != NULL)
931 {
932 aProgramSrc->SetHeader ("#version 150");
933 }
b86bb3df 934#endif
b86bb3df 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
299e0ab9 951// =======================================================================
952// function : pointSpriteAlphaSrc
953// purpose :
954// =======================================================================
fd59283a 955TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
299e0ab9 956{
fd59283a 957 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").a; }";
299e0ab9 958#if !defined(GL_ES_VERSION_2_0)
fd59283a 959 if (myContext->core11 == NULL
960 && (theBits & OpenGl_PO_TextureA) != 0)
299e0ab9 961 {
fd59283a 962 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").r; }";
299e0ab9 963 }
fd59283a 964#else
965 (void )theBits;
299e0ab9 966#endif
299e0ab9 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
b86bb3df 984// =======================================================================
8625ef7e 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();
299e0ab9 992 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
8625ef7e 993 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
4e1523ef 994 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
8625ef7e 995 if ((theBits & OpenGl_PO_Point) != 0)
996 {
997 #if defined(GL_ES_VERSION_2_0)
998 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
999 #endif
8625ef7e 1000
299e0ab9 1001 if ((theBits & OpenGl_PO_TextureRGB) != 0)
8625ef7e 1002 {
1003 aSrcFragGetColor =
fd59283a 1004 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord "); }";
8625ef7e 1005 }
299e0ab9 1006
fd59283a 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 }
8625ef7e 1032 }
6c6aadb1 1033 else
1034 {
1035 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1036 {
4e1523ef 1037 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1038 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1039 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1040
1041 aSrcFragGetColor =
79f4f036 1042 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w); }";
6c6aadb1 1043 }
e135a155 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;"
b872ca56 1056 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
e135a155 1057
1058 aSrcFragGetColor =
1059 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1060 }
6c6aadb1 1061 }
8625ef7e 1062 if ((theBits & OpenGl_PO_VertColor) != 0)
1063 {
4e1523ef 1064 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
8625ef7e 1065 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
4e1523ef 1066 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
8625ef7e 1067 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1068 }
1a7ece8f 1069 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1070 {
4e1523ef 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;";
8625ef7e 1077 aSrcVertExtraMain +=
1078 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1079 EOL" Position = occWorldViewMatrix * PositionWorld;";
1a7ece8f 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 }
8625ef7e 1093 }
1094
ac116c22 1095 TCollection_AsciiString aSrcVertEndMain;
1096 if ((theBits & OpenGl_PO_StippleLine) != 0)
1097 {
959a265a 1098 bool hasGlslBitOps = false;
ac116c22 1099 #if defined(GL_ES_VERSION_2_0)
1100 if (myContext->IsGlGreaterEqual (3, 0))
1101 {
1102 aProgramSrc->SetHeader ("#version 300 es");
959a265a 1103 hasGlslBitOps = true;
ac116c22 1104 }
1105 #else
959a265a 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"))
ac116c22 1112 {
959a265a 1113 aProgramSrc->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1114 hasGlslBitOps = true;
ac116c22 1115 }
1116 #endif
1117
959a265a 1118 if (hasGlslBitOps)
ac116c22 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.";
3b523c4c 1141 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1142 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
ac116c22 1143 }
1144 }
1145
8625ef7e 1146 aSrcVert =
e135a155 1147 aSrcVertExtraFunc
1148 + aSrcVertExtraOut
8625ef7e 1149 + EOL"void main()"
1150 EOL"{"
1151 + aSrcVertExtraMain
1152 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
ac116c22 1153 + aSrcVertEndMain
1154 + EOL"}";
8625ef7e 1155
1156 aSrcFrag =
1157 aSrcFragExtraOut
1158 + aSrcFragGetColor
299e0ab9 1159 + aSrcGetAlpha
8625ef7e 1160 + EOL"void main()"
1161 EOL"{"
1162 + aSrcFragExtraMain
1163 + aSrcFragMainGetColor
1164 + EOL"}";
1165
4e1523ef 1166#if !defined(GL_ES_VERSION_2_0)
1167 if (myContext->core32 != NULL)
1168 {
1169 aProgramSrc->SetHeader ("#version 150");
1170 }
1171#endif
8625ef7e 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
299e0ab9 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 {
fd59283a 1194 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
299e0ab9 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 + ";"
fd59283a 1209 EOL" aColor = occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ") * aColor;"
299e0ab9 1210 EOL" if (aColor.a <= 0.1) discard;"
1211 EOL" return aColor;"
1212 EOL"}";
1213 }
1214
1215 return aSrcFragGetColor;
1216}
1217
256f9ac0 1218// =======================================================================
1219// function : stdComputeLighting
1220// purpose :
1221// =======================================================================
abdf0b10 1222TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
256f9ac0 1223{
f68acbf4 1224 Standard_Integer aLightsMap[Graphic3d_TOLS_SPOT + 1] = { 0, 0, 0, 0 };
256f9ac0 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 {
c357e426 1234 case Graphic3d_TOLS_AMBIENT:
256f9ac0 1235 --anIndex;
1236 break; // skip ambient
c357e426 1237 case Graphic3d_TOLS_DIRECTIONAL:
256f9ac0 1238 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1239 break;
c357e426 1240 case Graphic3d_TOLS_POSITIONAL:
256f9ac0 1241 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1242 break;
c357e426 1243 case Graphic3d_TOLS_SPOT:
256f9ac0 1244 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1245 break;
1246 }
f68acbf4 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;
256f9ac0 1270 }
1271 }
1272
abdf0b10 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
256f9ac0 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
363bc51b 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);"
256f9ac0 1304 EOL"}";
1305}
1306
8625ef7e 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();
abdf0b10 1315 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
6c6aadb1 1316 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
8625ef7e 1317 if ((theBits & OpenGl_PO_Point) != 0)
1318 {
1319 #if defined(GL_ES_VERSION_2_0)
1320 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1321 #endif
299e0ab9 1322
1323 if (textureUsed (theBits))
6c6aadb1 1324 {
299e0ab9 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);
6c6aadb1 1334 }
1335 }
1336 else
1337 {
1338 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1339 {
4e1523ef 1340 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1341 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1342 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1343
1344 aSrcFragGetColor =
1345 EOL"vec4 getColor(void)"
1346 EOL"{"
1347 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
79f4f036 1348 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1349 EOL"}";
1350 }
1351 }
299e0ab9 1352
1353 if ((theBits & OpenGl_PO_VertColor) != 0)
1354 {
1355 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1356 }
1357
1a7ece8f 1358 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1359 {
4e1523ef 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;";
8625ef7e 1366 aSrcVertExtraMain +=
1367 EOL" PositionWorld = aPositionWorld;"
1368 EOL" Position = aPosition;";
1a7ece8f 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 }
8625ef7e 1382 }
1383
abdf0b10 1384 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1385 aSrcVert = TCollection_AsciiString()
1386 + THE_FUNC_transformNormal
1387 + EOL
abdf0b10 1388 + aSrcVertColor
256f9ac0 1389 + aLights
8625ef7e 1390 + EOL
4e1523ef 1391 EOL"THE_SHADER_OUT vec4 FrontColor;"
1392 EOL"THE_SHADER_OUT vec4 BackColor;"
8625ef7e 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()
4e1523ef 1408 + EOL"THE_SHADER_IN vec4 FrontColor;"
1409 EOL"THE_SHADER_IN vec4 BackColor;"
8625ef7e 1410 + aSrcFragExtraOut
6c6aadb1 1411 + aSrcFragGetColor
8625ef7e 1412 + EOL"void main()"
1413 EOL"{"
1414 + aSrcFragExtraMain
4e1523ef 1415 + EOL" occFragColor = getColor();"
8625ef7e 1416 EOL"}";
1417
4e1523ef 1418#if !defined(GL_ES_VERSION_2_0)
1419 if (myContext->core32 != NULL)
1420 {
1421 aProgramSrc->SetHeader ("#version 150");
1422 }
1423#endif
8625ef7e 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{
6c6aadb1 1442 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1443
8625ef7e 1444 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
6c6aadb1 1445 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1446 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
8625ef7e 1447 if ((theBits & OpenGl_PO_Point) != 0)
1448 {
1449 #if defined(GL_ES_VERSION_2_0)
1450 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1451 #endif
6c6aadb1 1452
299e0ab9 1453 if (textureUsed (theBits))
6c6aadb1 1454 {
299e0ab9 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);
6c6aadb1 1464 }
1465 }
1466 else
1467 {
1468 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1469 {
4e1523ef 1470 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1471 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1472 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1473
1474 aSrcFragGetColor =
1475 EOL"vec4 getColor(void)"
1476 EOL"{"
1477 EOL" vec4 aColor = " thePhongCompLight ";"
79f4f036 1478 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1479 EOL"}";
1480 }
1481 }
1482
299e0ab9 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
1a7ece8f 1491 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1492 {
1a7ece8f 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 }
8625ef7e 1505 }
1506
1507 aSrcVert = TCollection_AsciiString()
1508 + THE_FUNC_transformNormal
1509 + EOL
4e1523ef 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;"
8625ef7e 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
abdf0b10 1526 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1527 aSrcFrag = TCollection_AsciiString()
4e1523ef 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;"
8625ef7e 1532 + EOL
6c6aadb1 1533 + aSrcFragExtraOut
1534 + aSrcFragGetVertColor
256f9ac0 1535 + aLights
6c6aadb1 1536 + aSrcFragGetColor
8625ef7e 1537 + EOL
1538 EOL"void main()"
1539 EOL"{"
1540 + aSrcFragExtraMain
4e1523ef 1541 + EOL" occFragColor = getColor();"
8625ef7e 1542 EOL"}";
1543
4e1523ef 1544#if !defined(GL_ES_VERSION_2_0)
1545 if (myContext->core32 != NULL)
1546 {
1547 aProgramSrc->SetHeader ("#version 150");
1548 }
1549#endif
8625ef7e 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
38a0206f 1561// =======================================================================
f978241f 1562// function : prepareStdProgramStereo
38a0206f 1563// purpose :
1564// =======================================================================
f978241f 1565Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1566 const Graphic3d_StereoMode theStereoMode)
38a0206f 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
f978241f 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
0deb6f04 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);"
f978241f 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);"
6e66a3fa 1617 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
f978241f 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);"
6e66a3fa 1640 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
f978241f 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);"
6e66a3fa 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;"
f978241f 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 }
38a0206f 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;
f978241f 1770 if (!Create (aProgramSrc, aKey, theProgram))
38a0206f 1771 {
f978241f 1772 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
38a0206f 1773 return Standard_False;
1774 }
1775
f978241f 1776 myContext->BindProgram (theProgram);
1777 theProgram->SetSampler (myContext, "uLeftSampler", 0);
1778 theProgram->SetSampler (myContext, "uRightSampler", 1);
38a0206f 1779 myContext->BindProgram (NULL);
1780 return Standard_True;
1781}
1782
8625ef7e 1783// =======================================================================
1784// function : bindProgramWithState
1785// purpose :
1786// =======================================================================
299e0ab9 1787Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
8625ef7e 1788{
1789 if (!myContext->BindProgram (theProgram))
1790 {
1791 return Standard_False;
1792 }
1793 theProgram->ApplyVariables (myContext);
1794
8625ef7e 1795 PushState (theProgram);
1796 return Standard_True;
1797}