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