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