0027961: Visualization - remove unused and no more working OpenGl_AVIWriter
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
CommitLineData
30f0ad28 1// Created on: 2013-09-26
2// Created by: Denis BOGOLEPOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
30f0ad28 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
30f0ad28 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
30f0ad28 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
30f0ad28 15
16#include <typeinfo>
17
e135a155 18#include <Graphic3d_TextureParams.hxx>
30f0ad28 19#include <OpenGl_AspectFace.hxx>
20#include <OpenGl_AspectLine.hxx>
21#include <OpenGl_AspectMarker.hxx>
22#include <OpenGl_AspectText.hxx>
23#include <OpenGl_Clipping.hxx>
24#include <OpenGl_Context.hxx>
25#include <OpenGl_ShaderManager.hxx>
26#include <OpenGl_ShaderProgram.hxx>
0adbd30f 27#include <OpenGl_Workspace.hxx>
30f0ad28 28
ac116c22 29#include <TCollection_ExtendedString.hxx>
30
92efcf78 31IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
32
8625ef7e 33namespace
34{
35
89a929ea 36 //! Clipping planes limit (see the same definition in Declarations.glsl).
37 static const Standard_Size THE_MAX_CLIP_PLANES = 8;
38
8625ef7e 39#define EOL "\n"
40
79f4f036 41//! Definition of TexCoord varying.
4e1523ef 42const char THE_VARY_TexCoord_OUT[] =
79f4f036 43 EOL"THE_SHADER_OUT vec4 TexCoord;";
4e1523ef 44const char THE_VARY_TexCoord_IN[] =
79f4f036 45 EOL"THE_SHADER_IN vec4 TexCoord;";
46//! Compute TexCoord value in Vertex Shader
47const char THE_VARY_TexCoord_Trsf[] =
48 EOL" float aRotSin = occTextureTrsf_RotationSin();"
49 EOL" float aRotCos = occTextureTrsf_RotationCos();"
50 EOL" vec2 aTex2 = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
51 EOL" vec2 aCopy = aTex2;"
52 EOL" aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
53 EOL" aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
54 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
6c6aadb1 55
fd59283a 56//! Auxiliary function to flip gl_PointCoord vertically
57#define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
58
8625ef7e 59//! Auxiliary function to transform normal
60const char THE_FUNC_transformNormal[] =
61 EOL"vec3 transformNormal (in vec3 theNormal)"
62 EOL"{"
63 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
64 EOL" * occModelWorldMatrixInverseTranspose"
65 EOL" * vec4 (theNormal, 0.0);"
66 EOL" return normalize (aResult.xyz);"
67 EOL"}";
68
69//! Global shader variable for color definition with lighting enabled.
70const char THE_FUNC_lightDef[] =
71 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
72 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
73 EOL"vec3 Specular;"; //!< Specular contribution of light sources
74
8625ef7e 75//! Function computes contribution of isotropic point light source
76const char THE_FUNC_pointLight[] =
77 EOL"void pointLight (in int theId,"
78 EOL" in vec3 theNormal,"
79 EOL" in vec3 theView,"
80 EOL" in vec3 thePoint,"
81 EOL" in bool theIsFront)"
82 EOL"{"
83 EOL" vec3 aLight = occLight_Position (theId).xyz;"
84 EOL" if (occLight_IsHeadlight (theId) == 0)"
85 EOL" {"
5f4bd4d4 86 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
8625ef7e 87 EOL" }"
88 EOL" aLight -= thePoint;"
89 EOL
90 EOL" float aDist = length (aLight);"
91 EOL" aLight = aLight * (1.0 / aDist);"
92 EOL
93 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
94 EOL" + occLight_LinearAttenuation (theId) * aDist);"
95 EOL
96 EOL" vec3 aHalf = normalize (aLight + theView);"
97 EOL
98 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
99 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
100 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
101 EOL
102 EOL" float aSpecl = 0.0;"
103 EOL" if (aNdotL > 0.0)"
104 EOL" {"
105 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
106 EOL" }"
107 EOL
108 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
109 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
110 EOL"}";
111
112//! Function computes contribution of spotlight source
113const char THE_FUNC_spotLight[] =
114 EOL"void spotLight (in int theId,"
115 EOL" in vec3 theNormal,"
116 EOL" in vec3 theView,"
117 EOL" in vec3 thePoint,"
118 EOL" in bool theIsFront)"
119 EOL"{"
120 EOL" vec3 aLight = occLight_Position (theId).xyz;"
121 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
122 EOL" if (occLight_IsHeadlight (theId) == 0)"
123 EOL" {"
5f4bd4d4 124 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
125 EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
8625ef7e 126 EOL" }"
127 EOL" aLight -= thePoint;"
128 EOL
129 EOL" float aDist = length (aLight);"
130 EOL" aLight = aLight * (1.0 / aDist);"
131 EOL
132 EOL" aSpotDir = normalize (aSpotDir);"
133 // light cone
134 EOL" float aCosA = dot (aSpotDir, -aLight);"
135 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
136 EOL" {"
137 EOL" return;"
138 EOL" }"
139 EOL
140 EOL" float anExponent = occLight_SpotExponent (theId);"
141 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
142 EOL" + occLight_LinearAttenuation (theId) * aDist);"
143 EOL" if (anExponent > 0.0)"
144 EOL" {"
145 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
146 EOL" }"
147 EOL
148 EOL" vec3 aHalf = normalize (aLight + theView);"
149 EOL
150 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
151 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
152 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
153 EOL
154 EOL" float aSpecl = 0.0;"
155 EOL" if (aNdotL > 0.0)"
156 EOL" {"
157 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
158 EOL" }"
159 EOL
160 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
161 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
162 EOL"}";
163
164//! Function computes contribution of directional light source
165const char THE_FUNC_directionalLight[] =
166 EOL"void directionalLight (in int theId,"
167 EOL" in vec3 theNormal,"
168 EOL" in vec3 theView,"
169 EOL" in bool theIsFront)"
170 EOL"{"
171 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
172 EOL" if (occLight_IsHeadlight (theId) == 0)"
173 EOL" {"
5f4bd4d4 174 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
8625ef7e 175 EOL" }"
176 EOL
177 EOL" vec3 aHalf = normalize (aLight + theView);"
178 EOL
179 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
180 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
181 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
182 EOL
183 EOL" float aSpecl = 0.0;"
184 EOL" if (aNdotL > 0.0)"
185 EOL" {"
186 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
187 EOL" }"
188 EOL
189 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
190 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
191 EOL"}";
192
f68acbf4 193//! The same as THE_FUNC_directionalLight but for the light with zero index
194//! (avoids limitations on some mobile devices).
195const char THE_FUNC_directionalLightFirst[] =
196 EOL"void directionalLightFirst (in vec3 theNormal,"
197 EOL" in vec3 theView,"
198 EOL" in bool theIsFront)"
199 EOL"{"
200 EOL" vec3 aLight = normalize (occLightSources[1].xyz);"
201 EOL" if (occLight_IsHeadlight (0) == 0)"
202 EOL" {"
5f4bd4d4 203 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
f68acbf4 204 EOL" }"
205 EOL
206 EOL" vec3 aHalf = normalize (aLight + theView);"
207 EOL
208 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
209 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
210 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
211 EOL
212 EOL" float aSpecl = 0.0;"
213 EOL" if (aNdotL > 0.0)"
214 EOL" {"
215 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
216 EOL" }"
217 EOL
218 EOL" Diffuse += occLightSources[0].rgb * aNdotL;"
219 EOL" Specular += occLightSources[0].rgb * aSpecl;"
220 EOL"}";
221
8625ef7e 222//! Process clipping planes in Fragment Shader.
223//! Should be added at the beginning of the main() function.
1a7ece8f 224const char THE_FRAG_CLIP_PLANES_N[] =
8625ef7e 225 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
226 EOL" {"
227 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
89a929ea 228 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
8625ef7e 229 EOL" {"
89a929ea 230 EOL" discard;"
8625ef7e 231 EOL" }"
232 EOL" }";
233
1a7ece8f 234//! Process 1 clipping plane in Fragment Shader.
235const char THE_FRAG_CLIP_PLANES_1[] =
236 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
237 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
238 EOL" {"
239 EOL" discard;"
240 EOL" }";
241
242//! Process 2 clipping planes in Fragment Shader.
243const char THE_FRAG_CLIP_PLANES_2[] =
244 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
245 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
246 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
247 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
248 EOL" {"
249 EOL" discard;"
250 EOL" }";
251
8625ef7e 252}
253
30f0ad28 254// =======================================================================
255// function : OpenGl_ShaderManager
256// purpose : Creates new empty shader manager
257// =======================================================================
258OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
c357e426 259: myShadingModel (Graphic3d_TOSM_VERTEX),
8625ef7e 260 myContext (theContext),
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
275// =======================================================================
05e2200b 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
294// =======================================================================
30f0ad28 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
386// =======================================================================
256f9ac0 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
422// =======================================================================
30f0ad28 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
473// =======================================================================
30f0ad28 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,
4fe9ad57 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
3202bf1e 770 const GLint aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), THE_MAX_CLIP_PLANES);
771 theProgram->SetUniform (myContext,
772 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
773 aNbPlanes);
774 if (aNbPlanes < 1)
12381341 775 {
776 return;
777 }
778
89a929ea 779 OpenGl_Vec4 anEquations[THE_MAX_CLIP_PLANES];
12381341 780 GLuint aPlaneId = 0;
3202bf1e 781 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
12381341 782 {
3202bf1e 783 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
784 if (aPlaneIter.IsDisabled())
30f0ad28 785 {
12381341 786 continue;
30f0ad28 787 }
89a929ea 788 else if (aPlaneId >= THE_MAX_CLIP_PLANES)
789 {
790 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
791 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
792 "Warning: clipping planes limit (8) has been exceeded.");
793 break;
794 }
30f0ad28 795
12381341 796 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
797 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
798 (float) anEquation.y(),
799 (float) anEquation.z(),
800 (float) anEquation.w());
12381341 801 ++aPlaneId;
30f0ad28 802 }
5495fa7e 803
89a929ea 804 theProgram->SetUniform (myContext, aLocEquations, THE_MAX_CLIP_PLANES, anEquations);
30f0ad28 805}
806
807// =======================================================================
e135a155 808// function : PushState
30f0ad28 809// purpose : Pushes state of OCCT graphics parameters to the program
810// =======================================================================
811void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
812{
813 PushClippingState (theProgram);
30f0ad28 814 PushWorldViewState (theProgram);
815 PushModelWorldState (theProgram);
05e2200b 816 PushProjectionState (theProgram);
30f0ad28 817 PushLightSourceState (theProgram);
12381341 818}
8625ef7e 819
820// =======================================================================
821// function : prepareStdProgramFont
822// purpose :
823// =======================================================================
824Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
825{
826 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
b990e557 827 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
79f4f036 828 + EOL"THE_SHADER_OUT vec2 TexCoord;"
829 EOL"void main()"
b990e557 830 EOL"{"
831 EOL" TexCoord = occTexCoord.st;"
832 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
833 EOL"}";
834
4e1523ef 835 TCollection_AsciiString
836 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
837#if !defined(GL_ES_VERSION_2_0)
838 if (myContext->core11 == NULL)
839 {
840 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
841 }
842#endif
843
b990e557 844 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
79f4f036 845 + EOL"THE_SHADER_IN vec2 TexCoord;"
4e1523ef 846 + aSrcGetAlpha
847 + EOL"void main()"
b990e557 848 EOL"{"
849 EOL" vec4 aColor = occColor;"
850 EOL" aColor.a *= getAlpha();"
851 EOL" if (aColor.a <= 0.285) discard;"
4e1523ef 852 EOL" occFragColor = aColor;"
b990e557 853 EOL"}";
8625ef7e 854
4e1523ef 855#if !defined(GL_ES_VERSION_2_0)
856 if (myContext->core32 != NULL)
857 {
858 aProgramSrc->SetHeader ("#version 150");
859 }
860#endif
8625ef7e 861 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
862 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
863 TCollection_AsciiString aKey;
864 if (!Create (aProgramSrc, aKey, myFontProgram))
865 {
866 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
867 return Standard_False;
868 }
869 return Standard_True;
870}
871
872// =======================================================================
b86bb3df 873// function : prepareStdProgramFboBlit
874// purpose :
875// =======================================================================
876Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
877{
878 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
879 TCollection_AsciiString aSrcVert =
880 EOL"THE_SHADER_OUT vec2 TexCoord;"
881 EOL"void main()"
882 EOL"{"
883 EOL" TexCoord = occVertex.zw;"
884 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
885 EOL"}";
886
887 TCollection_AsciiString aSrcFrag =
888 EOL"uniform sampler2D uColorSampler;"
889 EOL"uniform sampler2D uDepthSampler;"
890 EOL
891 EOL"THE_SHADER_IN vec2 TexCoord;"
892 EOL
893 EOL"void main()"
894 EOL"{"
895 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
896 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
897 EOL"}";
898
899#if defined(GL_ES_VERSION_2_0)
900 if (myContext->IsGlGreaterEqual (3, 0))
901 {
902 aProgramSrc->SetHeader ("#version 300 es");
903 }
1ce0716b 904 else if (myContext->extFragDepth)
905 {
906 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
907 EOL"#define gl_FragDepth gl_FragDepthEXT");
908 }
b86bb3df 909 else
910 {
911 // there is no way to draw into depth buffer
912 aSrcFrag =
913 EOL"uniform sampler2D uColorSampler;"
914 EOL
915 EOL"THE_SHADER_IN vec2 TexCoord;"
916 EOL
917 EOL"void main()"
918 EOL"{"
919 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
920 EOL"}";
921 }
4e1523ef 922#else
923 if (myContext->core32 != NULL)
924 {
925 aProgramSrc->SetHeader ("#version 150");
926 }
b86bb3df 927#endif
b86bb3df 928 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
929 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
930 TCollection_AsciiString aKey;
931 if (!Create (aProgramSrc, aKey, myBlitProgram))
932 {
933 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
934 return Standard_False;
935 }
936
937 myContext->BindProgram (myBlitProgram);
938 myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
939 myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
940 myContext->BindProgram (NULL);
941 return Standard_True;
942}
943
944// =======================================================================
299e0ab9 945// function : pointSpriteAlphaSrc
946// purpose :
947// =======================================================================
fd59283a 948TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
299e0ab9 949{
fd59283a 950 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").a; }";
299e0ab9 951#if !defined(GL_ES_VERSION_2_0)
fd59283a 952 if (myContext->core11 == NULL
953 && (theBits & OpenGl_PO_TextureA) != 0)
299e0ab9 954 {
fd59283a 955 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").r; }";
299e0ab9 956 }
fd59283a 957#else
958 (void )theBits;
299e0ab9 959#endif
299e0ab9 960 return aSrcGetAlpha;
961}
962
963namespace
964{
965
966 // =======================================================================
967 // function : textureUsed
968 // purpose :
969 // =======================================================================
970 static bool textureUsed (const Standard_Integer theBits)
971 {
972 return (theBits & OpenGl_PO_TextureA) != 0 || (theBits & OpenGl_PO_TextureRGB) != 0;
973 }
974
975}
976
977// =======================================================================
8625ef7e 978// function : prepareStdProgramFlat
979// purpose :
980// =======================================================================
981Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
982 const Standard_Integer theBits)
983{
984 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
299e0ab9 985 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
8625ef7e 986 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
4e1523ef 987 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
8625ef7e 988 if ((theBits & OpenGl_PO_Point) != 0)
989 {
990 #if defined(GL_ES_VERSION_2_0)
991 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
992 #endif
8625ef7e 993
299e0ab9 994 if ((theBits & OpenGl_PO_TextureRGB) != 0)
8625ef7e 995 {
996 aSrcFragGetColor =
fd59283a 997 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord "); }";
8625ef7e 998 }
299e0ab9 999
fd59283a 1000 if (textureUsed (theBits))
1001 {
1002 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1003
1004 #if !defined(GL_ES_VERSION_2_0)
1005 if (myContext->core11 != NULL
1006 && myContext->IsGlGreaterEqual (2, 1))
1007 {
1008 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1009 }
1010 #endif
1011
1012 aSrcFragMainGetColor =
1013 EOL" vec4 aColor = getColor();"
1014 EOL" aColor.a = getAlpha();"
1015 EOL" if (aColor.a <= 0.1) discard;"
1016 EOL" occFragColor = aColor;";
1017 }
1018 else
1019 {
1020 aSrcFragMainGetColor =
1021 EOL" vec4 aColor = getColor();"
1022 EOL" if (aColor.a <= 0.1) discard;"
1023 EOL" occFragColor = aColor;";
1024 }
8625ef7e 1025 }
6c6aadb1 1026 else
1027 {
1028 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1029 {
4e1523ef 1030 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1031 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1032 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1033
1034 aSrcFragGetColor =
79f4f036 1035 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w); }";
6c6aadb1 1036 }
e135a155 1037 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1038 {
1039 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1040 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1041
1042 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1043
1044 aSrcVertExtraMain +=
1045 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1046 EOL" vec3 aNormal = transformNormal (occNormal);"
1047 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1048 EOL" aReflect.z += 1.0;"
b872ca56 1049 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
e135a155 1050
1051 aSrcFragGetColor =
1052 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1053 }
6c6aadb1 1054 }
8625ef7e 1055 if ((theBits & OpenGl_PO_VertColor) != 0)
1056 {
4e1523ef 1057 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
8625ef7e 1058 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
4e1523ef 1059 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
8625ef7e 1060 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1061 }
1a7ece8f 1062 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1063 {
4e1523ef 1064 aSrcVertExtraOut +=
1065 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1066 EOL"THE_SHADER_OUT vec4 Position;";
1067 aSrcFragExtraOut +=
1068 EOL"THE_SHADER_IN vec4 PositionWorld;"
1069 EOL"THE_SHADER_IN vec4 Position;";
8625ef7e 1070 aSrcVertExtraMain +=
1071 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1072 EOL" Position = occWorldViewMatrix * PositionWorld;";
1a7ece8f 1073
1074 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1075 {
1076 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1077 }
1078 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1079 {
1080 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1081 }
1082 else
1083 {
1084 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1085 }
8625ef7e 1086 }
1087
ac116c22 1088 TCollection_AsciiString aSrcVertEndMain;
1089 if ((theBits & OpenGl_PO_StippleLine) != 0)
1090 {
959a265a 1091 bool hasGlslBitOps = false;
ac116c22 1092 #if defined(GL_ES_VERSION_2_0)
1093 if (myContext->IsGlGreaterEqual (3, 0))
1094 {
1095 aProgramSrc->SetHeader ("#version 300 es");
959a265a 1096 hasGlslBitOps = true;
ac116c22 1097 }
1098 #else
959a265a 1099 if (myContext->IsGlGreaterEqual (3, 0))
1100 {
1101 aProgramSrc->SetHeader ("#version 130");
1102 hasGlslBitOps = true;
1103 }
1104 else if(myContext->CheckExtension("GL_EXT_gpu_shader4"))
ac116c22 1105 {
959a265a 1106 aProgramSrc->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1107 hasGlslBitOps = true;
ac116c22 1108 }
1109 #endif
1110
959a265a 1111 if (hasGlslBitOps)
ac116c22 1112 {
1113 aSrcVertExtraOut +=
1114 EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1115 aSrcFragExtraOut +=
1116 EOL"THE_SHADER_IN vec2 ScreenSpaceCoord;"
1117 EOL"uniform int uPattern;"
1118 EOL"uniform float uFactor;";
1119 aSrcVertEndMain =
1120 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1121 aSrcFragMainGetColor =
1122 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1123 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1124 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1125 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1126 EOL" vec4 aColor = getColor();"
1127 EOL" if (aColor.a <= 0.1) discard;"
1128 EOL" occFragColor = aColor;";
1129 }
1130 else
1131 {
1132 const TCollection_ExtendedString aWarnMessage =
1133 "Warning: stipple lines in GLSL will be ignored.";
3b523c4c 1134 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1135 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
ac116c22 1136 }
1137 }
1138
8625ef7e 1139 aSrcVert =
e135a155 1140 aSrcVertExtraFunc
1141 + aSrcVertExtraOut
8625ef7e 1142 + EOL"void main()"
1143 EOL"{"
1144 + aSrcVertExtraMain
1145 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
ac116c22 1146 + aSrcVertEndMain
1147 + EOL"}";
8625ef7e 1148
1149 aSrcFrag =
1150 aSrcFragExtraOut
1151 + aSrcFragGetColor
299e0ab9 1152 + aSrcGetAlpha
8625ef7e 1153 + EOL"void main()"
1154 EOL"{"
1155 + aSrcFragExtraMain
1156 + aSrcFragMainGetColor
1157 + EOL"}";
1158
4e1523ef 1159#if !defined(GL_ES_VERSION_2_0)
1160 if (myContext->core32 != NULL)
1161 {
1162 aProgramSrc->SetHeader ("#version 150");
1163 }
1164#endif
8625ef7e 1165 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1166 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1167
1168 TCollection_AsciiString aKey;
1169 if (!Create (aProgramSrc, aKey, theProgram))
1170 {
1171 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1172 return Standard_False;
1173 }
1174 return Standard_True;
1175}
1176
1177// =======================================================================
299e0ab9 1178// function : pointSpriteShadingSrc
1179// purpose :
1180// =======================================================================
1181TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc,
1182 const Standard_Integer theBits)
1183{
1184 TCollection_AsciiString aSrcFragGetColor;
1185 if ((theBits & OpenGl_PO_TextureA) != 0)
1186 {
fd59283a 1187 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
299e0ab9 1188 EOL"vec4 getColor(void)"
1189 EOL"{"
1190 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1191 EOL" aColor.a = getAlpha();"
1192 EOL" if (aColor.a <= 0.1) discard;"
1193 EOL" return aColor;"
1194 EOL"}";
1195 }
1196 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1197 {
1198 aSrcFragGetColor = TCollection_AsciiString() +
1199 EOL"vec4 getColor(void)"
1200 EOL"{"
1201 EOL" vec4 aColor = " + theBaseColorSrc + ";"
fd59283a 1202 EOL" aColor = occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ") * aColor;"
299e0ab9 1203 EOL" if (aColor.a <= 0.1) discard;"
1204 EOL" return aColor;"
1205 EOL"}";
1206 }
1207
1208 return aSrcFragGetColor;
1209}
1210
1211// =======================================================================
256f9ac0 1212// function : stdComputeLighting
1213// purpose :
1214// =======================================================================
abdf0b10 1215TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
256f9ac0 1216{
f68acbf4 1217 Standard_Integer aLightsMap[Graphic3d_TOLS_SPOT + 1] = { 0, 0, 0, 0 };
256f9ac0 1218 TCollection_AsciiString aLightsFunc, aLightsLoop;
1219 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1220 if (aLights != NULL)
1221 {
1222 Standard_Integer anIndex = 0;
1223 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1224 {
1225 switch (aLightIter.Value().Type)
1226 {
c357e426 1227 case Graphic3d_TOLS_AMBIENT:
256f9ac0 1228 --anIndex;
1229 break; // skip ambient
c357e426 1230 case Graphic3d_TOLS_DIRECTIONAL:
256f9ac0 1231 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1232 break;
c357e426 1233 case Graphic3d_TOLS_POSITIONAL:
256f9ac0 1234 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1235 break;
c357e426 1236 case Graphic3d_TOLS_SPOT:
256f9ac0 1237 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1238 break;
1239 }
f68acbf4 1240 aLightsMap[aLightIter.Value().Type] += 1;
1241 }
1242 const Standard_Integer aNbLoopLights = aLightsMap[Graphic3d_TOLS_DIRECTIONAL]
1243 + aLightsMap[Graphic3d_TOLS_POSITIONAL]
1244 + aLightsMap[Graphic3d_TOLS_SPOT];
1245 if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] == 1
1246 && aNbLoopLights == 1)
1247 {
1248 // use the version with hard-coded first index
1249 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
1250 aLightsFunc += THE_FUNC_directionalLightFirst;
1251 }
1252 else if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] > 0)
1253 {
1254 aLightsFunc += THE_FUNC_directionalLight;
1255 }
1256 if (aLightsMap[Graphic3d_TOLS_POSITIONAL] > 0)
1257 {
1258 aLightsFunc += THE_FUNC_pointLight;
1259 }
1260 if (aLightsMap[Graphic3d_TOLS_SPOT] > 0)
1261 {
1262 aLightsFunc += THE_FUNC_spotLight;
256f9ac0 1263 }
1264 }
1265
abdf0b10 1266 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1267 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1268 if (theHasVertColor)
1269 {
1270 aGetMatAmbient = "getVertColor();";
1271 aGetMatDiffuse = "getVertColor();";
1272 }
1273
256f9ac0 1274 return TCollection_AsciiString()
1275 + THE_FUNC_lightDef
1276 + aLightsFunc
1277 + EOL
1278 EOL"vec4 computeLighting (in vec3 theNormal,"
1279 EOL" in vec3 theView,"
1280 EOL" in vec4 thePoint,"
1281 EOL" in bool theIsFront)"
1282 EOL"{"
1283 EOL" Ambient = occLightAmbient.rgb;"
1284 EOL" Diffuse = vec3 (0.0);"
1285 EOL" Specular = vec3 (0.0);"
1286 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1287 + aLightsLoop
363bc51b 1288 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
1289 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
1290 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1291 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1292 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
1293 EOL" + Diffuse * aMatDiffuse.rgb"
1294 EOL" + Specular * aMatSpecular.rgb"
1295 EOL" + aMatEmission.rgb;"
1296 EOL" return vec4 (aColor, aMatDiffuse.a);"
256f9ac0 1297 EOL"}";
1298}
1299
1300// =======================================================================
8625ef7e 1301// function : prepareStdProgramGouraud
1302// purpose :
1303// =======================================================================
1304Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1305 const Standard_Integer theBits)
1306{
1307 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
abdf0b10 1308 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
6c6aadb1 1309 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
8625ef7e 1310 if ((theBits & OpenGl_PO_Point) != 0)
1311 {
1312 #if defined(GL_ES_VERSION_2_0)
1313 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1314 #endif
299e0ab9 1315
1316 if (textureUsed (theBits))
6c6aadb1 1317 {
299e0ab9 1318 #if !defined(GL_ES_VERSION_2_0)
1319 if (myContext->core11 != NULL
1320 && myContext->IsGlGreaterEqual (2, 1))
1321 {
1322 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1323 }
1324 #endif
1325
1326 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
6c6aadb1 1327 }
1328 }
1329 else
1330 {
1331 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1332 {
4e1523ef 1333 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1334 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1335 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1336
1337 aSrcFragGetColor =
1338 EOL"vec4 getColor(void)"
1339 EOL"{"
1340 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
79f4f036 1341 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1342 EOL"}";
1343 }
1344 }
299e0ab9 1345
1346 if ((theBits & OpenGl_PO_VertColor) != 0)
1347 {
1348 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1349 }
1350
1a7ece8f 1351 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1352 {
4e1523ef 1353 aSrcVertExtraOut +=
1354 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1355 EOL"THE_SHADER_OUT vec4 Position;";
1356 aSrcFragExtraOut +=
1357 EOL"THE_SHADER_IN vec4 PositionWorld;"
1358 EOL"THE_SHADER_IN vec4 Position;";
8625ef7e 1359 aSrcVertExtraMain +=
1360 EOL" PositionWorld = aPositionWorld;"
1361 EOL" Position = aPosition;";
1a7ece8f 1362
1363 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1364 {
1365 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1366 }
1367 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1368 {
1369 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1370 }
1371 else
1372 {
1373 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1374 }
8625ef7e 1375 }
1376
abdf0b10 1377 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1378 aSrcVert = TCollection_AsciiString()
1379 + THE_FUNC_transformNormal
1380 + EOL
abdf0b10 1381 + aSrcVertColor
256f9ac0 1382 + aLights
8625ef7e 1383 + EOL
4e1523ef 1384 EOL"THE_SHADER_OUT vec4 FrontColor;"
1385 EOL"THE_SHADER_OUT vec4 BackColor;"
8625ef7e 1386 EOL
1387 + aSrcVertExtraOut
1388 + EOL"void main()"
1389 EOL"{"
1390 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1391 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1392 EOL" vec3 aNormal = transformNormal (occNormal);"
1393 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1394 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1395 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1396 + aSrcVertExtraMain
1397 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1398 EOL"}";
1399
1400 aSrcFrag = TCollection_AsciiString()
4e1523ef 1401 + EOL"THE_SHADER_IN vec4 FrontColor;"
1402 EOL"THE_SHADER_IN vec4 BackColor;"
8625ef7e 1403 + aSrcFragExtraOut
6c6aadb1 1404 + aSrcFragGetColor
8625ef7e 1405 + EOL"void main()"
1406 EOL"{"
1407 + aSrcFragExtraMain
4e1523ef 1408 + EOL" occFragColor = getColor();"
8625ef7e 1409 EOL"}";
1410
4e1523ef 1411#if !defined(GL_ES_VERSION_2_0)
1412 if (myContext->core32 != NULL)
1413 {
1414 aProgramSrc->SetHeader ("#version 150");
1415 }
1416#endif
8625ef7e 1417 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1418 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1419 TCollection_AsciiString aKey;
1420 if (!Create (aProgramSrc, aKey, theProgram))
1421 {
1422 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1423 return Standard_False;
1424 }
1425 return Standard_True;
1426}
1427
1428// =======================================================================
1429// function : prepareStdProgramPhong
1430// purpose :
1431// =======================================================================
1432Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1433 const Standard_Integer theBits)
1434{
6c6aadb1 1435 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1436
8625ef7e 1437 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
6c6aadb1 1438 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1439 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
8625ef7e 1440 if ((theBits & OpenGl_PO_Point) != 0)
1441 {
1442 #if defined(GL_ES_VERSION_2_0)
1443 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1444 #endif
6c6aadb1 1445
299e0ab9 1446 if (textureUsed (theBits))
6c6aadb1 1447 {
299e0ab9 1448 #if !defined(GL_ES_VERSION_2_0)
1449 if (myContext->core11 != NULL
1450 && myContext->IsGlGreaterEqual (2, 1))
1451 {
1452 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1453 }
1454 #endif
1455
1456 aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
6c6aadb1 1457 }
1458 }
1459 else
1460 {
1461 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1462 {
4e1523ef 1463 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1464 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1465 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1466
1467 aSrcFragGetColor =
1468 EOL"vec4 getColor(void)"
1469 EOL"{"
1470 EOL" vec4 aColor = " thePhongCompLight ";"
79f4f036 1471 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1472 EOL"}";
1473 }
1474 }
1475
299e0ab9 1476 if ((theBits & OpenGl_PO_VertColor) != 0)
1477 {
1478 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1479 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1480 aSrcFragGetVertColor = EOL"THE_SHADER_IN vec4 VertColor;"
1481 EOL"vec4 getVertColor(void) { return VertColor; }";
1482 }
1483
1a7ece8f 1484 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1485 {
1a7ece8f 1486 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1487 {
1488 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1489 }
1490 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1491 {
1492 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1493 }
1494 else
1495 {
1496 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1497 }
8625ef7e 1498 }
1499
1500 aSrcVert = TCollection_AsciiString()
1501 + THE_FUNC_transformNormal
1502 + EOL
4e1523ef 1503 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1504 EOL"THE_SHADER_OUT vec4 Position;"
1505 EOL"THE_SHADER_OUT vec3 Normal;"
1506 EOL"THE_SHADER_OUT vec3 View;"
8625ef7e 1507 EOL
1508 + aSrcVertExtraOut
1509 + EOL"void main()"
1510 EOL"{"
1511 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1512 EOL" Position = occWorldViewMatrix * PositionWorld;"
1513 EOL" Normal = transformNormal (occNormal);"
1514 EOL" View = vec3 (0.0, 0.0, 1.0);"
1515 + aSrcVertExtraMain
1516 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1517 EOL"}";
1518
abdf0b10 1519 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1520 aSrcFrag = TCollection_AsciiString()
4e1523ef 1521 + EOL"THE_SHADER_IN vec4 PositionWorld;"
1522 EOL"THE_SHADER_IN vec4 Position;"
1523 EOL"THE_SHADER_IN vec3 Normal;"
1524 EOL"THE_SHADER_IN vec3 View;"
8625ef7e 1525 + EOL
6c6aadb1 1526 + aSrcFragExtraOut
1527 + aSrcFragGetVertColor
256f9ac0 1528 + aLights
6c6aadb1 1529 + aSrcFragGetColor
8625ef7e 1530 + EOL
1531 EOL"void main()"
1532 EOL"{"
1533 + aSrcFragExtraMain
4e1523ef 1534 + EOL" occFragColor = getColor();"
8625ef7e 1535 EOL"}";
1536
4e1523ef 1537#if !defined(GL_ES_VERSION_2_0)
1538 if (myContext->core32 != NULL)
1539 {
1540 aProgramSrc->SetHeader ("#version 150");
1541 }
1542#endif
8625ef7e 1543 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1544 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1545 TCollection_AsciiString aKey;
1546 if (!Create (aProgramSrc, aKey, theProgram))
1547 {
1548 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1549 return Standard_False;
1550 }
1551 return Standard_True;
1552}
1553
1554// =======================================================================
f978241f 1555// function : prepareStdProgramStereo
38a0206f 1556// purpose :
1557// =======================================================================
f978241f 1558Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1559 const Graphic3d_StereoMode theStereoMode)
38a0206f 1560{
1561 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1562 TCollection_AsciiString aSrcVert =
1563 EOL"THE_SHADER_OUT vec2 TexCoord;"
1564 EOL"void main()"
1565 EOL"{"
1566 EOL" TexCoord = occVertex.zw;"
1567 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1568 EOL"}";
1569
f978241f 1570 TCollection_AsciiString aSrcFrag;
1571 switch (theStereoMode)
1572 {
1573 case Graphic3d_StereoMode_Anaglyph:
1574 {
1575 aSrcFrag =
1576 EOL"uniform sampler2D uLeftSampler;"
1577 EOL"uniform sampler2D uRightSampler;"
1578 EOL
1579 EOL"uniform mat4 uMultL;"
1580 EOL"uniform mat4 uMultR;"
1581 EOL
0deb6f04 1582 EOL"const vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
1583 EOL"const vec4 THE_POW_DOWN = 1.0 / vec4 (2.2, 2.2, 2.2, 1.0);"
f978241f 1584 EOL
1585 EOL"THE_SHADER_IN vec2 TexCoord;"
1586 EOL
1587 EOL"void main()"
1588 EOL"{"
1589 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1590 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1591 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
1592 EOL" aColorR = pow (aColorR, THE_POW_UP);"
1593 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
1594 EOL" occFragColor = pow (aColor, THE_POW_DOWN);"
1595 EOL"}";
1596 break;
1597 }
1598 case Graphic3d_StereoMode_RowInterlaced:
1599 {
1600 aSrcFrag =
1601 EOL"uniform sampler2D uLeftSampler;"
1602 EOL"uniform sampler2D uRightSampler;"
1603 EOL
1604 EOL"THE_SHADER_IN vec2 TexCoord;"
1605 EOL
1606 EOL"void main()"
1607 EOL"{"
1608 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1609 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 1610 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
f978241f 1611 EOL" {"
1612 EOL" occFragColor = aColorL;"
1613 EOL" }"
1614 EOL" else"
1615 EOL" {"
1616 EOL" occFragColor = aColorR;"
1617 EOL" }"
1618 EOL"}";
1619 break;
1620 }
1621 case Graphic3d_StereoMode_ColumnInterlaced:
1622 {
1623 aSrcFrag =
1624 EOL"uniform sampler2D uLeftSampler;"
1625 EOL"uniform sampler2D uRightSampler;"
1626 EOL
1627 EOL"THE_SHADER_IN vec2 TexCoord;"
1628 EOL
1629 EOL"void main()"
1630 EOL"{"
1631 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1632 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 1633 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
f978241f 1634 EOL" {"
1635 EOL" occFragColor = aColorL;"
1636 EOL" }"
1637 EOL" else"
1638 EOL" {"
1639 EOL" occFragColor = aColorR;"
1640 EOL" }"
1641 EOL"}";
1642 break;
1643 }
1644 case Graphic3d_StereoMode_ChessBoard:
1645 {
1646 aSrcFrag =
1647 EOL"uniform sampler2D uLeftSampler;"
1648 EOL"uniform sampler2D uRightSampler;"
1649 EOL
1650 EOL"THE_SHADER_IN vec2 TexCoord;"
1651 EOL
1652 EOL"void main()"
1653 EOL"{"
1654 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1655 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 1656 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
1657 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
f978241f 1658 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
1659 EOL" {"
1660 EOL" occFragColor = aColorL;"
1661 EOL" }"
1662 EOL" else"
1663 EOL" {"
1664 EOL" occFragColor = aColorR;"
1665 EOL" }"
1666 EOL"}";
1667 break;
1668 }
1669 case Graphic3d_StereoMode_SideBySide:
1670 {
1671 aSrcFrag =
1672 EOL"uniform sampler2D uLeftSampler;"
1673 EOL"uniform sampler2D uRightSampler;"
1674 EOL
1675 EOL"THE_SHADER_IN vec2 TexCoord;"
1676 EOL
1677 EOL"void main()"
1678 EOL"{"
1679 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
1680 EOL" if (TexCoord.x > 0.5)"
1681 EOL" {"
1682 EOL" aTexCoord.x -= 1.0;"
1683 EOL" }"
1684 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1685 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1686 EOL" if (TexCoord.x <= 0.5)"
1687 EOL" {"
1688 EOL" occFragColor = aColorL;"
1689 EOL" }"
1690 EOL" else"
1691 EOL" {"
1692 EOL" occFragColor = aColorR;"
1693 EOL" }"
1694 EOL"}";
1695 break;
1696 }
1697 case Graphic3d_StereoMode_OverUnder:
1698 {
1699 aSrcFrag =
1700 EOL"uniform sampler2D uLeftSampler;"
1701 EOL"uniform sampler2D uRightSampler;"
1702 EOL
1703 EOL"THE_SHADER_IN vec2 TexCoord;"
1704 EOL
1705 EOL"void main()"
1706 EOL"{"
1707 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
1708 EOL" if (TexCoord.y > 0.5)"
1709 EOL" {"
1710 EOL" aTexCoord.y -= 1.0;"
1711 EOL" }"
1712 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1713 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1714 EOL" if (TexCoord.y <= 0.5)"
1715 EOL" {"
1716 EOL" occFragColor = aColorL;"
1717 EOL" }"
1718 EOL" else"
1719 EOL" {"
1720 EOL" occFragColor = aColorR;"
1721 EOL" }"
1722 EOL"}";
1723 break;
1724 }
1725 case Graphic3d_StereoMode_QuadBuffer:
1726 case Graphic3d_StereoMode_SoftPageFlip:
1727 default:
1728 {
1729 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
1730 if (!aProgram.IsNull())
1731 {
1732 return aProgram->IsValid();
1733 }*/
1734 aSrcFrag =
1735 EOL"uniform sampler2D uLeftSampler;"
1736 EOL"uniform sampler2D uRightSampler;"
1737 EOL
1738 EOL"THE_SHADER_IN vec2 TexCoord;"
1739 EOL
1740 EOL"void main()"
1741 EOL"{"
1742 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1743 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1744 EOL" aColorL.b = 0.0;"
1745 EOL" aColorL.g = 0.0;"
1746 EOL" aColorR.r = 0.0;"
1747 EOL" occFragColor = aColorL + aColorR;"
1748 EOL"}";
1749 break;
1750 }
1751 }
38a0206f 1752
1753#if !defined(GL_ES_VERSION_2_0)
1754 if (myContext->core32 != NULL)
1755 {
1756 aProgramSrc->SetHeader ("#version 150");
1757 }
1758#endif
1759
1760 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1761 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1762 TCollection_AsciiString aKey;
f978241f 1763 if (!Create (aProgramSrc, aKey, theProgram))
38a0206f 1764 {
f978241f 1765 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
38a0206f 1766 return Standard_False;
1767 }
1768
f978241f 1769 myContext->BindProgram (theProgram);
1770 theProgram->SetSampler (myContext, "uLeftSampler", 0);
1771 theProgram->SetSampler (myContext, "uRightSampler", 1);
38a0206f 1772 myContext->BindProgram (NULL);
1773 return Standard_True;
1774}
1775
1776// =======================================================================
8625ef7e 1777// function : bindProgramWithState
1778// purpose :
1779// =======================================================================
299e0ab9 1780Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
8625ef7e 1781{
1782 if (!myContext->BindProgram (theProgram))
1783 {
1784 return Standard_False;
1785 }
1786 theProgram->ApplyVariables (myContext);
1787
8625ef7e 1788 PushState (theProgram);
1789 return Standard_True;
1790}