0028811: Visualization - merge texturing support into AIS_Shape class and get rid...
[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
a1073ae2 252//! Output color and coverage for accumulation by OIT algorithm.
253const char THE_FRAG_write_oit_buffers[] =
254 EOL" float aWeight = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);"
255 EOL" occFragCoverage.r = occFragColor.a * aWeight;"
256 EOL" occFragColor = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);";
257
8613985b 258#if !defined(GL_ES_VERSION_2_0)
259
260 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
261 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
262 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
263 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
264
265 //! Bind FFP light source.
266 static void bindLight (const OpenGl_Light& theLight,
267 const GLenum theLightGlId,
268 const OpenGl_Mat4& theModelView,
269 OpenGl_Context* theCtx)
270 {
271 // the light is a headlight?
272 if (theLight.IsHeadlight)
273 {
274 theCtx->core11->glMatrixMode (GL_MODELVIEW);
275 theCtx->core11->glLoadIdentity();
276 }
277
278 // setup light type
279 switch (theLight.Type)
280 {
281 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
282 case Graphic3d_TOLS_DIRECTIONAL:
283 {
284 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
285 const OpenGl_Vec4 anInfDir = -theLight.Direction;
286
287 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
288 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
289 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData());
290 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData());
291 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
292 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
293 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
294 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
295 break;
296 }
297 case Graphic3d_TOLS_POSITIONAL:
298 {
299 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
300 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position.x()), static_cast<float>(theLight.Position.y()), static_cast<float>(theLight.Position.z()), 1.0f);
301 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
302 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData());
303 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData());
304 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
305 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
306 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
307 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
308 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
309 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
310 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
311 break;
312 }
313 case Graphic3d_TOLS_SPOT:
314 {
315 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position.x()), static_cast<float>(theLight.Position.y()), static_cast<float>(theLight.Position.z()), 1.0f);
316 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
317 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData());
318 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData());
319 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
320 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.Direction.GetData());
321 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
322 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
323 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
324 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
325 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
326 break;
327 }
328 }
329
330 // restore matrix in case of headlight
331 if (theLight.IsHeadlight)
332 {
333 theCtx->core11->glLoadMatrixf (theModelView.GetData());
334 }
335
336 glEnable (theLightGlId);
337 }
338#endif
339
8625ef7e 340}
341
30f0ad28 342// =======================================================================
343// function : OpenGl_ShaderManager
344// purpose : Creates new empty shader manager
345// =======================================================================
346OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
8613985b 347: myFfpProgram (new OpenGl_ShaderProgramFFP()),
348 myShadingModel (Graphic3d_TOSM_VERTEX),
8625ef7e 349 myContext (theContext),
7c3ef2f7 350 myHasLocalOrigin (Standard_False),
e6804ff7 351 myLastView (NULL)
30f0ad28 352{
256f9ac0 353 //
30f0ad28 354}
355
356// =======================================================================
357// function : ~OpenGl_ShaderManager
358// purpose : Releases resources of shader manager
359// =======================================================================
360OpenGl_ShaderManager::~OpenGl_ShaderManager()
361{
362 myProgramList.Clear();
363}
364
05e2200b 365// =======================================================================
366// function : clear
367// purpose :
368// =======================================================================
369void OpenGl_ShaderManager::clear()
370{
371 myProgramList.Clear();
372 myLightPrograms.Nullify();
373 myFlatPrograms = OpenGl_SetOfShaderPrograms();
374 myMapOfLightPrograms.Clear();
375 myFontProgram.Nullify();
b86bb3df 376 myBlitProgram.Nullify();
f978241f 377 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
378 {
379 myStereoPrograms[aModeIter].Nullify();
380 }
05e2200b 381 switchLightPrograms();
382}
383
30f0ad28 384// =======================================================================
385// function : Create
386// purpose : Creates new shader program
387// =======================================================================
8625ef7e 388Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
389 TCollection_AsciiString& theShareKey,
390 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 391{
392ac980 392 theProgram.Nullify();
393 if (theProxy.IsNull())
30f0ad28 394 {
8625ef7e 395 return Standard_False;
30f0ad28 396 }
392ac980 397
398 theShareKey = theProxy->GetId();
399 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
400 {
05dd08ce 401 if (theProgram->Share())
402 {
403 myProgramList.Append (theProgram);
404 }
8625ef7e 405 return Standard_True;
392ac980 406 }
407
408 theProgram = new OpenGl_ShaderProgram (theProxy);
409 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
30f0ad28 410 {
392ac980 411 theProgram->Release (myContext);
412 theShareKey.Clear();
413 theProgram.Nullify();
8625ef7e 414 return Standard_False;
30f0ad28 415 }
30f0ad28 416
392ac980 417 myProgramList.Append (theProgram);
418 myContext->ShareResource (theShareKey, theProgram);
8625ef7e 419 return Standard_True;
30f0ad28 420}
421
422// =======================================================================
423// function : Unregister
424// purpose : Removes specified shader program from the manager
425// =======================================================================
392ac980 426void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
427 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 428{
429 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
430 {
431 if (anIt.Value() == theProgram)
432 {
392ac980 433 if (!theProgram->UnShare())
434 {
435 theShareKey.Clear();
436 theProgram.Nullify();
437 return;
438 }
439
30f0ad28 440 myProgramList.Remove (anIt);
441 break;
442 }
443 }
444
445 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
446 if (anID.IsEmpty())
447 {
448 myContext->DelayedRelease (theProgram);
449 theProgram.Nullify();
450 }
451 else
452 {
453 theProgram.Nullify();
05dd08ce 454 myContext->ReleaseResource (anID, Standard_True);
30f0ad28 455 }
456}
457
458// =======================================================================
459// function : ShaderPrograms
460// purpose : Returns list of registered shader programs
461// =======================================================================
462const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
463{
464 return myProgramList;
465}
466
467// =======================================================================
468// function : Empty
469// purpose : Returns true if no program objects are attached
470// =======================================================================
471Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
472{
473 return myProgramList.IsEmpty();
474}
475
256f9ac0 476// =======================================================================
477// function : switchLightPrograms
478// purpose :
479// =======================================================================
480void OpenGl_ShaderManager::switchLightPrograms()
481{
c357e426 482 TCollection_AsciiString aKey (myShadingModel == Graphic3d_TOSM_FRAGMENT ? "p_" : "g_");
256f9ac0 483 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
484 if (aLights != NULL)
485 {
486 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
487 {
488 switch (aLightIter.Value().Type)
489 {
c357e426 490 case Graphic3d_TOLS_AMBIENT:
256f9ac0 491 break; // skip ambient
c357e426 492 case Graphic3d_TOLS_DIRECTIONAL:
256f9ac0 493 aKey += "d";
494 break;
c357e426 495 case Graphic3d_TOLS_POSITIONAL:
256f9ac0 496 aKey += "p";
497 break;
c357e426 498 case Graphic3d_TOLS_SPOT:
256f9ac0 499 aKey += "s";
500 break;
501 }
502 }
503 }
504
505 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
506 {
507 myLightPrograms = new OpenGl_SetOfShaderPrograms();
508 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
509 }
510}
511
30f0ad28 512// =======================================================================
513// function : UpdateLightSourceStateTo
514// purpose : Updates state of OCCT light sources
515// =======================================================================
516void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
517{
518 myLightSourceState.Set (theLights);
519 myLightSourceState.Update();
256f9ac0 520 switchLightPrograms();
521}
522
7c3ef2f7 523// =======================================================================
524// function : UpdateLightSourceState
525// purpose :
526// =======================================================================
527void OpenGl_ShaderManager::UpdateLightSourceState()
528{
529 myLightSourceState.Update();
530}
531
256f9ac0 532// =======================================================================
533// function : SetShadingModel
534// purpose :
535// =======================================================================
c357e426 536void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
256f9ac0 537{
538 myShadingModel = theModel;
539 switchLightPrograms();
30f0ad28 540}
541
542// =======================================================================
543// function : SetProjectionState
544// purpose : Sets new state of OCCT projection transform
545// =======================================================================
c827ea3a 546void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
30f0ad28 547{
548 myProjectionState.Set (theProjectionMatrix);
549 myProjectionState.Update();
550}
551
552// =======================================================================
553// function : SetModelWorldState
554// purpose : Sets new state of OCCT model-world transform
555// =======================================================================
c827ea3a 556void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
30f0ad28 557{
558 myModelWorldState.Set (theModelWorldMatrix);
559 myModelWorldState.Update();
560}
561
562// =======================================================================
563// function : SetWorldViewState
564// purpose : Sets new state of OCCT world-view transform
565// =======================================================================
c827ea3a 566void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
30f0ad28 567{
568 myWorldViewState.Set (theWorldViewMatrix);
569 myWorldViewState.Update();
570}
571
30f0ad28 572// =======================================================================
573// function : PushLightSourceState
574// purpose : Pushes state of OCCT light sources to the program
575// =======================================================================
576void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
577{
8613985b 578 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE))
579 {
580 return;
581 }
582
583 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
584 if (theProgram == myFfpProgram)
30f0ad28 585 {
8613985b 586 #if !defined(GL_ES_VERSION_2_0)
587 if (myContext->core11 == NULL)
588 {
589 return;
590 }
591
592 if (myContext->core11 != NULL)
593 {
594 GLenum aLightGlId = GL_LIGHT0;
595 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
596 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
597 for (OpenGl_ListOfLight::Iterator aLightIt (*myLightSourceState.LightSources()); aLightIt.More(); aLightIt.Next())
598 {
599 const OpenGl_Light& aLight = aLightIt.Value();
600 if (aLight.Type == Graphic3d_TOLS_AMBIENT)
601 {
602 anAmbient += aLight.Color;
603 continue;
604 }
605 else if (aLightGlId > GL_LIGHT7) // OpenGLMaxLights - only 8 lights in OpenGL...
606 {
607 continue;
608 }
609
610 bindLight (aLightIt.Value(), aLightGlId, aModelView, myContext);
611 ++aLightGlId;
612 }
613
614 // apply accumulated ambient color
615 anAmbient.a() = 1.0f;
616 myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
617
618 // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
619 // therefore managing the state here does not have any effect - do it just for consistency.
620 if (aLightGlId != GL_LIGHT0)
621 {
622 ::glEnable (GL_LIGHTING);
623 }
624 else
625 {
626 ::glDisable (GL_LIGHTING);
627 }
628 // switch off unused lights
629 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
630 {
631 ::glDisable (aLightGlId);
632 }
633 }
634 #endif
30f0ad28 635 return;
636 }
30f0ad28 637
01eaf654 638 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
639 {
7c3ef2f7 640 myLightTypeArray[aLightIt].Type = -1;
01eaf654 641 }
642
12381341 643 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
644 if (aLightsDefNb < 1)
645 {
30f0ad28 646 theProgram->SetUniform (myContext,
12381341 647 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
648 0);
30f0ad28 649 theProgram->SetUniform (myContext,
12381341 650 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
651 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
01eaf654 652 theProgram->SetUniform (myContext,
653 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
654 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
7c3ef2f7 655 myLightTypeArray[0].Packed());
12381341 656 return;
657 }
30f0ad28 658
12381341 659 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
660 Standard_Integer aLightsNb = 0;
661 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
662 {
663 const OpenGl_Light& aLight = anIter.Value();
c357e426 664 if (aLight.Type == Graphic3d_TOLS_AMBIENT)
30f0ad28 665 {
12381341 666 anAmbient += aLight.Color;
667 continue;
668 }
669 else if (aLightsNb >= OpenGLMaxLights)
670 {
671 continue;
672 }
30f0ad28 673
7c3ef2f7 674 OpenGl_ShaderLightType& aLightType = myLightTypeArray[aLightsNb];
4fe9ad57 675 aLightType.Type = aLight.Type;
676 aLightType.IsHeadlight = aLight.IsHeadlight;
30f0ad28 677
7c3ef2f7 678 OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray[aLightsNb];
679 aLightParams.Color = aLight.Color;
680 if (aLight.Type == Graphic3d_TOLS_DIRECTIONAL)
681 {
682 aLightParams.Position = -aLight.Direction;
683 }
684 else if (!aLight.IsHeadlight)
685 {
686 aLightParams.Position.x() = static_cast<float>(aLight.Position.x() - myLocalOrigin.X());
687 aLightParams.Position.y() = static_cast<float>(aLight.Position.y() - myLocalOrigin.Y());
688 aLightParams.Position.z() = static_cast<float>(aLight.Position.z() - myLocalOrigin.Z());
689 aLightParams.Position.w() = 1.0f;
690 }
691 else
692 {
693 aLightParams.Position.x() = static_cast<float>(aLight.Position.x());
694 aLightParams.Position.y() = static_cast<float>(aLight.Position.y());
695 aLightParams.Position.z() = static_cast<float>(aLight.Position.z());
696 aLightParams.Position.w() = 1.0f;
697 }
698
c357e426 699 if (aLight.Type == Graphic3d_TOLS_SPOT)
12381341 700 {
4fe9ad57 701 aLightParams.Direction = aLight.Direction;
30f0ad28 702 }
4fe9ad57 703 aLightParams.Parameters = aLight.Params;
12381341 704 ++aLightsNb;
705 }
30f0ad28 706
12381341 707 theProgram->SetUniform (myContext,
708 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
709 aLightsNb);
710 theProgram->SetUniform (myContext,
711 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
712 anAmbient);
01eaf654 713 theProgram->SetUniform (myContext,
714 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
715 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
7c3ef2f7 716 myLightTypeArray[0].Packed());
12381341 717 if (aLightsNb > 0)
718 {
4fe9ad57 719 theProgram->SetUniform (myContext,
720 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
721 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
7c3ef2f7 722 myLightParamsArray[0].Packed());
30f0ad28 723 }
30f0ad28 724}
725
726// =======================================================================
727// function : PushProjectionState
728// purpose : Pushes state of OCCT projection transform to the program
729// =======================================================================
730void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
731{
732 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
733 {
734 return;
735 }
736
8613985b 737 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
738 if (theProgram == myFfpProgram)
739 {
740 #if !defined(GL_ES_VERSION_2_0)
741 if (myContext->core11 != NULL)
742 {
743 myContext->core11->glMatrixMode (GL_PROJECTION);
744 myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
745 }
746 #endif
747 return;
748 }
749
30f0ad28 750 theProgram->SetUniform (myContext,
751 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
752 myProjectionState.ProjectionMatrix());
753
754 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
755 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
756 {
757 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
758 }
759
760 theProgram->SetUniform (myContext,
761 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
762 myProjectionState.ProjectionMatrix(), true);
763
764 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
765 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
766 {
767 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
768 }
30f0ad28 769}
770
771// =======================================================================
772// function : PushModelWorldState
773// purpose : Pushes state of OCCT model-world transform to the program
774// =======================================================================
775void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
776{
777 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
778 {
779 return;
780 }
781
8613985b 782 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
783 if (theProgram == myFfpProgram)
784 {
785 #if !defined(GL_ES_VERSION_2_0)
786 if (myContext->core11 != NULL)
787 {
788 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
789 myContext->core11->glMatrixMode (GL_MODELVIEW);
790 myContext->core11->glLoadMatrixf (aModelView.GetData());
791 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
792 }
793 #endif
794 return;
795 }
796
30f0ad28 797 theProgram->SetUniform (myContext,
798 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
799 myModelWorldState.ModelWorldMatrix());
800
801 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
802 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
803 {
804 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
805 }
806
807 theProgram->SetUniform (myContext,
808 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
809 myModelWorldState.ModelWorldMatrix(), true);
810
811 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
812 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
813 {
814 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
815 }
30f0ad28 816}
817
818// =======================================================================
819// function : PushWorldViewState
820// purpose : Pushes state of OCCT world-view transform to the program
821// =======================================================================
822void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
823{
824 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
825 {
826 return;
827 }
828
8613985b 829 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
830 if (theProgram == myFfpProgram)
831 {
832 #if !defined(GL_ES_VERSION_2_0)
833 if (myContext->core11 != NULL)
834 {
835 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
836 myContext->core11->glMatrixMode (GL_MODELVIEW);
837 myContext->core11->glLoadMatrixf (aModelView.GetData());
838 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
839 }
840 #endif
841 return;
842 }
843
30f0ad28 844 theProgram->SetUniform (myContext,
845 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
846 myWorldViewState.WorldViewMatrix());
847
848 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
849 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
850 {
851 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
852 }
853
854 theProgram->SetUniform (myContext,
855 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
856 myWorldViewState.WorldViewMatrix(), true);
857
858 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
859 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
860 {
861 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
862 }
30f0ad28 863}
864
865// =======================================================================
866// function : UpdateClippingState
867// purpose : Updates state of OCCT clipping planes
868// =======================================================================
869void OpenGl_ShaderManager::UpdateClippingState()
870{
871 myClippingState.Update();
872}
873
874// =======================================================================
875// function : RevertClippingState
876// purpose : Reverts state of OCCT clipping planes
877// =======================================================================
878void OpenGl_ShaderManager::RevertClippingState()
879{
880 myClippingState.Revert();
881}
882
883// =======================================================================
884// function : PushClippingState
885// purpose : Pushes state of OCCT clipping planes to the program
886// =======================================================================
887void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
888{
889 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
890 {
891 return;
892 }
893
12381341 894 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
8613985b 895 if (theProgram == myFfpProgram)
896 {
897 #if !defined(GL_ES_VERSION_2_0)
898 if (myContext->core11 == NULL)
899 {
900 return;
901 }
902
903 const Standard_Integer aNbMaxPlanes = Min (myContext->MaxClipPlanes(), THE_MAX_CLIP_PLANES);
904 OpenGl_Vec4d anEquations[THE_MAX_CLIP_PLANES];
905 Standard_Integer aPlaneId = 0;
906 Standard_Boolean toRestoreModelView = Standard_False;
907 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
908 {
909 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
910 if (aPlaneIter.IsDisabled())
911 {
912 continue;
913 }
914 else if (aPlaneId >= aNbMaxPlanes)
915 {
916 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
917 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
918 TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
919 break;
920 }
921
922 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
923 OpenGl_Vec4d& aPlaneEq = anEquations[aPlaneId];
924 aPlaneEq.x() = anEquation.x();
925 aPlaneEq.y() = anEquation.y();
926 aPlaneEq.z() = anEquation.z();
927 aPlaneEq.w() = anEquation.w();
928 if (myHasLocalOrigin)
929 {
930 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
931 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
932 aPlaneEq.w() = aD;
933 }
934
935 const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
936 if (anFfpPlaneID == GL_CLIP_PLANE0)
937 {
938 // set either identity or pure view matrix
939 toRestoreModelView = Standard_True;
940 myContext->core11->glMatrixMode (GL_MODELVIEW);
941 myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
942 }
943
944 ::glEnable (anFfpPlaneID);
945 myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
946
947 ++aPlaneId;
948 }
949
950 // switch off unused lights
951 for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
952 {
953 ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
954 }
955
956 // restore combined model-view matrix
957 if (toRestoreModelView)
958 {
959 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
960 myContext->core11->glLoadMatrixf (aModelView.GetData());
961 }
962 #endif
963 return;
964 }
965
12381341 966 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
89a929ea 967 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
12381341 968 {
969 return;
970 }
971
3202bf1e 972 const GLint aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), THE_MAX_CLIP_PLANES);
973 theProgram->SetUniform (myContext,
974 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
975 aNbPlanes);
976 if (aNbPlanes < 1)
12381341 977 {
978 return;
979 }
980
89a929ea 981 OpenGl_Vec4 anEquations[THE_MAX_CLIP_PLANES];
12381341 982 GLuint aPlaneId = 0;
3202bf1e 983 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
12381341 984 {
3202bf1e 985 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
986 if (aPlaneIter.IsDisabled())
30f0ad28 987 {
12381341 988 continue;
30f0ad28 989 }
89a929ea 990 else if (aPlaneId >= THE_MAX_CLIP_PLANES)
991 {
992 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
993 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
994 "Warning: clipping planes limit (8) has been exceeded.");
995 break;
996 }
30f0ad28 997
12381341 998 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
7c3ef2f7 999 OpenGl_Vec4& aPlaneEq = anEquations[aPlaneId];
1000 aPlaneEq.x() = float(anEquation.x());
1001 aPlaneEq.y() = float(anEquation.y());
1002 aPlaneEq.z() = float(anEquation.z());
1003 aPlaneEq.w() = float(anEquation.w());
1004 if (myHasLocalOrigin)
1005 {
1006 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
1007 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
1008 aPlaneEq.w() = float(aD);
1009 }
12381341 1010 ++aPlaneId;
30f0ad28 1011 }
5495fa7e 1012
89a929ea 1013 theProgram->SetUniform (myContext, aLocEquations, THE_MAX_CLIP_PLANES, anEquations);
30f0ad28 1014}
1015
8613985b 1016// =======================================================================
1017// function : PushMaterialState
1018// purpose :
1019// =======================================================================
1020void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1021{
1022 if (myMaterialState.Index() == theProgram->ActiveState (OpenGl_MATERIAL_STATE))
1023 {
1024 return;
1025 }
1026
1027 const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
1028 const OpenGl_Material& aBackMat = myMaterialState.BackMaterial();
1029 theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
1030 if (theProgram == myFfpProgram)
1031 {
1032 #if !defined(GL_ES_VERSION_2_0)
1033 if (myContext->core11 == NULL)
1034 {
1035 return;
1036 }
1037
1038 const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
1039 myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Ambient.GetData());
1040 myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Diffuse.GetData());
1041 myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Specular.GetData());
1042 myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Emission.GetData());
1043 myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Shine());
1044 if (myMaterialState.ToDistinguish())
1045 {
1046 myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Ambient.GetData());
1047 myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Diffuse.GetData());
1048 myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Specular.GetData());
1049 myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Emission.GetData());
1050 myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Shine());
1051 }
1052 #endif
1053 return;
1054 }
1055
1056 theProgram->SetUniform (myContext,
1057 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
1058 myMaterialState.ToMapTexture() ? 1 : 0);
1059 theProgram->SetUniform (myContext,
1060 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
1061 myMaterialState.ToDistinguish() ? 1 : 0);
1062
1063 const GLint aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL);
1064 if (aLocFront != OpenGl_ShaderProgram::INVALID_LOCATION)
1065 {
1066 theProgram->SetUniform (myContext, aLocFront, OpenGl_Material::NbOfVec4(),
1067 aFrontMat.Packed());
1068 }
1069
1070 const GLint aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_BACK_MATERIAL);
1071 if (aLocBack != OpenGl_ShaderProgram::INVALID_LOCATION)
1072 {
1073 theProgram->SetUniform (myContext, aLocBack, OpenGl_Material::NbOfVec4(),
1074 aBackMat.Packed());
1075 }
1076}
1077
a1073ae2 1078// =======================================================================
1079// function : PushOitState
1080// purpose : Pushes state of OIT uniforms to the specified program
1081// =======================================================================
1082void OpenGl_ShaderManager::PushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1083{
1084 if (!theProgram->IsValid())
1085 {
1086 return;
1087 }
1088
1089 if (myOitState.Index() == theProgram->ActiveState (OpenGL_OIT_STATE))
1090 {
1091 return;
1092 }
1093
1094 const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
1095 if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
1096 {
1097 theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
1098 }
1099
1100 const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
1101 if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
1102 {
1103 theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
1104 }
1105}
1106
30f0ad28 1107// =======================================================================
e135a155 1108// function : PushState
30f0ad28 1109// purpose : Pushes state of OCCT graphics parameters to the program
1110// =======================================================================
1111void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1112{
8613985b 1113 const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
1114 PushClippingState (aProgram);
1115 PushWorldViewState (aProgram);
1116 PushModelWorldState (aProgram);
1117 PushProjectionState (aProgram);
1118 PushLightSourceState (aProgram);
1119 PushMaterialState (aProgram);
a1073ae2 1120 PushOitState (aProgram);
12381341 1121}
8625ef7e 1122
1123// =======================================================================
1124// function : prepareStdProgramFont
1125// purpose :
1126// =======================================================================
1127Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1128{
1129 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
b990e557 1130 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
79f4f036 1131 + EOL"THE_SHADER_OUT vec2 TexCoord;"
1132 EOL"void main()"
b990e557 1133 EOL"{"
1134 EOL" TexCoord = occTexCoord.st;"
1135 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1136 EOL"}";
1137
4e1523ef 1138 TCollection_AsciiString
1139 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
1140#if !defined(GL_ES_VERSION_2_0)
1141 if (myContext->core11 == NULL)
1142 {
1143 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
1144 }
1145#endif
1146
b990e557 1147 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
79f4f036 1148 + EOL"THE_SHADER_IN vec2 TexCoord;"
4e1523ef 1149 + aSrcGetAlpha
1150 + EOL"void main()"
b990e557 1151 EOL"{"
1152 EOL" vec4 aColor = occColor;"
1153 EOL" aColor.a *= getAlpha();"
1154 EOL" if (aColor.a <= 0.285) discard;"
4e1523ef 1155 EOL" occFragColor = aColor;"
b990e557 1156 EOL"}";
8625ef7e 1157
4e1523ef 1158#if !defined(GL_ES_VERSION_2_0)
1159 if (myContext->core32 != NULL)
1160 {
1161 aProgramSrc->SetHeader ("#version 150");
1162 }
a1073ae2 1163#else
1164 if (myContext->IsGlGreaterEqual (3, 0))
1165 {
1166 aProgramSrc->SetHeader ("#version 300 es");
1167 }
4e1523ef 1168#endif
8625ef7e 1169 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1170 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1171 TCollection_AsciiString aKey;
1172 if (!Create (aProgramSrc, aKey, myFontProgram))
1173 {
1174 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1175 return Standard_False;
1176 }
1177 return Standard_True;
1178}
1179
1180// =======================================================================
b86bb3df 1181// function : prepareStdProgramFboBlit
1182// purpose :
1183// =======================================================================
1184Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1185{
1186 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1187 TCollection_AsciiString aSrcVert =
1188 EOL"THE_SHADER_OUT vec2 TexCoord;"
1189 EOL"void main()"
1190 EOL"{"
1191 EOL" TexCoord = occVertex.zw;"
1192 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1193 EOL"}";
1194
1195 TCollection_AsciiString aSrcFrag =
1196 EOL"uniform sampler2D uColorSampler;"
1197 EOL"uniform sampler2D uDepthSampler;"
1198 EOL
1199 EOL"THE_SHADER_IN vec2 TexCoord;"
1200 EOL
1201 EOL"void main()"
1202 EOL"{"
1203 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1204 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1205 EOL"}";
1206
1207#if defined(GL_ES_VERSION_2_0)
1208 if (myContext->IsGlGreaterEqual (3, 0))
1209 {
1210 aProgramSrc->SetHeader ("#version 300 es");
1211 }
1ce0716b 1212 else if (myContext->extFragDepth)
1213 {
1214 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
1215 EOL"#define gl_FragDepth gl_FragDepthEXT");
1216 }
b86bb3df 1217 else
1218 {
1219 // there is no way to draw into depth buffer
1220 aSrcFrag =
1221 EOL"uniform sampler2D uColorSampler;"
1222 EOL
1223 EOL"THE_SHADER_IN vec2 TexCoord;"
1224 EOL
1225 EOL"void main()"
1226 EOL"{"
1227 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1228 EOL"}";
1229 }
4e1523ef 1230#else
1231 if (myContext->core32 != NULL)
1232 {
1233 aProgramSrc->SetHeader ("#version 150");
1234 }
b86bb3df 1235#endif
b86bb3df 1236 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1237 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1238 TCollection_AsciiString aKey;
1239 if (!Create (aProgramSrc, aKey, myBlitProgram))
1240 {
1241 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1242 return Standard_False;
1243 }
1244
1245 myContext->BindProgram (myBlitProgram);
1246 myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
1247 myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
1248 myContext->BindProgram (NULL);
1249 return Standard_True;
1250}
1251
a1073ae2 1252// =======================================================================
1253// function : prepareStdProgramOitCompositing
1254// purpose :
1255// =======================================================================
1256Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1257{
1258 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1259 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1260 TCollection_AsciiString aSrcVert, aSrcFrag;
1261
1262 aSrcVert =
1263 EOL"THE_SHADER_OUT vec2 TexCoord;"
1264 EOL"void main()"
1265 EOL"{"
1266 EOL" TexCoord = occVertex.zw;"
1267 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1268 EOL"}";
1269
1270 if (!theMsaa)
1271 {
1272 aSrcFrag =
1273 EOL"uniform sampler2D uAccumTexture;"
1274 EOL"uniform sampler2D uWeightTexture;"
1275 EOL
1276 EOL"THE_SHADER_IN vec2 TexCoord;"
1277 EOL
1278 EOL"void main()"
1279 EOL"{"
1280 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1281 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
1282 EOL" occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
1283 EOL"}";
1284 #if !defined(GL_ES_VERSION_2_0)
1285 if (myContext->IsGlGreaterEqual (3, 2))
1286 {
1287 aProgramSrc->SetHeader ("#version 150");
1288 }
1289 #else
1290 if (myContext->IsGlGreaterEqual (3, 0))
1291 {
1292 aProgramSrc->SetHeader ("#version 300 es");
1293 }
1294 #endif
1295 }
1296 else
1297 {
1298 aSrcFrag =
1299 EOL"uniform sampler2DMS uAccumTexture;"
1300 EOL"uniform sampler2DMS uWeightTexture;"
1301 EOL
1302 EOL"THE_SHADER_IN vec2 TexCoord;"
1303 EOL
1304 EOL"void main()"
1305 EOL"{"
1306 EOL" ivec2 aTexel = ivec2 (textureSize (uAccumTexture) * TexCoord);"
1307 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1308 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
1309 EOL" occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
1310 EOL"}";
1311 #if !defined(GL_ES_VERSION_2_0)
1312 if (myContext->IsGlGreaterEqual (4, 0))
1313 {
1314 aProgramSrc->SetHeader ("#version 400");
1315 }
1316 #else
1317 if (myContext->IsGlGreaterEqual (3, 0))
1318 {
1319 aProgramSrc->SetHeader ("#version 300 es");
1320 }
1321 #endif
1322 }
1323
1324 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1325 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1326 TCollection_AsciiString aKey;
1327 if (!Create (aProgramSrc, aKey, aProgram))
1328 {
1329 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1330 return Standard_False;
1331 }
1332
1333 myContext->BindProgram (aProgram);
1334 aProgram->SetSampler (myContext, "uAccumTexture", 0);
1335 aProgram->SetSampler (myContext, "uWeightTexture", 1);
1336 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1337 return Standard_True;
1338}
1339
299e0ab9 1340// =======================================================================
1341// function : pointSpriteAlphaSrc
1342// purpose :
1343// =======================================================================
fd59283a 1344TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
299e0ab9 1345{
fd59283a 1346 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").a; }";
299e0ab9 1347#if !defined(GL_ES_VERSION_2_0)
fd59283a 1348 if (myContext->core11 == NULL
1349 && (theBits & OpenGl_PO_TextureA) != 0)
299e0ab9 1350 {
fd59283a 1351 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").r; }";
299e0ab9 1352 }
fd59283a 1353#else
1354 (void )theBits;
299e0ab9 1355#endif
299e0ab9 1356 return aSrcGetAlpha;
1357}
1358
1359namespace
1360{
1361
1362 // =======================================================================
1363 // function : textureUsed
1364 // purpose :
1365 // =======================================================================
1366 static bool textureUsed (const Standard_Integer theBits)
1367 {
1368 return (theBits & OpenGl_PO_TextureA) != 0 || (theBits & OpenGl_PO_TextureRGB) != 0;
1369 }
1370
1371}
1372
b86bb3df 1373// =======================================================================
8625ef7e 1374// function : prepareStdProgramFlat
1375// purpose :
1376// =======================================================================
1377Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1378 const Standard_Integer theBits)
1379{
1380 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
a1073ae2 1381 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha;
1382 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
8625ef7e 1383 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
4e1523ef 1384 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
8625ef7e 1385 if ((theBits & OpenGl_PO_Point) != 0)
1386 {
1387 #if defined(GL_ES_VERSION_2_0)
1388 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1389 #endif
8625ef7e 1390
299e0ab9 1391 if ((theBits & OpenGl_PO_TextureRGB) != 0)
8625ef7e 1392 {
1393 aSrcFragGetColor =
fd59283a 1394 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord "); }";
8625ef7e 1395 }
299e0ab9 1396
fd59283a 1397 if (textureUsed (theBits))
1398 {
1399 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1400
1401 #if !defined(GL_ES_VERSION_2_0)
1402 if (myContext->core11 != NULL
1403 && myContext->IsGlGreaterEqual (2, 1))
1404 {
1405 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1406 }
1407 #endif
1408
1409 aSrcFragMainGetColor =
1410 EOL" vec4 aColor = getColor();"
1411 EOL" aColor.a = getAlpha();"
1412 EOL" if (aColor.a <= 0.1) discard;"
1413 EOL" occFragColor = aColor;";
1414 }
1415 else
1416 {
1417 aSrcFragMainGetColor =
1418 EOL" vec4 aColor = getColor();"
1419 EOL" if (aColor.a <= 0.1) discard;"
1420 EOL" occFragColor = aColor;";
1421 }
8625ef7e 1422 }
6c6aadb1 1423 else
1424 {
1425 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1426 {
4e1523ef 1427 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1428 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1429 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1430
1431 aSrcFragGetColor =
79f4f036 1432 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w); }";
6c6aadb1 1433 }
e135a155 1434 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1435 {
1436 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1437 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1438
1439 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1440
1441 aSrcVertExtraMain +=
1442 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1443 EOL" vec3 aNormal = transformNormal (occNormal);"
1444 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1445 EOL" aReflect.z += 1.0;"
b872ca56 1446 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
e135a155 1447
1448 aSrcFragGetColor =
1449 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1450 }
6c6aadb1 1451 }
8625ef7e 1452 if ((theBits & OpenGl_PO_VertColor) != 0)
1453 {
4e1523ef 1454 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
8625ef7e 1455 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
4e1523ef 1456 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
8625ef7e 1457 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1458 }
1a7ece8f 1459 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1460 {
4e1523ef 1461 aSrcVertExtraOut +=
1462 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1463 EOL"THE_SHADER_OUT vec4 Position;";
1464 aSrcFragExtraOut +=
1465 EOL"THE_SHADER_IN vec4 PositionWorld;"
1466 EOL"THE_SHADER_IN vec4 Position;";
8625ef7e 1467 aSrcVertExtraMain +=
1468 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1469 EOL" Position = occWorldViewMatrix * PositionWorld;";
1a7ece8f 1470
1471 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1472 {
1473 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1474 }
1475 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1476 {
1477 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1478 }
1479 else
1480 {
1481 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1482 }
8625ef7e 1483 }
a1073ae2 1484 if ((theBits & OpenGl_PO_WriteOit) != 0)
1485 {
1486 aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
1487 }
8625ef7e 1488
ac116c22 1489 TCollection_AsciiString aSrcVertEndMain;
1490 if ((theBits & OpenGl_PO_StippleLine) != 0)
1491 {
959a265a 1492 bool hasGlslBitOps = false;
ac116c22 1493 #if defined(GL_ES_VERSION_2_0)
1494 if (myContext->IsGlGreaterEqual (3, 0))
1495 {
959a265a 1496 hasGlslBitOps = true;
ac116c22 1497 }
1498 #else
959a265a 1499 if (myContext->IsGlGreaterEqual (3, 0))
1500 {
1501 aProgramSrc->SetHeader ("#version 130");
1502 hasGlslBitOps = true;
1503 }
1504 else if(myContext->CheckExtension("GL_EXT_gpu_shader4"))
ac116c22 1505 {
959a265a 1506 aProgramSrc->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1507 hasGlslBitOps = true;
ac116c22 1508 }
1509 #endif
1510
959a265a 1511 if (hasGlslBitOps)
ac116c22 1512 {
1513 aSrcVertExtraOut +=
1514 EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1515 aSrcFragExtraOut +=
1516 EOL"THE_SHADER_IN vec2 ScreenSpaceCoord;"
1517 EOL"uniform int uPattern;"
1518 EOL"uniform float uFactor;";
1519 aSrcVertEndMain =
1520 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1521 aSrcFragMainGetColor =
1522 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1523 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1524 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1525 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1526 EOL" vec4 aColor = getColor();"
1527 EOL" if (aColor.a <= 0.1) discard;"
1528 EOL" occFragColor = aColor;";
1529 }
1530 else
1531 {
1532 const TCollection_ExtendedString aWarnMessage =
1533 "Warning: stipple lines in GLSL will be ignored.";
3b523c4c 1534 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1535 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
ac116c22 1536 }
1537 }
1538
8625ef7e 1539 aSrcVert =
e135a155 1540 aSrcVertExtraFunc
1541 + aSrcVertExtraOut
8625ef7e 1542 + EOL"void main()"
1543 EOL"{"
1544 + aSrcVertExtraMain
1545 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
ac116c22 1546 + aSrcVertEndMain
1547 + EOL"}";
8625ef7e 1548
1549 aSrcFrag =
1550 aSrcFragExtraOut
1551 + aSrcFragGetColor
299e0ab9 1552 + aSrcGetAlpha
8625ef7e 1553 + EOL"void main()"
1554 EOL"{"
1555 + aSrcFragExtraMain
1556 + aSrcFragMainGetColor
a1073ae2 1557 + aSrcFragWriteOit
8625ef7e 1558 + EOL"}";
1559
4e1523ef 1560#if !defined(GL_ES_VERSION_2_0)
1561 if (myContext->core32 != NULL)
1562 {
1563 aProgramSrc->SetHeader ("#version 150");
1564 }
a1073ae2 1565#else
1566 if (myContext->IsGlGreaterEqual (3, 0))
1567 {
1568 aProgramSrc->SetHeader ("#version 300 es");
1569 }
4e1523ef 1570#endif
8625ef7e 1571 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1572 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1573
1574 TCollection_AsciiString aKey;
1575 if (!Create (aProgramSrc, aKey, theProgram))
1576 {
1577 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1578 return Standard_False;
1579 }
1580 return Standard_True;
1581}
1582
299e0ab9 1583// =======================================================================
1584// function : pointSpriteShadingSrc
1585// purpose :
1586// =======================================================================
1587TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc,
1588 const Standard_Integer theBits)
1589{
1590 TCollection_AsciiString aSrcFragGetColor;
1591 if ((theBits & OpenGl_PO_TextureA) != 0)
1592 {
fd59283a 1593 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
299e0ab9 1594 EOL"vec4 getColor(void)"
1595 EOL"{"
1596 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1597 EOL" aColor.a = getAlpha();"
1598 EOL" if (aColor.a <= 0.1) discard;"
1599 EOL" return aColor;"
1600 EOL"}";
1601 }
1602 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1603 {
1604 aSrcFragGetColor = TCollection_AsciiString() +
1605 EOL"vec4 getColor(void)"
1606 EOL"{"
1607 EOL" vec4 aColor = " + theBaseColorSrc + ";"
fd59283a 1608 EOL" aColor = occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ") * aColor;"
299e0ab9 1609 EOL" if (aColor.a <= 0.1) discard;"
1610 EOL" return aColor;"
1611 EOL"}";
1612 }
1613
1614 return aSrcFragGetColor;
1615}
1616
256f9ac0 1617// =======================================================================
1618// function : stdComputeLighting
1619// purpose :
1620// =======================================================================
abdf0b10 1621TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
256f9ac0 1622{
f68acbf4 1623 Standard_Integer aLightsMap[Graphic3d_TOLS_SPOT + 1] = { 0, 0, 0, 0 };
256f9ac0 1624 TCollection_AsciiString aLightsFunc, aLightsLoop;
1625 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1626 if (aLights != NULL)
1627 {
1628 Standard_Integer anIndex = 0;
1629 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1630 {
1631 switch (aLightIter.Value().Type)
1632 {
c357e426 1633 case Graphic3d_TOLS_AMBIENT:
256f9ac0 1634 --anIndex;
1635 break; // skip ambient
c357e426 1636 case Graphic3d_TOLS_DIRECTIONAL:
256f9ac0 1637 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1638 break;
c357e426 1639 case Graphic3d_TOLS_POSITIONAL:
256f9ac0 1640 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1641 break;
c357e426 1642 case Graphic3d_TOLS_SPOT:
256f9ac0 1643 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1644 break;
1645 }
f68acbf4 1646 aLightsMap[aLightIter.Value().Type] += 1;
1647 }
1648 const Standard_Integer aNbLoopLights = aLightsMap[Graphic3d_TOLS_DIRECTIONAL]
1649 + aLightsMap[Graphic3d_TOLS_POSITIONAL]
1650 + aLightsMap[Graphic3d_TOLS_SPOT];
1651 if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] == 1
1652 && aNbLoopLights == 1)
1653 {
1654 // use the version with hard-coded first index
1655 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
1656 aLightsFunc += THE_FUNC_directionalLightFirst;
1657 }
1658 else if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] > 0)
1659 {
1660 aLightsFunc += THE_FUNC_directionalLight;
1661 }
1662 if (aLightsMap[Graphic3d_TOLS_POSITIONAL] > 0)
1663 {
1664 aLightsFunc += THE_FUNC_pointLight;
1665 }
1666 if (aLightsMap[Graphic3d_TOLS_SPOT] > 0)
1667 {
1668 aLightsFunc += THE_FUNC_spotLight;
256f9ac0 1669 }
1670 }
1671
abdf0b10 1672 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1673 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1674 if (theHasVertColor)
1675 {
1676 aGetMatAmbient = "getVertColor();";
1677 aGetMatDiffuse = "getVertColor();";
1678 }
1679
256f9ac0 1680 return TCollection_AsciiString()
1681 + THE_FUNC_lightDef
1682 + aLightsFunc
1683 + EOL
1684 EOL"vec4 computeLighting (in vec3 theNormal,"
1685 EOL" in vec3 theView,"
1686 EOL" in vec4 thePoint,"
1687 EOL" in bool theIsFront)"
1688 EOL"{"
1689 EOL" Ambient = occLightAmbient.rgb;"
1690 EOL" Diffuse = vec3 (0.0);"
1691 EOL" Specular = vec3 (0.0);"
1692 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1693 + aLightsLoop
363bc51b 1694 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
1695 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
1696 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1697 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1698 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
1699 EOL" + Diffuse * aMatDiffuse.rgb"
1700 EOL" + Specular * aMatSpecular.rgb"
1701 EOL" + aMatEmission.rgb;"
1702 EOL" return vec4 (aColor, aMatDiffuse.a);"
256f9ac0 1703 EOL"}";
1704}
1705
8625ef7e 1706// =======================================================================
1707// function : prepareStdProgramGouraud
1708// purpose :
1709// =======================================================================
1710Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1711 const Standard_Integer theBits)
1712{
1713 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
a1073ae2 1714 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain;
1715 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
6c6aadb1 1716 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
8625ef7e 1717 if ((theBits & OpenGl_PO_Point) != 0)
1718 {
1719 #if defined(GL_ES_VERSION_2_0)
1720 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1721 #endif
299e0ab9 1722
1723 if (textureUsed (theBits))
6c6aadb1 1724 {
299e0ab9 1725 #if !defined(GL_ES_VERSION_2_0)
1726 if (myContext->core11 != NULL
1727 && myContext->IsGlGreaterEqual (2, 1))
1728 {
1729 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1730 }
1731 #endif
1732
1733 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
6c6aadb1 1734 }
1735 }
1736 else
1737 {
1738 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1739 {
4e1523ef 1740 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1741 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1742 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1743
1744 aSrcFragGetColor =
1745 EOL"vec4 getColor(void)"
1746 EOL"{"
1747 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
79f4f036 1748 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1749 EOL"}";
1750 }
1751 }
299e0ab9 1752
1753 if ((theBits & OpenGl_PO_VertColor) != 0)
1754 {
1755 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1756 }
1757
1a7ece8f 1758 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1759 {
4e1523ef 1760 aSrcVertExtraOut +=
1761 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1762 EOL"THE_SHADER_OUT vec4 Position;";
1763 aSrcFragExtraOut +=
1764 EOL"THE_SHADER_IN vec4 PositionWorld;"
1765 EOL"THE_SHADER_IN vec4 Position;";
8625ef7e 1766 aSrcVertExtraMain +=
1767 EOL" PositionWorld = aPositionWorld;"
1768 EOL" Position = aPosition;";
1a7ece8f 1769
1770 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1771 {
1772 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1773 }
1774 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1775 {
1776 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1777 }
1778 else
1779 {
1780 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1781 }
8625ef7e 1782 }
a1073ae2 1783 if ((theBits & OpenGl_PO_WriteOit) != 0)
1784 {
1785 aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
1786 }
8625ef7e 1787
abdf0b10 1788 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1789 aSrcVert = TCollection_AsciiString()
1790 + THE_FUNC_transformNormal
1791 + EOL
abdf0b10 1792 + aSrcVertColor
256f9ac0 1793 + aLights
8625ef7e 1794 + EOL
4e1523ef 1795 EOL"THE_SHADER_OUT vec4 FrontColor;"
1796 EOL"THE_SHADER_OUT vec4 BackColor;"
8625ef7e 1797 EOL
1798 + aSrcVertExtraOut
1799 + EOL"void main()"
1800 EOL"{"
1801 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1802 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1803 EOL" vec3 aNormal = transformNormal (occNormal);"
1804 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1805 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1806 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1807 + aSrcVertExtraMain
1808 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1809 EOL"}";
1810
1811 aSrcFrag = TCollection_AsciiString()
4e1523ef 1812 + EOL"THE_SHADER_IN vec4 FrontColor;"
1813 EOL"THE_SHADER_IN vec4 BackColor;"
8625ef7e 1814 + aSrcFragExtraOut
6c6aadb1 1815 + aSrcFragGetColor
8625ef7e 1816 + EOL"void main()"
1817 EOL"{"
1818 + aSrcFragExtraMain
4e1523ef 1819 + EOL" occFragColor = getColor();"
a1073ae2 1820 + aSrcFragWriteOit
1821 + EOL"}";
8625ef7e 1822
4e1523ef 1823#if !defined(GL_ES_VERSION_2_0)
1824 if (myContext->core32 != NULL)
1825 {
1826 aProgramSrc->SetHeader ("#version 150");
1827 }
a1073ae2 1828#else
1829 if (myContext->IsGlGreaterEqual (3, 0))
1830 {
1831 aProgramSrc->SetHeader ("#version 300 es");
1832 }
4e1523ef 1833#endif
8625ef7e 1834 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1835 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1836 TCollection_AsciiString aKey;
1837 if (!Create (aProgramSrc, aKey, theProgram))
1838 {
1839 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1840 return Standard_False;
1841 }
1842 return Standard_True;
1843}
1844
1845// =======================================================================
1846// function : prepareStdProgramPhong
1847// purpose :
1848// =======================================================================
1849Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1850 const Standard_Integer theBits)
1851{
6c6aadb1 1852 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1853
8625ef7e 1854 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
a1073ae2 1855 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain;
1856 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain, aSrcFragWriteOit;
6c6aadb1 1857 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
8625ef7e 1858 if ((theBits & OpenGl_PO_Point) != 0)
1859 {
1860 #if defined(GL_ES_VERSION_2_0)
1861 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1862 #endif
6c6aadb1 1863
299e0ab9 1864 if (textureUsed (theBits))
6c6aadb1 1865 {
299e0ab9 1866 #if !defined(GL_ES_VERSION_2_0)
1867 if (myContext->core11 != NULL
1868 && myContext->IsGlGreaterEqual (2, 1))
1869 {
1870 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1871 }
1872 #endif
1873
1874 aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
6c6aadb1 1875 }
1876 }
1877 else
1878 {
1879 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1880 {
4e1523ef 1881 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1882 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
79f4f036 1883 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 1884
1885 aSrcFragGetColor =
1886 EOL"vec4 getColor(void)"
1887 EOL"{"
1888 EOL" vec4 aColor = " thePhongCompLight ";"
79f4f036 1889 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 1890 EOL"}";
1891 }
1892 }
1893
299e0ab9 1894 if ((theBits & OpenGl_PO_VertColor) != 0)
1895 {
1896 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1897 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1898 aSrcFragGetVertColor = EOL"THE_SHADER_IN vec4 VertColor;"
1899 EOL"vec4 getVertColor(void) { return VertColor; }";
1900 }
1901
1a7ece8f 1902 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 1903 {
1a7ece8f 1904 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1905 {
1906 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1907 }
1908 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1909 {
1910 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1911 }
1912 else
1913 {
1914 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1915 }
8625ef7e 1916 }
a1073ae2 1917 if ((theBits & OpenGl_PO_WriteOit) != 0)
1918 {
1919 aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
1920 }
8625ef7e 1921
1922 aSrcVert = TCollection_AsciiString()
1923 + THE_FUNC_transformNormal
1924 + EOL
4e1523ef 1925 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1926 EOL"THE_SHADER_OUT vec4 Position;"
1927 EOL"THE_SHADER_OUT vec3 Normal;"
1928 EOL"THE_SHADER_OUT vec3 View;"
8625ef7e 1929 EOL
1930 + aSrcVertExtraOut
1931 + EOL"void main()"
1932 EOL"{"
1933 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1934 EOL" Position = occWorldViewMatrix * PositionWorld;"
1935 EOL" Normal = transformNormal (occNormal);"
1936 EOL" View = vec3 (0.0, 0.0, 1.0);"
1937 + aSrcVertExtraMain
1938 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1939 EOL"}";
1940
abdf0b10 1941 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
8625ef7e 1942 aSrcFrag = TCollection_AsciiString()
4e1523ef 1943 + EOL"THE_SHADER_IN vec4 PositionWorld;"
1944 EOL"THE_SHADER_IN vec4 Position;"
1945 EOL"THE_SHADER_IN vec3 Normal;"
1946 EOL"THE_SHADER_IN vec3 View;"
8625ef7e 1947 + EOL
6c6aadb1 1948 + aSrcFragExtraOut
1949 + aSrcFragGetVertColor
256f9ac0 1950 + aLights
6c6aadb1 1951 + aSrcFragGetColor
8625ef7e 1952 + EOL
1953 EOL"void main()"
1954 EOL"{"
1955 + aSrcFragExtraMain
4e1523ef 1956 + EOL" occFragColor = getColor();"
a1073ae2 1957 + aSrcFragWriteOit
1958 + EOL"}";
8625ef7e 1959
4e1523ef 1960#if !defined(GL_ES_VERSION_2_0)
1961 if (myContext->core32 != NULL)
1962 {
1963 aProgramSrc->SetHeader ("#version 150");
1964 }
a1073ae2 1965#else
1966 if (myContext->IsGlGreaterEqual (3, 0))
1967 {
1968 aProgramSrc->SetHeader ("#version 300 es");
1969 }
4e1523ef 1970#endif
8625ef7e 1971 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1972 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1973 TCollection_AsciiString aKey;
1974 if (!Create (aProgramSrc, aKey, theProgram))
1975 {
1976 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1977 return Standard_False;
1978 }
1979 return Standard_True;
1980}
1981
38a0206f 1982// =======================================================================
f978241f 1983// function : prepareStdProgramStereo
38a0206f 1984// purpose :
1985// =======================================================================
f978241f 1986Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1987 const Graphic3d_StereoMode theStereoMode)
38a0206f 1988{
1989 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1990 TCollection_AsciiString aSrcVert =
1991 EOL"THE_SHADER_OUT vec2 TexCoord;"
1992 EOL"void main()"
1993 EOL"{"
1994 EOL" TexCoord = occVertex.zw;"
1995 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1996 EOL"}";
1997
f978241f 1998 TCollection_AsciiString aSrcFrag;
1999 switch (theStereoMode)
2000 {
2001 case Graphic3d_StereoMode_Anaglyph:
2002 {
2003 aSrcFrag =
2004 EOL"uniform sampler2D uLeftSampler;"
2005 EOL"uniform sampler2D uRightSampler;"
2006 EOL
2007 EOL"uniform mat4 uMultL;"
2008 EOL"uniform mat4 uMultR;"
2009 EOL
0deb6f04 2010 EOL"const vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
2011 EOL"const vec4 THE_POW_DOWN = 1.0 / vec4 (2.2, 2.2, 2.2, 1.0);"
f978241f 2012 EOL
2013 EOL"THE_SHADER_IN vec2 TexCoord;"
2014 EOL
2015 EOL"void main()"
2016 EOL"{"
2017 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2018 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2019 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
2020 EOL" aColorR = pow (aColorR, THE_POW_UP);"
2021 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2022 EOL" occFragColor = pow (aColor, THE_POW_DOWN);"
2023 EOL"}";
2024 break;
2025 }
2026 case Graphic3d_StereoMode_RowInterlaced:
2027 {
2028 aSrcFrag =
2029 EOL"uniform sampler2D uLeftSampler;"
2030 EOL"uniform sampler2D uRightSampler;"
2031 EOL
2032 EOL"THE_SHADER_IN vec2 TexCoord;"
2033 EOL
2034 EOL"void main()"
2035 EOL"{"
2036 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2037 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 2038 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
f978241f 2039 EOL" {"
2040 EOL" occFragColor = aColorL;"
2041 EOL" }"
2042 EOL" else"
2043 EOL" {"
2044 EOL" occFragColor = aColorR;"
2045 EOL" }"
2046 EOL"}";
2047 break;
2048 }
2049 case Graphic3d_StereoMode_ColumnInterlaced:
2050 {
2051 aSrcFrag =
2052 EOL"uniform sampler2D uLeftSampler;"
2053 EOL"uniform sampler2D uRightSampler;"
2054 EOL
2055 EOL"THE_SHADER_IN vec2 TexCoord;"
2056 EOL
2057 EOL"void main()"
2058 EOL"{"
2059 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2060 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 2061 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
f978241f 2062 EOL" {"
2063 EOL" occFragColor = aColorL;"
2064 EOL" }"
2065 EOL" else"
2066 EOL" {"
2067 EOL" occFragColor = aColorR;"
2068 EOL" }"
2069 EOL"}";
2070 break;
2071 }
2072 case Graphic3d_StereoMode_ChessBoard:
2073 {
2074 aSrcFrag =
2075 EOL"uniform sampler2D uLeftSampler;"
2076 EOL"uniform sampler2D uRightSampler;"
2077 EOL
2078 EOL"THE_SHADER_IN vec2 TexCoord;"
2079 EOL
2080 EOL"void main()"
2081 EOL"{"
2082 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2083 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 2084 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2085 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
f978241f 2086 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2087 EOL" {"
2088 EOL" occFragColor = aColorL;"
2089 EOL" }"
2090 EOL" else"
2091 EOL" {"
2092 EOL" occFragColor = aColorR;"
2093 EOL" }"
2094 EOL"}";
2095 break;
2096 }
2097 case Graphic3d_StereoMode_SideBySide:
2098 {
2099 aSrcFrag =
2100 EOL"uniform sampler2D uLeftSampler;"
2101 EOL"uniform sampler2D uRightSampler;"
2102 EOL
2103 EOL"THE_SHADER_IN vec2 TexCoord;"
2104 EOL
2105 EOL"void main()"
2106 EOL"{"
2107 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2108 EOL" if (TexCoord.x > 0.5)"
2109 EOL" {"
2110 EOL" aTexCoord.x -= 1.0;"
2111 EOL" }"
2112 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2113 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2114 EOL" if (TexCoord.x <= 0.5)"
2115 EOL" {"
2116 EOL" occFragColor = aColorL;"
2117 EOL" }"
2118 EOL" else"
2119 EOL" {"
2120 EOL" occFragColor = aColorR;"
2121 EOL" }"
2122 EOL"}";
2123 break;
2124 }
2125 case Graphic3d_StereoMode_OverUnder:
2126 {
2127 aSrcFrag =
2128 EOL"uniform sampler2D uLeftSampler;"
2129 EOL"uniform sampler2D uRightSampler;"
2130 EOL
2131 EOL"THE_SHADER_IN vec2 TexCoord;"
2132 EOL
2133 EOL"void main()"
2134 EOL"{"
2135 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2136 EOL" if (TexCoord.y > 0.5)"
2137 EOL" {"
2138 EOL" aTexCoord.y -= 1.0;"
2139 EOL" }"
2140 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2141 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2142 EOL" if (TexCoord.y <= 0.5)"
2143 EOL" {"
2144 EOL" occFragColor = aColorL;"
2145 EOL" }"
2146 EOL" else"
2147 EOL" {"
2148 EOL" occFragColor = aColorR;"
2149 EOL" }"
2150 EOL"}";
2151 break;
2152 }
2153 case Graphic3d_StereoMode_QuadBuffer:
2154 case Graphic3d_StereoMode_SoftPageFlip:
2155 default:
2156 {
2157 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2158 if (!aProgram.IsNull())
2159 {
2160 return aProgram->IsValid();
2161 }*/
2162 aSrcFrag =
2163 EOL"uniform sampler2D uLeftSampler;"
2164 EOL"uniform sampler2D uRightSampler;"
2165 EOL
2166 EOL"THE_SHADER_IN vec2 TexCoord;"
2167 EOL
2168 EOL"void main()"
2169 EOL"{"
2170 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2171 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2172 EOL" aColorL.b = 0.0;"
2173 EOL" aColorL.g = 0.0;"
2174 EOL" aColorR.r = 0.0;"
2175 EOL" occFragColor = aColorL + aColorR;"
2176 EOL"}";
2177 break;
2178 }
2179 }
38a0206f 2180
2181#if !defined(GL_ES_VERSION_2_0)
2182 if (myContext->core32 != NULL)
2183 {
2184 aProgramSrc->SetHeader ("#version 150");
2185 }
a1073ae2 2186#else
2187 if (myContext->IsGlGreaterEqual (3, 0))
2188 {
2189 aProgramSrc->SetHeader ("#version 300 es");
2190 }
38a0206f 2191#endif
2192
2193 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
2194 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
2195 TCollection_AsciiString aKey;
f978241f 2196 if (!Create (aProgramSrc, aKey, theProgram))
38a0206f 2197 {
f978241f 2198 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
38a0206f 2199 return Standard_False;
2200 }
2201
f978241f 2202 myContext->BindProgram (theProgram);
2203 theProgram->SetSampler (myContext, "uLeftSampler", 0);
2204 theProgram->SetSampler (myContext, "uRightSampler", 1);
38a0206f 2205 myContext->BindProgram (NULL);
2206 return Standard_True;
2207}
2208
8625ef7e 2209// =======================================================================
2210// function : bindProgramWithState
2211// purpose :
2212// =======================================================================
299e0ab9 2213Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
8625ef7e 2214{
8613985b 2215 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
2216 if (isBound
2217 && !theProgram.IsNull())
8625ef7e 2218 {
8613985b 2219 theProgram->ApplyVariables (myContext);
8625ef7e 2220 }
8625ef7e 2221 PushState (theProgram);
8613985b 2222 return isBound;
8625ef7e 2223}