0031649: Visualization, TKOpenGL - broken skybox in VR output
[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>
bf5f0ca2 19#include <OpenGl_Aspects.hxx>
25c35042 20#include <OpenGl_ClippingIterator.hxx>
30f0ad28 21#include <OpenGl_Context.hxx>
67312b79 22#include <Graphic3d_CubeMapPacked.hxx>
30f0ad28 23#include <OpenGl_ShaderManager.hxx>
24#include <OpenGl_ShaderProgram.hxx>
98b15dbf 25#include <OpenGl_VertexBufferCompat.hxx>
737e9a8d 26#include <OpenGl_PointSprite.hxx>
0adbd30f 27#include <OpenGl_Workspace.hxx>
ac116c22 28#include <TCollection_ExtendedString.hxx>
29
67312b79 30#include "../Shaders/Shaders_PBRDistribution_glsl.pxx"
31#include "../Shaders/Shaders_PBRGeometry_glsl.pxx"
32#include "../Shaders/Shaders_PBRFresnel_glsl.pxx"
33#include "../Shaders/Shaders_PBRCookTorrance_glsl.pxx"
34#include "../Shaders/Shaders_PBRIllumination_glsl.pxx"
35#include "../Shaders/Shaders_PBREnvBaking_fs.pxx"
36#include "../Shaders/Shaders_PBREnvBaking_vs.pxx"
88b312d3 37#include "../Shaders/Shaders_PointLightAttenuation_glsl.pxx"
78607702 38#include "../Shaders/Shaders_TangentSpaceNormal_glsl.pxx"
67312b79 39
92efcf78 40IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
41
8625ef7e 42namespace
43{
992ed6b3 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//! Compute TexCoord value in Vertex Shader
58const char THE_VARY_TexCoord_Trsf[] =
59 EOL" float aRotSin = occTextureTrsf_RotationSin();"
60 EOL" float aRotCos = occTextureTrsf_RotationCos();"
faff3767 61 EOL" vec2 aTex2 = vec2 (occTexCoord.x * aRotCos - occTexCoord.y * aRotSin,"
62 EOL" occTexCoord.x * aRotSin + occTexCoord.y * aRotCos);"
63 EOL" aTex2 = (aTex2 + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
79f4f036 64 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
6c6aadb1 65
fd59283a 66//! Auxiliary function to flip gl_PointCoord vertically
67#define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
68
67312b79 69//! Auxiliary function to transform normal from model to view coordinate system.
70const char THE_FUNC_transformNormal_view[] =
8625ef7e 71 EOL"vec3 transformNormal (in vec3 theNormal)"
72 EOL"{"
73 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
74 EOL" * occModelWorldMatrixInverseTranspose"
75 EOL" * vec4 (theNormal, 0.0);"
76 EOL" return normalize (aResult.xyz);"
77 EOL"}";
78
67312b79 79//! The same function as THE_FUNC_transformNormal but is used in PBR pipeline.
80//! The normals are expected to be in world coordinate system in PBR pipeline.
81const char THE_FUNC_transformNormal_world[] =
82 EOL"vec3 transformNormal (in vec3 theNormal)"
83 EOL"{"
84 EOL" vec4 aResult = occModelWorldMatrixInverseTranspose"
85 EOL" * vec4 (theNormal, 0.0);"
86 EOL" return normalize (aResult.xyz);"
87 EOL"}";
88
8625ef7e 89//! Global shader variable for color definition with lighting enabled.
90const char THE_FUNC_lightDef[] =
91 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
92 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
93 EOL"vec3 Specular;"; //!< Specular contribution of light sources
94
67312b79 95//! Global shader variable for color definition with lighting enabled.
96const char THE_FUNC_PBR_lightDef[] =
97 EOL"vec3 DirectLighting;" //!< Accumulator of direct lighting from light sources
98 EOL"vec4 BaseColor;" //!< Base color (albedo) of material for PBR
99 EOL"float Metallic;" //!< Metallic coefficient of material
72f6dc61 100 EOL"float NormalizedRoughness;" //!< Normalized roughness coefficient of material
67312b79 101 EOL"float Roughness;" //!< Roughness coefficient of material
102 EOL"vec3 Emission;" //!< Light intensity emitted by material
103 EOL"float IOR;"; //!< Material's index of refraction
104
8625ef7e 105//! Function computes contribution of isotropic point light source
106const char THE_FUNC_pointLight[] =
107 EOL"void pointLight (in int theId,"
108 EOL" in vec3 theNormal,"
109 EOL" in vec3 theView,"
110 EOL" in vec3 thePoint,"
111 EOL" in bool theIsFront)"
112 EOL"{"
9504a30d 113 EOL" vec3 aLight = occLight_Position (theId);"
67312b79 114 EOL" if (!occLight_IsHeadlight (theId))"
8625ef7e 115 EOL" {"
5f4bd4d4 116 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
8625ef7e 117 EOL" }"
118 EOL" aLight -= thePoint;"
119 EOL
120 EOL" float aDist = length (aLight);"
88b312d3 121 EOL" float aRange = occLight_Range (theId);"
122 EOL" float anAtten = occPointLightAttenuation (aDist, aRange, occLight_LinearAttenuation (theId), occLight_ConstAttenuation (theId));"
123 EOL" if (anAtten <= 0.0) return;"
124 EOL" aLight /= aDist;"
8625ef7e 125 EOL
126 EOL" vec3 aHalf = normalize (aLight + theView);"
127 EOL
128 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
129 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
130 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
131 EOL
132 EOL" float aSpecl = 0.0;"
133 EOL" if (aNdotL > 0.0)"
134 EOL" {"
135 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
136 EOL" }"
137 EOL
9504a30d 138 EOL" Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten;"
139 EOL" Specular += occLight_Specular(theId) * aSpecl * anAtten;"
8625ef7e 140 EOL"}";
141
67312b79 142//! Function computes contribution of isotropic point light source
143const char THE_FUNC_PBR_pointLight[] =
144 EOL"void pointLight (in int theId,"
145 EOL" in vec3 theNormal,"
146 EOL" in vec3 theView,"
147 EOL" in vec3 thePoint,"
148 EOL" in bool theIsFront)"
149 EOL"{"
9504a30d 150 EOL" vec3 aLight = occLight_Position (theId);"
67312b79 151 EOL" if (occLight_IsHeadlight (theId))"
152 EOL" {"
153 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
154 EOL" }"
155 EOL" aLight -= thePoint;"
156 EOL
157 EOL" float aDist = length (aLight);"
88b312d3 158 EOL" float aRange = occLight_Range (theId);"
159 EOL" float anAtten = occPointLightAttenuation (aDist, aRange);"
160 EOL" if (anAtten <= 0.0) return;"
67312b79 161 EOL" aLight /= aDist;"
162 EOL
67312b79 163 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
9504a30d 164 EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
165 EOL" BaseColor, Metallic, Roughness, IOR,"
166 EOL" occLight_Specular (theId),"
67312b79 167 EOL" occLight_Intensity(theId) * anAtten);"
168 EOL"}";
169
8625ef7e 170//! Function computes contribution of spotlight source
171const char THE_FUNC_spotLight[] =
172 EOL"void spotLight (in int theId,"
173 EOL" in vec3 theNormal,"
174 EOL" in vec3 theView,"
175 EOL" in vec3 thePoint,"
176 EOL" in bool theIsFront)"
177 EOL"{"
9504a30d 178 EOL" vec3 aLight = occLight_Position (theId);"
179 EOL" vec3 aSpotDir = occLight_SpotDirection (theId);"
67312b79 180 EOL" if (!occLight_IsHeadlight (theId))"
8625ef7e 181 EOL" {"
5f4bd4d4 182 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
183 EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
8625ef7e 184 EOL" }"
185 EOL" aLight -= thePoint;"
186 EOL
187 EOL" float aDist = length (aLight);"
88b312d3 188 EOL" float aRange = occLight_Range (theId);"
189 EOL" float anAtten = occPointLightAttenuation (aDist, aRange, occLight_LinearAttenuation (theId), occLight_ConstAttenuation (theId));"
190 EOL" if (anAtten <= 0.0) return;"
191 EOL" aLight /= aDist;"
8625ef7e 192 EOL
193 EOL" aSpotDir = normalize (aSpotDir);"
194 // light cone
195 EOL" float aCosA = dot (aSpotDir, -aLight);"
196 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
197 EOL" {"
198 EOL" return;"
199 EOL" }"
200 EOL
201 EOL" float anExponent = occLight_SpotExponent (theId);"
8625ef7e 202 EOL" if (anExponent > 0.0)"
203 EOL" {"
204 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
205 EOL" }"
206 EOL
207 EOL" vec3 aHalf = normalize (aLight + theView);"
208 EOL
209 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
210 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
211 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
212 EOL
213 EOL" float aSpecl = 0.0;"
214 EOL" if (aNdotL > 0.0)"
215 EOL" {"
216 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
217 EOL" }"
218 EOL
9504a30d 219 EOL" Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten;"
220 EOL" Specular += occLight_Specular(theId) * aSpecl * anAtten;"
8625ef7e 221 EOL"}";
222
67312b79 223//! Function computes contribution of spotlight source
224 const char THE_FUNC_PBR_spotLight[] =
225 EOL"void spotLight (in int theId,"
226 EOL" in vec3 theNormal,"
227 EOL" in vec3 theView,"
228 EOL" in vec3 thePoint,"
229 EOL" in bool theIsFront)"
230 EOL"{"
9504a30d 231 EOL" vec3 aLight = occLight_Position (theId);"
232 EOL" vec3 aSpotDir = occLight_SpotDirection (theId);"
67312b79 233 EOL" if (occLight_IsHeadlight (theId))"
234 EOL" {"
235 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
236 EOL" aSpotDir = vec3 (occWorldViewMatrixInverse * vec4 (aSpotDir, 0.0));"
237 EOL" }"
238 EOL" aLight -= thePoint;"
239 EOL
240 EOL" float aDist = length (aLight);"
88b312d3 241 EOL" float aRange = occLight_Range (theId);"
242 EOL" float anAtten = occPointLightAttenuation (aDist, aRange);"
243 EOL" if (anAtten <= 0.0) return;"
67312b79 244 EOL" aLight /= aDist;"
245 EOL
246 EOL" aSpotDir = normalize (aSpotDir);"
247 // light cone
248 EOL" float aCosA = dot (aSpotDir, -aLight);"
88b312d3 249 EOL" float aRelativeAngle = 2.0 * acos(aCosA) / occLight_SpotCutOff(theId);"
250 EOL" if (aCosA >= 1.0 || aRelativeAngle > 1.0)"
67312b79 251 EOL" {"
252 EOL" return;"
253 EOL" }"
67312b79 254 EOL" float anExponent = occLight_SpotExponent (theId);"
88b312d3 255 EOL" if ((1.0 - aRelativeAngle) <= anExponent)"
67312b79 256 EOL" {"
88b312d3 257 EOL" float anAngularAttenuationOffset = cos(0.5 * occLight_SpotCutOff(theId));"
258 EOL" float anAngularAttenuationScale = 1.0 / max(0.001, cos(0.5 * occLight_SpotCutOff(theId) * (1.0 - anExponent)) - anAngularAttenuationOffset);"
259 EOL" anAngularAttenuationOffset *= -anAngularAttenuationScale;"
260 EOL" float anAngularAttenuantion = clamp(aCosA * anAngularAttenuationScale + anAngularAttenuationOffset, 0.0, 1.0);"
261 EOL" anAtten *= anAngularAttenuantion * anAngularAttenuantion;"
67312b79 262 EOL" }"
67312b79 263 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
88b312d3 264 EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
9504a30d 265 EOL" BaseColor, Metallic, Roughness, IOR,"
266 EOL" occLight_Specular(theId),"
67312b79 267 EOL" occLight_Intensity(theId) * anAtten);"
268 EOL"}";
269
8625ef7e 270//! Function computes contribution of directional light source
271const char THE_FUNC_directionalLight[] =
272 EOL"void directionalLight (in int theId,"
273 EOL" in vec3 theNormal,"
274 EOL" in vec3 theView,"
275 EOL" in bool theIsFront)"
276 EOL"{"
9504a30d 277 EOL" vec3 aLight = normalize (occLight_Position (theId));"
67312b79 278 EOL" if (!occLight_IsHeadlight (theId))"
8625ef7e 279 EOL" {"
5f4bd4d4 280 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
8625ef7e 281 EOL" }"
282 EOL
283 EOL" vec3 aHalf = normalize (aLight + theView);"
284 EOL
285 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
286 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
287 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
288 EOL
289 EOL" float aSpecl = 0.0;"
290 EOL" if (aNdotL > 0.0)"
291 EOL" {"
292 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
293 EOL" }"
294 EOL
9504a30d 295 EOL" Diffuse += occLight_Diffuse (theId) * aNdotL;"
296 EOL" Specular += occLight_Specular (theId) * aSpecl;"
8625ef7e 297 EOL"}";
298
67312b79 299//! Function computes contribution of directional light source
300const char THE_FUNC_PBR_directionalLight[] =
301 EOL"void directionalLight (in int theId,"
302 EOL" in vec3 theNormal,"
303 EOL" in vec3 theView,"
304 EOL" in bool theIsFront)"
305 EOL"{"
9504a30d 306 EOL" vec3 aLight = normalize (occLight_Position (theId));"
67312b79 307 EOL" if (occLight_IsHeadlight (theId))"
308 EOL" {"
309 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 0.0));"
310 EOL" }"
311 EOL
312 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
9504a30d 313 EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
314 EOL" BaseColor, Metallic, Roughness, IOR,"
315 EOL" occLight_Specular (theId),"
67312b79 316 EOL" occLight_Intensity(theId));"
317 EOL"}";
318
f68acbf4 319//! The same as THE_FUNC_directionalLight but for the light with zero index
320//! (avoids limitations on some mobile devices).
321const char THE_FUNC_directionalLightFirst[] =
322 EOL"void directionalLightFirst (in vec3 theNormal,"
323 EOL" in vec3 theView,"
324 EOL" in bool theIsFront)"
325 EOL"{"
9504a30d 326 EOL" vec3 aLight = normalize (occLight_Position(0));"
67312b79 327 EOL" if (!occLight_IsHeadlight (0))"
f68acbf4 328 EOL" {"
5f4bd4d4 329 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
f68acbf4 330 EOL" }"
331 EOL
332 EOL" vec3 aHalf = normalize (aLight + theView);"
333 EOL
334 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
335 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
336 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
337 EOL
338 EOL" float aSpecl = 0.0;"
339 EOL" if (aNdotL > 0.0)"
340 EOL" {"
341 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
342 EOL" }"
343 EOL
9504a30d 344 EOL" Diffuse += occLight_Diffuse(0) * aNdotL;"
345 EOL" Specular += occLight_Specular(0) * aSpecl;"
f68acbf4 346 EOL"}";
347
67312b79 348//! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip.
349const char THE_FUNC_cubemap_vector_transform[] =
350 EOL"vec3 cubemapVectorTransform (in vec3 theVector,"
351 EOL" in int theYCoeff,"
352 EOL" in int theZCoeff)"
353 EOL"{"
354 EOL" theVector = theVector.yzx;"
355 EOL" theVector.y *= float(theYCoeff);"
356 EOL" theVector.z *= float(theZCoeff);"
357 EOL" return theVector;"
358 EOL"}";
359
8625ef7e 360//! Process clipping planes in Fragment Shader.
361//! Should be added at the beginning of the main() function.
1a7ece8f 362const char THE_FRAG_CLIP_PLANES_N[] =
8625ef7e 363 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
364 EOL" {"
365 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
89a929ea 366 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
8625ef7e 367 EOL" {"
89a929ea 368 EOL" discard;"
8625ef7e 369 EOL" }"
370 EOL" }";
371
25c35042 372//! Process chains of clipping planes in Fragment Shader.
373const char THE_FRAG_CLIP_CHAINS_N[] =
374EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)"
375EOL" {"
376EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
377EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
378EOL" {"
379EOL" if (occClipPlaneChains[aPlaneIter] == 1)"
380EOL" {"
381EOL" discard;"
382EOL" }"
383EOL" aPlaneIter += 1;"
384EOL" }"
385EOL" else"
386EOL" {"
387EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];"
388EOL" }"
389EOL" }";
390
1a7ece8f 391//! Process 1 clipping plane in Fragment Shader.
392const char THE_FRAG_CLIP_PLANES_1[] =
393 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
394 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
395 EOL" {"
396 EOL" discard;"
397 EOL" }";
398
399//! Process 2 clipping planes in Fragment Shader.
400const char THE_FRAG_CLIP_PLANES_2[] =
401 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
402 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
403 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
404 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
405 EOL" {"
406 EOL" discard;"
407 EOL" }";
408
25c35042 409//! Process a chain of 2 clipping planes in Fragment Shader (3/4 section).
410const char THE_FRAG_CLIP_CHAINS_2[] =
411EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
412EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
413EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
414EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
415EOL" {"
416EOL" discard;"
417EOL" }";
418
2a332745 419//! Modify color for Wireframe presentation.
420const char THE_FRAG_WIREFRAME_COLOR[] =
421EOL"vec4 getFinalColor(void)"
422EOL"{"
423EOL" float aDistance = min (min (EdgeDistance[0], EdgeDistance[1]), EdgeDistance[2]);"
424EOL" bool isHollow = occWireframeColor.a < 0.0;"
425EOL" float aMixVal = smoothstep (occLineWidth - occLineFeather * 0.5, occLineWidth + occLineFeather * 0.5, aDistance);"
426EOL" vec4 aMixColor = isHollow"
427EOL" ? vec4 (getColor().rgb, 1.0 - aMixVal)" // edges only (of interior color)
428EOL" : mix (occWireframeColor, getColor(), aMixVal);" // interior + edges
429EOL" return aMixColor;"
430EOL"}";
431
6ef0d6f1 432//! Compute gl_Position vertex shader output.
433const char THE_VERT_gl_Position[] =
434EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;";
435
436//! Displace gl_Position alongside vertex normal for outline rendering.
437//! This code adds silhouette only for smooth surfaces of closed primitive, and produces visual artifacts on sharp edges.
438const char THE_VERT_gl_Position_OUTLINE[] =
439EOL" float anOutlineDisp = occOrthoScale > 0.0 ? occOrthoScale : gl_Position.w;"
440EOL" vec4 anOutlinePos = occVertex + vec4 (occNormal * (occSilhouetteThickness * anOutlineDisp), 0.0);"
441EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * anOutlinePos;";
442
8613985b 443#if !defined(GL_ES_VERSION_2_0)
444
445 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
446 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
447 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
448 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
449
450 //! Bind FFP light source.
992ed6b3 451 static void bindLight (const Graphic3d_CLight& theLight,
8613985b 452 const GLenum theLightGlId,
453 const OpenGl_Mat4& theModelView,
454 OpenGl_Context* theCtx)
455 {
456 // the light is a headlight?
992ed6b3 457 if (theLight.IsHeadlight())
8613985b 458 {
459 theCtx->core11->glMatrixMode (GL_MODELVIEW);
460 theCtx->core11->glLoadIdentity();
461 }
462
463 // setup light type
992ed6b3 464 const Graphic3d_Vec4& aLightColor = theLight.PackedColor();
465 switch (theLight.Type())
8613985b 466 {
467 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
468 case Graphic3d_TOLS_DIRECTIONAL:
469 {
470 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
88b312d3 471 const OpenGl_Vec4 anInfDir = -theLight.PackedDirectionRange();
8613985b 472
473 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
474 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
992ed6b3 475 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
476 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
8613985b 477 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
478 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
479 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
480 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
481 break;
482 }
483 case Graphic3d_TOLS_POSITIONAL:
484 {
485 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
992ed6b3 486 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 487 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
992ed6b3 488 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
489 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
8613985b 490 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
491 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
492 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
493 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
494 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
495 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
9504a30d 496 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
8613985b 497 break;
498 }
499 case Graphic3d_TOLS_SPOT:
500 {
992ed6b3 501 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 502 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
992ed6b3 503 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
504 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
8613985b 505 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
88b312d3 506 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.PackedDirectionRange().GetData());
8613985b 507 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
508 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
509 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
510 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
511 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
512 break;
513 }
514 }
515
516 // restore matrix in case of headlight
992ed6b3 517 if (theLight.IsHeadlight())
8613985b 518 {
519 theCtx->core11->glLoadMatrixf (theModelView.GetData());
520 }
521
522 glEnable (theLightGlId);
523 }
524#endif
525
d95f5ce1 526 //! Generate map key for light sources configuration.
527 static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights)
528 {
529 if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
530 {
531 return TCollection_AsciiString ("l_") + theLights->KeyEnabledLong();
532 }
533
534 const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled());
535 return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit;
536 }
8625ef7e 537}
538
30f0ad28 539// =======================================================================
540// function : OpenGl_ShaderManager
541// purpose : Creates new empty shader manager
542// =======================================================================
543OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
8613985b 544: myFfpProgram (new OpenGl_ShaderProgramFFP()),
545 myShadingModel (Graphic3d_TOSM_VERTEX),
6ef0d6f1 546 myUnlitPrograms (new OpenGl_SetOfPrograms()),
8625ef7e 547 myContext (theContext),
ba00aab7 548 mySRgbState (theContext->ToRenderSRGB()),
7c3ef2f7 549 myHasLocalOrigin (Standard_False),
e6804ff7 550 myLastView (NULL)
30f0ad28 551{
256f9ac0 552 //
30f0ad28 553}
554
555// =======================================================================
556// function : ~OpenGl_ShaderManager
557// purpose : Releases resources of shader manager
558// =======================================================================
559OpenGl_ShaderManager::~OpenGl_ShaderManager()
560{
561 myProgramList.Clear();
67312b79 562 if (!myPBREnvironment.IsNull())
563 {
564 myPBREnvironment->Release (myContext);
565 }
30f0ad28 566}
567
05e2200b 568// =======================================================================
569// function : clear
570// purpose :
571// =======================================================================
572void OpenGl_ShaderManager::clear()
573{
574 myProgramList.Clear();
575 myLightPrograms.Nullify();
6ef0d6f1 576 myUnlitPrograms = new OpenGl_SetOfPrograms();
577 myOutlinePrograms.Nullify();
05e2200b 578 myMapOfLightPrograms.Clear();
579 myFontProgram.Nullify();
ba00aab7 580 myBlitPrograms[0].Init (Handle(OpenGl_ShaderProgram)());
581 myBlitPrograms[1].Init (Handle(OpenGl_ShaderProgram)());
98b15dbf 582 myBoundBoxProgram.Nullify();
583 myBoundBoxVertBuffer.Nullify();
f978241f 584 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
585 {
586 myStereoPrograms[aModeIter].Nullify();
587 }
05e2200b 588 switchLightPrograms();
589}
590
30f0ad28 591// =======================================================================
592// function : Create
593// purpose : Creates new shader program
594// =======================================================================
8625ef7e 595Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
596 TCollection_AsciiString& theShareKey,
597 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 598{
392ac980 599 theProgram.Nullify();
600 if (theProxy.IsNull())
30f0ad28 601 {
8625ef7e 602 return Standard_False;
30f0ad28 603 }
392ac980 604
605 theShareKey = theProxy->GetId();
606 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
607 {
05dd08ce 608 if (theProgram->Share())
609 {
610 myProgramList.Append (theProgram);
611 }
8625ef7e 612 return Standard_True;
392ac980 613 }
614
615 theProgram = new OpenGl_ShaderProgram (theProxy);
616 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
30f0ad28 617 {
392ac980 618 theProgram->Release (myContext);
619 theShareKey.Clear();
620 theProgram.Nullify();
8625ef7e 621 return Standard_False;
30f0ad28 622 }
30f0ad28 623
392ac980 624 myProgramList.Append (theProgram);
625 myContext->ShareResource (theShareKey, theProgram);
8625ef7e 626 return Standard_True;
30f0ad28 627}
628
629// =======================================================================
630// function : Unregister
631// purpose : Removes specified shader program from the manager
632// =======================================================================
392ac980 633void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
634 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 635{
636 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
637 {
638 if (anIt.Value() == theProgram)
639 {
392ac980 640 if (!theProgram->UnShare())
641 {
642 theShareKey.Clear();
643 theProgram.Nullify();
644 return;
645 }
646
30f0ad28 647 myProgramList.Remove (anIt);
648 break;
649 }
650 }
651
652 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
653 if (anID.IsEmpty())
654 {
655 myContext->DelayedRelease (theProgram);
656 theProgram.Nullify();
657 }
658 else
659 {
660 theProgram.Nullify();
05dd08ce 661 myContext->ReleaseResource (anID, Standard_True);
30f0ad28 662 }
663}
664
665// =======================================================================
666// function : ShaderPrograms
667// purpose : Returns list of registered shader programs
668// =======================================================================
669const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
670{
671 return myProgramList;
672}
673
674// =======================================================================
675// function : Empty
676// purpose : Returns true if no program objects are attached
677// =======================================================================
678Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
679{
680 return myProgramList.IsEmpty();
681}
682
256f9ac0 683// =======================================================================
684// function : switchLightPrograms
685// purpose :
686// =======================================================================
687void OpenGl_ShaderManager::switchLightPrograms()
688{
992ed6b3 689 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
dc89236f 690 if (aLights.IsNull())
256f9ac0 691 {
6ef0d6f1 692 if (!myMapOfLightPrograms.Find ("unlit", myLightPrograms))
693 {
694 myLightPrograms = new OpenGl_SetOfShaderPrograms (myUnlitPrograms);
695 myMapOfLightPrograms.Bind ("unlit", myLightPrograms);
696 }
dc89236f 697 return;
698 }
699
d95f5ce1 700 const TCollection_AsciiString aKey = genLightKey (aLights);
256f9ac0 701 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
702 {
703 myLightPrograms = new OpenGl_SetOfShaderPrograms();
704 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
705 }
706}
707
ba00aab7 708// =======================================================================
709// function : UpdateSRgbState
710// purpose :
711// =======================================================================
712void OpenGl_ShaderManager::UpdateSRgbState()
713{
714 if (mySRgbState == myContext->ToRenderSRGB())
715 {
716 return;
717 }
718
719 mySRgbState = myContext->ToRenderSRGB();
720
721 // special cases - GLSL programs dealing with sRGB/linearRGB internally
722 myStereoPrograms[Graphic3d_StereoMode_Anaglyph].Nullify();
723}
724
30f0ad28 725// =======================================================================
726// function : UpdateLightSourceStateTo
727// purpose : Updates state of OCCT light sources
728// =======================================================================
67312b79 729void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
730 Standard_Integer theSpecIBLMapLevels)
30f0ad28 731{
732 myLightSourceState.Set (theLights);
67312b79 733 myLightSourceState.SetSpecIBLMapLevels (theSpecIBLMapLevels);
30f0ad28 734 myLightSourceState.Update();
256f9ac0 735 switchLightPrograms();
736}
737
7c3ef2f7 738// =======================================================================
739// function : UpdateLightSourceState
740// purpose :
741// =======================================================================
742void OpenGl_ShaderManager::UpdateLightSourceState()
743{
744 myLightSourceState.Update();
745}
746
256f9ac0 747// =======================================================================
748// function : SetShadingModel
749// purpose :
750// =======================================================================
c357e426 751void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
256f9ac0 752{
dc89236f 753 if (theModel == Graphic3d_TOSM_DEFAULT)
754 {
755 throw Standard_ProgramError ("OpenGl_ShaderManager::SetShadingModel() - attempt to set invalid Shading Model!");
756 }
757
256f9ac0 758 myShadingModel = theModel;
759 switchLightPrograms();
30f0ad28 760}
761
762// =======================================================================
763// function : SetProjectionState
764// purpose : Sets new state of OCCT projection transform
765// =======================================================================
c827ea3a 766void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
30f0ad28 767{
768 myProjectionState.Set (theProjectionMatrix);
769 myProjectionState.Update();
770}
771
772// =======================================================================
773// function : SetModelWorldState
774// purpose : Sets new state of OCCT model-world transform
775// =======================================================================
c827ea3a 776void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
30f0ad28 777{
778 myModelWorldState.Set (theModelWorldMatrix);
779 myModelWorldState.Update();
780}
781
782// =======================================================================
783// function : SetWorldViewState
784// purpose : Sets new state of OCCT world-view transform
785// =======================================================================
c827ea3a 786void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
30f0ad28 787{
788 myWorldViewState.Set (theWorldViewMatrix);
789 myWorldViewState.Update();
790}
791
30f0ad28 792// =======================================================================
8cf3bf84 793// function : pushLightSourceState
794// purpose :
30f0ad28 795// =======================================================================
8cf3bf84 796void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
30f0ad28 797{
8613985b 798 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
799 if (theProgram == myFfpProgram)
30f0ad28 800 {
8613985b 801 #if !defined(GL_ES_VERSION_2_0)
802 if (myContext->core11 == NULL)
803 {
804 return;
805 }
806
daf73ab7 807 GLenum aLightGlId = GL_LIGHT0;
daf73ab7 808 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
992ed6b3 809 for (Graphic3d_LightSet::Iterator aLightIt (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
810 aLightIt.More(); aLightIt.Next())
8613985b 811 {
992ed6b3 812 if (aLightGlId > GL_LIGHT7) // only 8 lights in FFP...
8613985b 813 {
992ed6b3 814 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
815 "Warning: light sources limit (8) has been exceeded within Fixed-function pipeline.");
816 continue;
8613985b 817 }
992ed6b3 818
819 bindLight (*aLightIt.Value(), aLightGlId, aModelView, myContext);
820 ++aLightGlId;
daf73ab7 821 }
8613985b 822
daf73ab7 823 // apply accumulated ambient color
992ed6b3 824 const Graphic3d_Vec4 anAmbient = !myLightSourceState.LightSources().IsNull()
825 ? myLightSourceState.LightSources()->AmbientColor()
826 : Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
daf73ab7 827 myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
8613985b 828
daf73ab7 829 // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
830 // therefore managing the state here does not have any effect - do it just for consistency.
831 if (aLightGlId != GL_LIGHT0)
832 {
833 ::glEnable (GL_LIGHTING);
834 }
835 else
836 {
837 ::glDisable (GL_LIGHTING);
838 }
839 // switch off unused lights
840 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
841 {
842 ::glDisable (aLightGlId);
8613985b 843 }
844 #endif
30f0ad28 845 return;
846 }
30f0ad28 847
daf73ab7 848 const Standard_Integer aNbLightsMax = theProgram->NbLightsMax();
849 const GLint anAmbientLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT);
850 if (aNbLightsMax == 0
851 && anAmbientLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
01eaf654 852 {
daf73ab7 853 return;
01eaf654 854 }
855
daf73ab7 856 if (myLightTypeArray.Size() < aNbLightsMax)
857 {
858 myLightTypeArray .Resize (0, aNbLightsMax - 1, false);
859 myLightParamsArray.Resize (0, aNbLightsMax - 1, false);
860 }
861 for (Standard_Integer aLightIt = 0; aLightIt < aNbLightsMax; ++aLightIt)
862 {
9504a30d 863 myLightTypeArray.SetValue (aLightIt, -1);
daf73ab7 864 }
865
992ed6b3 866 if (myLightSourceState.LightSources().IsNull()
daf73ab7 867 || myLightSourceState.LightSources()->IsEmpty())
12381341 868 {
30f0ad28 869 theProgram->SetUniform (myContext,
12381341 870 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
871 0);
30f0ad28 872 theProgram->SetUniform (myContext,
daf73ab7 873 anAmbientLoc,
12381341 874 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
01eaf654 875 theProgram->SetUniform (myContext,
876 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
9504a30d 877 aNbLightsMax,
878 &myLightTypeArray.First());
12381341 879 return;
880 }
30f0ad28 881
12381341 882 Standard_Integer aLightsNb = 0;
992ed6b3 883 for (Graphic3d_LightSet::Iterator anIter (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
884 anIter.More(); anIter.Next())
12381341 885 {
992ed6b3 886 const Graphic3d_CLight& aLight = *anIter.Value();
887 if (aLightsNb >= aNbLightsMax)
12381341 888 {
daf73ab7 889 if (aNbLightsMax != 0)
890 {
891 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
892 TCollection_AsciiString("Warning: light sources limit (") + aNbLightsMax + ") has been exceeded.");
893 }
12381341 894 continue;
895 }
30f0ad28 896
9504a30d 897 Standard_Integer& aLightType = myLightTypeArray .ChangeValue (aLightsNb);
daf73ab7 898 OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray.ChangeValue (aLightsNb);
992ed6b3 899 if (!aLight.IsEnabled()) // has no affect with Graphic3d_LightSet::IterationFilter_ExcludeDisabled - here just for consistency
7c3ef2f7 900 {
992ed6b3 901 // 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
9504a30d 902 aLightType = -1; // Graphic3d_TOLS_AMBIENT can be used instead
903 aLightParams.Color = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f);
992ed6b3 904 ++aLightsNb;
905 continue;
7c3ef2f7 906 }
992ed6b3 907
ba00aab7 908 // ignoring OpenGl_Context::ToRenderSRGB() for light colors,
909 // as non-absolute colors for lights are rare and require tuning anyway
9504a30d 910 aLightType = aLight.Type();
992ed6b3 911 aLightParams.Color = aLight.PackedColor();
67312b79 912 aLightParams.Color.a() = aLight.Intensity(); // used by PBR and ignored by old shading model
992ed6b3 913 if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
7c3ef2f7 914 {
88b312d3 915 aLightParams.Position = -aLight.PackedDirectionRange();
992ed6b3 916 }
917 else if (!aLight.IsHeadlight())
918 {
919 aLightParams.Position.x() = static_cast<float>(aLight.Position().X() - myLocalOrigin.X());
920 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y() - myLocalOrigin.Y());
921 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z() - myLocalOrigin.Z());
7c3ef2f7 922 }
923 else
924 {
992ed6b3 925 aLightParams.Position.x() = static_cast<float>(aLight.Position().X());
926 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y());
927 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z());
7c3ef2f7 928 }
9504a30d 929 aLightParams.Position.w() = aLight.IsHeadlight() ? 1.0f : 0.0f;
7c3ef2f7 930
992ed6b3 931 if (aLight.Type() == Graphic3d_TOLS_SPOT)
12381341 932 {
88b312d3 933 aLightParams.Direction = aLight.PackedDirectionRange();
934 }
935 if (aLight.Type() == Graphic3d_TOLS_POSITIONAL)
936 {
937 aLightParams.Direction.w() = aLight.Range();
30f0ad28 938 }
992ed6b3 939 aLightParams.Parameters = aLight.PackedParams();
12381341 940 ++aLightsNb;
941 }
30f0ad28 942
992ed6b3 943 const Graphic3d_Vec4& anAmbient = myLightSourceState.LightSources()->AmbientColor();
12381341 944 theProgram->SetUniform (myContext,
945 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
946 aLightsNb);
947 theProgram->SetUniform (myContext,
daf73ab7 948 anAmbientLoc,
12381341 949 anAmbient);
01eaf654 950 theProgram->SetUniform (myContext,
951 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
9504a30d 952 aNbLightsMax,
953 &myLightTypeArray.First());
12381341 954 if (aLightsNb > 0)
955 {
4fe9ad57 956 theProgram->SetUniform (myContext,
957 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
958 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
daf73ab7 959 myLightParamsArray.First().Packed());
30f0ad28 960 }
67312b79 961
962 if (const OpenGl_ShaderUniformLocation aLocation = theProgram->GetStateLocation (OpenGl_OCCT_NB_SPEC_IBL_LEVELS))
963 {
964 theProgram->SetUniform (myContext, aLocation, myLightSourceState.SpecIBLMapLevels());
965 }
30f0ad28 966}
967
968// =======================================================================
8cf3bf84 969// function : pushProjectionState
970// purpose :
30f0ad28 971// =======================================================================
8cf3bf84 972void OpenGl_ShaderManager::pushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
30f0ad28 973{
8613985b 974 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
975 if (theProgram == myFfpProgram)
976 {
977 #if !defined(GL_ES_VERSION_2_0)
978 if (myContext->core11 != NULL)
979 {
980 myContext->core11->glMatrixMode (GL_PROJECTION);
981 myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
982 }
983 #endif
984 return;
985 }
986
30f0ad28 987 theProgram->SetUniform (myContext,
988 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
989 myProjectionState.ProjectionMatrix());
990
991 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
992 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
993 {
994 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
995 }
996
997 theProgram->SetUniform (myContext,
998 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
999 myProjectionState.ProjectionMatrix(), true);
1000
1001 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
1002 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1003 {
1004 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
1005 }
30f0ad28 1006}
1007
1008// =======================================================================
8cf3bf84 1009// function : pushModelWorldState
1010// purpose :
30f0ad28 1011// =======================================================================
8cf3bf84 1012void OpenGl_ShaderManager::pushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
30f0ad28 1013{
8613985b 1014 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
1015 if (theProgram == myFfpProgram)
1016 {
1017 #if !defined(GL_ES_VERSION_2_0)
1018 if (myContext->core11 != NULL)
1019 {
1020 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1021 myContext->core11->glMatrixMode (GL_MODELVIEW);
1022 myContext->core11->glLoadMatrixf (aModelView.GetData());
1023 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
1024 }
1025 #endif
1026 return;
1027 }
1028
30f0ad28 1029 theProgram->SetUniform (myContext,
1030 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
1031 myModelWorldState.ModelWorldMatrix());
1032
1033 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
1034 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1035 {
1036 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
1037 }
1038
1039 theProgram->SetUniform (myContext,
1040 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
1041 myModelWorldState.ModelWorldMatrix(), true);
1042
1043 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
1044 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1045 {
1046 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
1047 }
30f0ad28 1048}
1049
1050// =======================================================================
8cf3bf84 1051// function : pushWorldViewState
1052// purpose :
30f0ad28 1053// =======================================================================
8cf3bf84 1054void OpenGl_ShaderManager::pushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
30f0ad28 1055{
1056 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
1057 {
1058 return;
1059 }
1060
8613985b 1061 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
1062 if (theProgram == myFfpProgram)
1063 {
1064 #if !defined(GL_ES_VERSION_2_0)
1065 if (myContext->core11 != NULL)
1066 {
1067 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1068 myContext->core11->glMatrixMode (GL_MODELVIEW);
1069 myContext->core11->glLoadMatrixf (aModelView.GetData());
1070 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
1071 }
1072 #endif
1073 return;
1074 }
1075
30f0ad28 1076 theProgram->SetUniform (myContext,
1077 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
1078 myWorldViewState.WorldViewMatrix());
1079
1080 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
1081 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1082 {
1083 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
1084 }
1085
1086 theProgram->SetUniform (myContext,
1087 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
1088 myWorldViewState.WorldViewMatrix(), true);
1089
1090 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
1091 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1092 {
1093 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
1094 }
30f0ad28 1095}
1096
1097// =======================================================================
1098// function : UpdateClippingState
1099// purpose : Updates state of OCCT clipping planes
1100// =======================================================================
1101void OpenGl_ShaderManager::UpdateClippingState()
1102{
1103 myClippingState.Update();
1104}
1105
1106// =======================================================================
1107// function : RevertClippingState
1108// purpose : Reverts state of OCCT clipping planes
1109// =======================================================================
1110void OpenGl_ShaderManager::RevertClippingState()
1111{
1112 myClippingState.Revert();
1113}
1114
1115// =======================================================================
8cf3bf84 1116// function : pushClippingState
1117// purpose :
30f0ad28 1118// =======================================================================
8cf3bf84 1119void OpenGl_ShaderManager::pushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
30f0ad28 1120{
12381341 1121 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
8613985b 1122 if (theProgram == myFfpProgram)
1123 {
1124 #if !defined(GL_ES_VERSION_2_0)
1125 if (myContext->core11 == NULL)
1126 {
1127 return;
1128 }
1129
daf73ab7 1130 const Standard_Integer aNbMaxPlanes = myContext->MaxClipPlanes();
1131 if (myClipPlaneArrayFfp.Size() < aNbMaxPlanes)
1132 {
1133 myClipPlaneArrayFfp.Resize (0, aNbMaxPlanes - 1, false);
1134 }
1135
8613985b 1136 Standard_Integer aPlaneId = 0;
1137 Standard_Boolean toRestoreModelView = Standard_False;
25c35042 1138 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
8613985b 1139 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1140 {
1141 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
25c35042 1142 if (aPlaneIter.IsDisabled()
1143 || aPlane->IsChain()
1144 || (aPlane == aCappedChain
1145 && myContext->Clipping().IsCappingEnableAllExcept()))
8613985b 1146 {
1147 continue;
1148 }
1149 else if (aPlaneId >= aNbMaxPlanes)
1150 {
daf73ab7 1151 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
8613985b 1152 TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
1153 break;
1154 }
1155
1156 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
daf73ab7 1157 OpenGl_Vec4d& aPlaneEq = myClipPlaneArrayFfp.ChangeValue (aPlaneId);
8613985b 1158 aPlaneEq.x() = anEquation.x();
1159 aPlaneEq.y() = anEquation.y();
1160 aPlaneEq.z() = anEquation.z();
1161 aPlaneEq.w() = anEquation.w();
1162 if (myHasLocalOrigin)
1163 {
1164 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
1165 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
1166 aPlaneEq.w() = aD;
1167 }
1168
1169 const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
1170 if (anFfpPlaneID == GL_CLIP_PLANE0)
1171 {
1172 // set either identity or pure view matrix
1173 toRestoreModelView = Standard_True;
1174 myContext->core11->glMatrixMode (GL_MODELVIEW);
1175 myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
1176 }
1177
1178 ::glEnable (anFfpPlaneID);
1179 myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
1180
1181 ++aPlaneId;
1182 }
1183
1184 // switch off unused lights
1185 for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
1186 {
1187 ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
1188 }
1189
1190 // restore combined model-view matrix
1191 if (toRestoreModelView)
1192 {
1193 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1194 myContext->core11->glLoadMatrixf (aModelView.GetData());
1195 }
1196 #endif
1197 return;
1198 }
1199
12381341 1200 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
89a929ea 1201 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
12381341 1202 {
1203 return;
1204 }
1205
daf73ab7 1206 const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax();
25c35042 1207 const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
3202bf1e 1208 if (aNbPlanes < 1)
12381341 1209 {
25c35042 1210 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0);
12381341 1211 return;
1212 }
1213
daf73ab7 1214 if (myClipPlaneArray.Size() < aNbClipPlanesMax)
1215 {
1216 myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false);
25c35042 1217 myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false);
daf73ab7 1218 }
1219
1220 Standard_Integer aPlaneId = 0;
25c35042 1221 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
3202bf1e 1222 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
12381341 1223 {
3202bf1e 1224 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1225 if (aPlaneIter.IsDisabled())
30f0ad28 1226 {
12381341 1227 continue;
30f0ad28 1228 }
25c35042 1229
1230 if (myContext->Clipping().IsCappingDisableAllExcept())
89a929ea 1231 {
25c35042 1232 // enable only specific (sub) plane
1233 if (aPlane != aCappedChain)
1234 {
1235 continue;
1236 }
1237
1238 Standard_Integer aSubPlaneIndex = 1;
1239 for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1240 {
1241 if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane())
1242 {
1243 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1);
1244 break;
1245 }
1246 }
89a929ea 1247 break;
1248 }
25c35042 1249 else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept()
1250 {
1251 // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane
1252 if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax)
1253 {
1254 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1255 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1256 break;
1257 }
30f0ad28 1258
25c35042 1259 Standard_Integer aSubPlaneIndex = 1;
1260 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1261 {
1262 if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane())
1263 {
1264 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1);
1265 }
1266 }
1267 }
1268 else
7c3ef2f7 1269 {
25c35042 1270 // normal case
1271 if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax)
1272 {
1273 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1274 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1275 break;
1276 }
1277 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
1278 {
1279 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes());
1280 }
7c3ef2f7 1281 }
30f0ad28 1282 }
5495fa7e 1283
25c35042 1284 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId);
daf73ab7 1285 theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First());
25c35042 1286 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First());
30f0ad28 1287}
1288
8613985b 1289// =======================================================================
8cf3bf84 1290// function : pushMaterialState
8613985b 1291// purpose :
1292// =======================================================================
8cf3bf84 1293void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
8613985b 1294{
8613985b 1295 const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
1296 const OpenGl_Material& aBackMat = myMaterialState.BackMaterial();
1297 theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
1298 if (theProgram == myFfpProgram)
1299 {
1300 #if !defined(GL_ES_VERSION_2_0)
1301 if (myContext->core11 == NULL)
1302 {
1303 return;
1304 }
1305
c40eb6b9 1306 if (myMaterialState.AlphaCutoff() < ShortRealLast())
1307 {
1308 glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff());
1309 glEnable (GL_ALPHA_TEST);
1310 }
1311 else
1312 {
1313 glDisable (GL_ALPHA_TEST);
1314 }
1315
8613985b 1316 const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
67312b79 1317 myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Common.Ambient.GetData());
1318 myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Common.Diffuse.GetData());
1319 myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Common.Specular.GetData());
1320 myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Common.Emission.GetData());
1321 myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Common.Shine());
8613985b 1322 if (myMaterialState.ToDistinguish())
1323 {
67312b79 1324 myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Common.Ambient.GetData());
1325 myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Common.Diffuse.GetData());
1326 myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Common.Specular.GetData());
1327 myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Common.Emission.GetData());
1328 myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Common.Shine());
8613985b 1329 }
1330 #endif
1331 return;
1332 }
1333
c40eb6b9 1334 theProgram->SetUniform (myContext,
1335 theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF),
1336 myMaterialState.AlphaCutoff());
8613985b 1337 theProgram->SetUniform (myContext,
1338 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
1339 myMaterialState.ToMapTexture() ? 1 : 0);
1340 theProgram->SetUniform (myContext,
1341 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
1342 myMaterialState.ToDistinguish() ? 1 : 0);
1343
67312b79 1344 if (const OpenGl_ShaderUniformLocation& aLocPbrFront = theProgram->GetStateLocation (OpenGl_OCCT_PBR_FRONT_MATERIAL))
8613985b 1345 {
67312b79 1346 theProgram->SetUniform (myContext, aLocPbrFront, OpenGl_MaterialPBR::NbOfVec4(),
1347 aFrontMat.Pbr.Packed());
8613985b 1348 }
67312b79 1349 if (const OpenGl_ShaderUniformLocation aLocPbrBack = theProgram->GetStateLocation (OpenGl_OCCT_PBR_BACK_MATERIAL))
8613985b 1350 {
67312b79 1351 theProgram->SetUniform (myContext, aLocPbrBack, OpenGl_MaterialPBR::NbOfVec4(),
1352 aBackMat.Pbr.Packed());
1353 }
1354 if (const OpenGl_ShaderUniformLocation aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_FRONT_MATERIAL))
1355 {
1356 theProgram->SetUniform (myContext, aLocFront, OpenGl_MaterialCommon::NbOfVec4(),
1357 aFrontMat.Common.Packed());
1358 }
1359 if (const OpenGl_ShaderUniformLocation aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_BACK_MATERIAL))
1360 {
1361 theProgram->SetUniform (myContext, aLocBack, OpenGl_MaterialCommon::NbOfVec4(),
1362 aBackMat.Common.Packed());
8613985b 1363 }
1364}
1365
a1073ae2 1366// =======================================================================
8cf3bf84 1367// function : pushOitState
1368// purpose :
a1073ae2 1369// =======================================================================
8cf3bf84 1370void OpenGl_ShaderManager::pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
a1073ae2 1371{
a1073ae2 1372 const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
1373 if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
1374 {
1375 theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
1376 }
1377
1378 const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
1379 if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
1380 {
1381 theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
1382 }
1383}
1384
2a332745 1385// =======================================================================
1386// function : PushInteriorState
1387// purpose :
1388// =======================================================================
1389void OpenGl_ShaderManager::PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram,
bf5f0ca2 1390 const Handle(Graphic3d_Aspects)& theAspect) const
2a332745 1391{
1392 if (theProgram.IsNull()
1393 || !theProgram->IsValid())
1394 {
1395 return;
1396 }
1397
2a332745 1398 if (const OpenGl_ShaderUniformLocation aLocLineWidth = theProgram->GetStateLocation (OpenGl_OCCT_LINE_WIDTH))
1399 {
1400 theProgram->SetUniform (myContext, aLocLineWidth, theAspect->EdgeWidth() * myContext->LineWidthScale());
1401 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCCT_LINE_FEATHER), myContext->LineFeather() * myContext->LineWidthScale());
1402 }
1403 if (const OpenGl_ShaderUniformLocation aLocWireframeColor = theProgram->GetStateLocation (OpenGl_OCCT_WIREFRAME_COLOR))
1404 {
1405 if (theAspect->InteriorStyle() == Aspect_IS_HOLLOW)
1406 {
1407 theProgram->SetUniform (myContext, aLocWireframeColor, OpenGl_Vec4 (-1.0f, -1.0f, -1.0f, -1.0f));
1408 }
1409 else
1410 {
ba00aab7 1411 theProgram->SetUniform (myContext, aLocWireframeColor, myContext->Vec4FromQuantityColor (theAspect->EdgeColorRGBA()));
2a332745 1412 }
1413 }
1414 if (const OpenGl_ShaderUniformLocation aLocQuadModeState = theProgram->GetStateLocation (OpenGl_OCCT_QUAD_MODE_STATE))
1415 {
1416 theProgram->SetUniform (myContext, aLocQuadModeState, theAspect->ToSkipFirstEdge() ? 1 : 0);
1417 }
1418}
1419
30f0ad28 1420// =======================================================================
e135a155 1421// function : PushState
30f0ad28 1422// purpose : Pushes state of OCCT graphics parameters to the program
1423// =======================================================================
08669adf 1424void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram,
1425 Graphic3d_TypeOfShadingModel theShadingModel) const
30f0ad28 1426{
8613985b 1427 const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
1428 PushClippingState (aProgram);
1429 PushWorldViewState (aProgram);
1430 PushModelWorldState (aProgram);
1431 PushProjectionState (aProgram);
1432 PushLightSourceState (aProgram);
1433 PushMaterialState (aProgram);
a1073ae2 1434 PushOitState (aProgram);
8cf3bf84 1435
1436 if (!theProgram.IsNull())
1437 {
1438 if (const OpenGl_ShaderUniformLocation& aLocViewPort = theProgram->GetStateLocation (OpenGl_OCCT_VIEWPORT))
1439 {
1440 theProgram->SetUniform (myContext, aLocViewPort, OpenGl_Vec4 ((float )myContext->Viewport()[0], (float )myContext->Viewport()[1],
1441 (float )myContext->Viewport()[2], (float )myContext->Viewport()[3]));
1442 }
1443 }
08669adf 1444#if !defined(GL_ES_VERSION_2_0)
1445 else if (myContext->core11 != NULL)
1446 {
1447 // manage FFP lighting
1448 myContext->SetShadeModel (theShadingModel);
1449 if (theShadingModel == Graphic3d_TOSM_UNLIT)
1450 {
1451 glDisable (GL_LIGHTING);
1452 }
1453 else
1454 {
1455 glEnable (GL_LIGHTING);
1456 }
1457 }
1458#else
1459 (void )theShadingModel;
1460#endif
12381341 1461}
8625ef7e 1462
1463// =======================================================================
1464// function : prepareStdProgramFont
1465// purpose :
1466// =======================================================================
1467Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1468{
3b4c6945 1469 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
737e9a8d 1470 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
3b4c6945 1471 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1472
6ef0d6f1 1473 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1474 + EOL"void main()"
3b4c6945 1475 EOL"{"
1476 EOL" TexCoord = occTexCoord.st;"
6ef0d6f1 1477 + THE_VERT_gl_Position
1478 + EOL"}";
b990e557 1479
4e1523ef 1480 TCollection_AsciiString
cc8cbabe 1481 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }";
4e1523ef 1482#if !defined(GL_ES_VERSION_2_0)
1483 if (myContext->core11 == NULL)
1484 {
cc8cbabe 1485 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }";
4e1523ef 1486 }
1487#endif
1488
3b4c6945 1489 TCollection_AsciiString aSrcFrag =
1490 aSrcGetAlpha
4e1523ef 1491 + EOL"void main()"
b990e557 1492 EOL"{"
1493 EOL" vec4 aColor = occColor;"
1494 EOL" aColor.a *= getAlpha();"
1495 EOL" if (aColor.a <= 0.285) discard;"
b17e5bae 1496 EOL" occSetFragColor (aColor);"
b990e557 1497 EOL"}";
8625ef7e 1498
3b4c6945 1499 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
d95f5ce1 1500 defaultGlslVersion (aProgramSrc, "font", 0);
737e9a8d 1501 aProgramSrc->SetDefaultSampler (false);
daf73ab7 1502 aProgramSrc->SetNbLightsMax (0);
1503 aProgramSrc->SetNbClipPlanesMax (0);
3b4c6945 1504 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1505 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
8625ef7e 1506 TCollection_AsciiString aKey;
1507 if (!Create (aProgramSrc, aKey, myFontProgram))
1508 {
1509 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1510 return Standard_False;
1511 }
1512 return Standard_True;
1513}
1514
ba00aab7 1515// =======================================================================
1516// function : BindFboBlitProgram
1517// purpose :
1518// =======================================================================
1519Standard_Boolean OpenGl_ShaderManager::BindFboBlitProgram (Standard_Integer theNbSamples,
1520 Standard_Boolean theIsFallback_sRGB)
1521{
1522 NCollection_Array1<Handle(OpenGl_ShaderProgram)>& aList = myBlitPrograms[theIsFallback_sRGB ? 1 : 0];
1523 Standard_Integer aNbSamples = Max (theNbSamples, 1);
1524 if (aNbSamples > aList.Upper())
1525 {
1526 aList.Resize (1, aNbSamples, true);
1527 }
1528
1529 Handle(OpenGl_ShaderProgram)& aProg = aList[aNbSamples];
1530 if (aProg.IsNull())
1531 {
1532 prepareStdProgramFboBlit (aProg, aNbSamples, theIsFallback_sRGB);
1533 }
1534 return !aProg.IsNull()
1535 && myContext->BindProgram (aProg);
1536}
1537
8625ef7e 1538// =======================================================================
b86bb3df 1539// function : prepareStdProgramFboBlit
1540// purpose :
1541// =======================================================================
ba00aab7 1542Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit (Handle(OpenGl_ShaderProgram)& theProgram,
1543 Standard_Integer theNbSamples,
1544 Standard_Boolean theIsFallback_sRGB)
b86bb3df 1545{
3b4c6945 1546 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1547 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1548
b86bb3df 1549 TCollection_AsciiString aSrcVert =
b86bb3df 1550 EOL"void main()"
1551 EOL"{"
1552 EOL" TexCoord = occVertex.zw;"
1553 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1554 EOL"}";
1555
ba00aab7 1556 TCollection_AsciiString aSrcFrag;
1557 if (theNbSamples > 1)
1558 {
1559 #if defined(GL_ES_VERSION_2_0)
1560 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1561 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1562 #else
1563 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1564 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1565 #endif
1566 aSrcFrag = TCollection_AsciiString()
1567 + EOL"#define THE_NUM_SAMPLES " + theNbSamples
1568 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1569 + EOL"void main()"
1570 EOL"{"
1571 EOL" ivec2 aSize = textureSize (uColorSampler);"
1572 EOL" ivec2 anUV = ivec2 (vec2 (aSize) * TexCoord);"
1573 EOL" gl_FragDepth = texelFetch (uDepthSampler, anUV, THE_NUM_SAMPLES / 2 - 1).r;"
1574 EOL
1575 EOL" vec4 aColor = vec4 (0.0);"
1576 EOL" for (int aSample = 0; aSample < THE_NUM_SAMPLES; ++aSample)"
1577 EOL" {"
1578 EOL" vec4 aVal = texelFetch (uColorSampler, anUV, aSample);"
1579 EOL" aColor += aVal;"
1580 EOL" }"
1581 EOL" aColor /= float(THE_NUM_SAMPLES);"
1582 EOL"#ifdef THE_SHIFT_sRGB"
1583 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1584 EOL"#endif"
1585 EOL" occSetFragColor (aColor);"
1586 EOL"}";
1587 }
1588 else
1589 {
1590 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uColorSampler", Graphic3d_TOS_FRAGMENT));
1591 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uDepthSampler", Graphic3d_TOS_FRAGMENT));
1592 aSrcFrag = TCollection_AsciiString()
1593 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1594 + EOL"void main()"
b86bb3df 1595 EOL"{"
1596 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
ba00aab7 1597 EOL" vec4 aColor = occTexture2D (uColorSampler, TexCoord);"
1598 EOL"#ifdef THE_SHIFT_sRGB"
1599 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1600 EOL"#endif"
1601 EOL" occSetFragColor (aColor);"
b86bb3df 1602 EOL"}";
ba00aab7 1603 }
b86bb3df 1604
3b4c6945 1605 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
b86bb3df 1606#if defined(GL_ES_VERSION_2_0)
ba00aab7 1607 if (myContext->IsGlGreaterEqual (3, 1))
1608 {
1609 // required for MSAA sampler
1610 aProgramSrc->SetHeader ("#version 310 es");
1611 }
1612 else if (myContext->IsGlGreaterEqual (3, 0))
b86bb3df 1613 {
1614 aProgramSrc->SetHeader ("#version 300 es");
1615 }
1ce0716b 1616 else if (myContext->extFragDepth)
1617 {
1618 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
1619 EOL"#define gl_FragDepth gl_FragDepthEXT");
1620 }
b86bb3df 1621 else
1622 {
1623 // there is no way to draw into depth buffer
1624 aSrcFrag =
b86bb3df 1625 EOL"void main()"
1626 EOL"{"
b17e5bae 1627 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
b86bb3df 1628 EOL"}";
1629 }
4e1523ef 1630#else
1631 if (myContext->core32 != NULL)
1632 {
1633 aProgramSrc->SetHeader ("#version 150");
1634 }
b86bb3df 1635#endif
ba00aab7 1636 TCollection_AsciiString anId = "occt_blit";
1637 if (theNbSamples > 1)
1638 {
1639 anId += TCollection_AsciiString ("_msaa") + theNbSamples;
1640 }
1641 if (theIsFallback_sRGB)
1642 {
1643 anId += "_gamma";
1644 }
1645 aProgramSrc->SetId (anId);
737e9a8d 1646 aProgramSrc->SetDefaultSampler (false);
daf73ab7 1647 aProgramSrc->SetNbLightsMax (0);
1648 aProgramSrc->SetNbClipPlanesMax (0);
3b4c6945 1649 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1650 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
b86bb3df 1651 TCollection_AsciiString aKey;
ba00aab7 1652 if (!Create (aProgramSrc, aKey, theProgram))
b86bb3df 1653 {
ba00aab7 1654 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
b86bb3df 1655 return Standard_False;
1656 }
1657
ba00aab7 1658 myContext->BindProgram (theProgram);
1659 theProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
1660 theProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
b86bb3df 1661 myContext->BindProgram (NULL);
1662 return Standard_True;
1663}
1664
a1073ae2 1665// =======================================================================
1666// function : prepareStdProgramOitCompositing
1667// purpose :
1668// =======================================================================
1669Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1670{
1671 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1672 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1673 TCollection_AsciiString aSrcVert, aSrcFrag;
1674
3b4c6945 1675 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1676 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1677
a1073ae2 1678 aSrcVert =
a1073ae2 1679 EOL"void main()"
1680 EOL"{"
1681 EOL" TexCoord = occVertex.zw;"
1682 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1683 EOL"}";
1684
1685 if (!theMsaa)
1686 {
3b4c6945 1687 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT));
1688 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT));
a1073ae2 1689 aSrcFrag =
a1073ae2 1690 EOL"void main()"
1691 EOL"{"
1692 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1693 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
b17e5bae 1694 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
a1073ae2 1695 EOL"}";
1696 #if !defined(GL_ES_VERSION_2_0)
1697 if (myContext->IsGlGreaterEqual (3, 2))
1698 {
1699 aProgramSrc->SetHeader ("#version 150");
1700 }
1701 #else
1702 if (myContext->IsGlGreaterEqual (3, 0))
1703 {
1704 aProgramSrc->SetHeader ("#version 300 es");
1705 }
1706 #endif
1707 }
1708 else
1709 {
3b4c6945 1710 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT));
1711 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT));
a1073ae2 1712 aSrcFrag =
a1073ae2 1713 EOL"void main()"
1714 EOL"{"
e3744452 1715 EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);"
a1073ae2 1716 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1717 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
b17e5bae 1718 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
a1073ae2 1719 EOL"}";
1720 #if !defined(GL_ES_VERSION_2_0)
1721 if (myContext->IsGlGreaterEqual (4, 0))
1722 {
1723 aProgramSrc->SetHeader ("#version 400");
1724 }
1725 #else
e3744452 1726 if (myContext->IsGlGreaterEqual (3, 2))
a1073ae2 1727 {
e3744452 1728 aProgramSrc->SetHeader ("#version 320 es");
1729 }
1730 else if (myContext->IsGlGreaterEqual (3, 0))
1731 {
1732 aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
a1073ae2 1733 }
1734 #endif
1735 }
1736
d95f5ce1 1737 aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit");
737e9a8d 1738 aProgramSrc->SetDefaultSampler (false);
daf73ab7 1739 aProgramSrc->SetNbLightsMax (0);
1740 aProgramSrc->SetNbClipPlanesMax (0);
3b4c6945 1741 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1742 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
a1073ae2 1743 TCollection_AsciiString aKey;
1744 if (!Create (aProgramSrc, aKey, aProgram))
1745 {
1746 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1747 return Standard_False;
1748 }
1749
1750 myContext->BindProgram (aProgram);
cc8cbabe 1751 aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0);
1752 aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
a1073ae2 1753 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1754 return Standard_True;
1755}
1756
299e0ab9 1757// =======================================================================
1758// function : pointSpriteAlphaSrc
1759// purpose :
1760// =======================================================================
737e9a8d 1761TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (Standard_Integer theBits)
299e0ab9 1762{
737e9a8d 1763 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").a; }";
299e0ab9 1764#if !defined(GL_ES_VERSION_2_0)
fd59283a 1765 if (myContext->core11 == NULL
737e9a8d 1766 && (theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
299e0ab9 1767 {
737e9a8d 1768 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").r; }";
299e0ab9 1769 }
fd59283a 1770#else
1771 (void )theBits;
299e0ab9 1772#endif
299e0ab9 1773 return aSrcGetAlpha;
1774}
1775
2a332745 1776// =======================================================================
1777// function : defaultGlslVersion
1778// purpose :
1779// =======================================================================
1780int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
d95f5ce1 1781 const TCollection_AsciiString& theName,
2a332745 1782 int theBits,
1783 bool theUsesDerivates) const
1784{
1785 int aBits = theBits;
59515ca6 1786 const bool toUseDerivates = theUsesDerivates
72f6dc61 1787 || (theBits & OpenGl_PO_StippleLine) != 0
1788 || (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal;
2a332745 1789#if !defined(GL_ES_VERSION_2_0)
1790 if (myContext->core32 != NULL)
1791 {
1792 theProgram->SetHeader ("#version 150");
1793 }
1794 else
1795 {
67312b79 1796 if ((theBits & OpenGl_PO_StippleLine) != 0
1797 || theProgram->IsPBR())
2a332745 1798 {
1799 if (myContext->IsGlGreaterEqual (3, 0))
1800 {
1801 theProgram->SetHeader ("#version 130");
1802 }
59515ca6 1803 else if (myContext->CheckExtension ("GL_EXT_gpu_shader4")) // myContext->hasGlslBitwiseOps == OpenGl_FeatureInExtensions
2a332745 1804 {
853af31f 1805 // GL_EXT_gpu_shader4 defines GLSL type "unsigned int", while core GLSL specs define type "uint"
1806 theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable\n"
1807 "#define uint unsigned int");
2a332745 1808 }
2a332745 1809 }
1810 }
59515ca6 1811 (void )toUseDerivates;
2a332745 1812#else
565baee6 1813
1814#if defined(__EMSCRIPTEN__)
1815 if (myContext->IsGlGreaterEqual (3, 0))
1816 {
1817 // consider this is browser responsibility to provide working WebGL 2.0 implementation
1818 // and black-list broken drivers (there is no OpenGL ES greater than 3.0)
1819 theProgram->SetHeader ("#version 300 es");
1820 }
1821#endif
2a332745 1822 // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
1823 // and "300 es" on OpenGL ES 3.1+ devices
1824 if (myContext->IsGlGreaterEqual (3, 1))
1825 {
1826 if ((theBits & OpenGl_PO_NeedsGeomShader) != 0)
1827 {
1828 theProgram->SetHeader (myContext->hasGeometryStage != OpenGl_FeatureInExtensions ? "#version 320 es" : "#version 310 es");
1829 }
1830 else
1831 {
1832 theProgram->SetHeader ("#version 300 es");
1833 }
1834 }
1835 else
1836 {
67312b79 1837 if (theProgram->IsPBR()
1838 && myContext->IsGlGreaterEqual (3, 0))
1839 {
1840 theProgram->SetHeader ("#version 300 es");
1841 }
2a332745 1842 if ((theBits & OpenGl_PO_WriteOit) != 0
1843 || (theBits & OpenGl_PO_StippleLine) != 0)
1844 {
1845 if (myContext->IsGlGreaterEqual (3, 0))
1846 {
1847 theProgram->SetHeader ("#version 300 es");
1848 }
1849 else
1850 {
1851 aBits = aBits & ~OpenGl_PO_WriteOit;
59515ca6 1852 if (!myContext->oesStdDerivatives)
1853 {
1854 aBits = aBits & ~OpenGl_PO_StippleLine;
1855 }
2a332745 1856 }
1857 }
59515ca6 1858 if (toUseDerivates)
2a332745 1859 {
1860 if (myContext->IsGlGreaterEqual (3, 0))
1861 {
1862 theProgram->SetHeader ("#version 300 es");
1863 }
1864 else if (myContext->oesStdDerivatives)
1865 {
1866 theProgram->SetHeader ("#extension GL_OES_standard_derivatives : enable");
1867 }
1868 }
1869 }
1870#endif
d95f5ce1 1871
1872 // should fit OpenGl_PO_NB
1873 char aBitsStr[64];
1874 Sprintf (aBitsStr, "%04x", aBits);
1875 theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr);
2a332745 1876 return aBits;
1877}
1878
1879// =======================================================================
1880// function : prepareGeomMainSrc
1881// purpose :
1882// =======================================================================
1883TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms,
1884 OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
1885 Standard_Integer theBits)
1886{
1887 if ((theBits & OpenGl_PO_NeedsGeomShader) == 0)
1888 {
1889 return TCollection_AsciiString();
1890 }
1891
1892 TCollection_AsciiString aSrcMainGeom =
1893 EOL"void main()"
1894 EOL"{";
1895
1896 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1897 {
1898 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY));
1899 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY));
1900 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY));
1901 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT));
1902 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT));
1903 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT));
1904 theStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT));
1905
1906 aSrcMainGeom = TCollection_AsciiString()
1907 + EOL"vec3 ViewPortTransform (vec4 theVec)"
1908 EOL"{"
1909 EOL" vec3 aWinCoord = theVec.xyz / theVec.w;"
1910 EOL" aWinCoord = aWinCoord * 0.5 + 0.5;"
1911 EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;"
1912 EOL" return aWinCoord;"
1913 EOL"}"
1914 + aSrcMainGeom
1915 + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);"
1916 EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1917 EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1918 EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);"
1919 EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));"
1920 EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;"
1921 EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance
1922 EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;";
1923 }
1924
1925 for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter)
1926 {
1927 const TCollection_AsciiString aVertIndex (aVertIter);
1928 // pass variables from Vertex shader to Fragment shader through Geometry shader
1929 for (OpenGl_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
1930 {
1931 if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT))
1932 {
1933 const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2);
1934 aSrcMainGeom += TCollection_AsciiString()
1935 + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";";
1936 }
1937 }
1938
1939 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1940 {
1941 switch (aVertIter)
1942 {
1943 case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break;
1944 case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break;
1945 case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break;
1946 }
1947 }
1948 aSrcMainGeom += TCollection_AsciiString()
1949 + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;"
1950 EOL" EmitVertex();";
1951 }
1952 aSrcMainGeom +=
1953 EOL" EndPrimitive();"
1954 EOL"}";
1955
1956 return aSrcMainGeom;
1957}
1958
b86bb3df 1959// =======================================================================
dc89236f 1960// function : prepareStdProgramUnlit
8625ef7e 1961// purpose :
1962// =======================================================================
dc89236f 1963Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
6ef0d6f1 1964 Standard_Integer theBits,
1965 Standard_Boolean theIsOutline)
8625ef7e 1966{
1967 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2a332745 1968 TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain;
1969 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
8625ef7e 1970 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
2a332745 1971 TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());";
3b4c6945 1972 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2a332745 1973
737e9a8d 1974 if ((theBits & OpenGl_PO_IsPoint) != 0)
8625ef7e 1975 {
1976 #if defined(GL_ES_VERSION_2_0)
1977 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1978 #endif
8625ef7e 1979
737e9a8d 1980 if ((theBits & OpenGl_PO_PointSprite) != 0)
8625ef7e 1981 {
737e9a8d 1982 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
1983 if ((theBits & OpenGl_PO_PointSpriteA) != OpenGl_PO_PointSpriteA)
6ef0d6f1 1984 {
1985 aSrcFragGetColor =
737e9a8d 1986 EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }";
1987 }
72f6dc61 1988 else if ((theBits & OpenGl_PO_TextureRGB) != 0
737e9a8d 1989 && (theBits & OpenGl_PO_VertColor) == 0)
1990 {
72f6dc61 1991 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
737e9a8d 1992 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
1993 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1994 aSrcVertExtraMain +=
1995 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
1996 aSrcFragGetColor =
1997 EOL"vec4 getColor(void) { return VertColor; }";
6ef0d6f1 1998 }
299e0ab9 1999
fd59283a 2000 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
2001
2002 #if !defined(GL_ES_VERSION_2_0)
2003 if (myContext->core11 != NULL
2004 && myContext->IsGlGreaterEqual (2, 1))
2005 {
2006 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2007 }
2008 #endif
2009
2010 aSrcFragMainGetColor =
2011 EOL" vec4 aColor = getColor();"
2012 EOL" aColor.a = getAlpha();"
2013 EOL" if (aColor.a <= 0.1) discard;"
b17e5bae 2014 EOL" occSetFragColor (aColor);";
fd59283a 2015 }
2016 else
2017 {
72f6dc61 2018 if ((theBits & OpenGl_PO_TextureRGB) != 0
737e9a8d 2019 && (theBits & OpenGl_PO_VertColor) == 0)
2020 {
72f6dc61 2021 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
737e9a8d 2022 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2023 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2024 aSrcVertExtraMain +=
2025 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
2026 aSrcFragGetColor =
2027 EOL"vec4 getColor(void) { return VertColor; }";
2028 }
2029
fd59283a 2030 aSrcFragMainGetColor =
2031 EOL" vec4 aColor = getColor();"
2032 EOL" if (aColor.a <= 0.1) discard;"
b17e5bae 2033 EOL" occSetFragColor (aColor);";
fd59283a 2034 }
8625ef7e 2035 }
6c6aadb1 2036 else
2037 {
72f6dc61 2038 if ((theBits & OpenGl_PO_HasTextures) != 0)
3b4c6945 2039 {
737e9a8d 2040 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
3b4c6945 2041 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
3b4c6945 2042
72f6dc61 2043 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureEnv)
2044 {
2045 aSrcVertExtraFunc = THE_FUNC_transformNormal_view;
6c6aadb1 2046
72f6dc61 2047 aSrcVertExtraMain +=
2048 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2049 EOL" vec3 aNormal = transformNormal (occNormal);"
2050 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
2051 EOL" aReflect.z += 1.0;"
2052 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
e135a155 2053
72f6dc61 2054 aSrcFragGetColor =
2055 EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
2056 }
2057 else
2058 {
2059 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2060 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
e135a155 2061
72f6dc61 2062 aSrcFragGetColor =
2063 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
2064 }
e135a155 2065 }
6c6aadb1 2066 }
8625ef7e 2067 if ((theBits & OpenGl_PO_VertColor) != 0)
2068 {
3b4c6945 2069 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
8625ef7e 2070 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
8625ef7e 2071 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
2072 }
daf73ab7 2073
2074 int aNbClipPlanes = 0;
1a7ece8f 2075 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 2076 {
3b4c6945 2077 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2078 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
8625ef7e 2079 aSrcVertExtraMain +=
2080 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2081 EOL" Position = occWorldViewMatrix * PositionWorld;";
1a7ece8f 2082
2a332745 2083 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2084 {
2085 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2086 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2087 ? THE_FRAG_CLIP_CHAINS_N
2088 : THE_FRAG_CLIP_PLANES_N;
2089 }
2090 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1a7ece8f 2091 {
daf73ab7 2092 aNbClipPlanes = 1;
1a7ece8f 2093 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2094 }
2095 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2096 {
daf73ab7 2097 aNbClipPlanes = 2;
25c35042 2098 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2099 ? THE_FRAG_CLIP_CHAINS_2
2100 : THE_FRAG_CLIP_PLANES_2;
1a7ece8f 2101 }
8625ef7e 2102 }
a1073ae2 2103 if ((theBits & OpenGl_PO_WriteOit) != 0)
2104 {
b17e5bae 2105 aProgramSrc->SetNbFragmentOutputs (2);
2106 aProgramSrc->SetWeightOitOutput (true);
a1073ae2 2107 }
8625ef7e 2108
6ef0d6f1 2109 if (theIsOutline)
2110 {
2111 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occOrthoScale", Graphic3d_TOS_VERTEX));
2112 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occSilhouetteThickness", Graphic3d_TOS_VERTEX));
2113 aSrcVertEndMain = THE_VERT_gl_Position_OUTLINE;
2114 }
2115 else if ((theBits & OpenGl_PO_StippleLine) != 0)
ac116c22 2116 {
d95f5ce1 2117 const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits);
2a332745 2118 if ((aBits & OpenGl_PO_StippleLine) != 0)
ac116c22 2119 {
59515ca6 2120 if (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
2121 {
2122 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int occStipplePattern", Graphic3d_TOS_FRAGMENT));
2123 }
2124 else
2125 {
2126 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occStipplePattern[16]", Graphic3d_TOS_FRAGMENT));
2127 }
2128 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occStippleFactor", Graphic3d_TOS_FRAGMENT));
8cf3bf84 2129 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_VERTEX));
3b4c6945 2130 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
ac116c22 2131 aSrcVertEndMain =
8cf3bf84 2132 EOL" vec2 aPosition = gl_Position.xy / gl_Position.w;"
2133 EOL" aPosition = aPosition * 0.5 + 0.5;"
2134 EOL" ScreenSpaceCoord = aPosition.xy * occViewport.zw + occViewport.xy;";
59515ca6 2135 aSrcFragMainGetColor = TCollection_AsciiString()
2136 + EOL" vec2 anAxis = vec2 (0.0, 1.0);"
8cf3bf84 2137 EOL" if (abs (dFdx (ScreenSpaceCoord.x)) - abs (dFdy (ScreenSpaceCoord.y)) > 0.001)"
2138 EOL" {"
2139 EOL" anAxis = vec2 (1.0, 0.0);"
2140 EOL" }"
8cf3bf84 2141 EOL" float aRotatePoint = dot (gl_FragCoord.xy, anAxis);"
59515ca6 2142 + (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable
2143 ? EOL" uint aBit = uint (floor (aRotatePoint / occStippleFactor + 0.5)) & 15U;"
2144 EOL" if ((uint (occStipplePattern) & (1U << aBit)) == 0U) discard;"
2145 : EOL" int aBit = int (mod (floor (aRotatePoint / occStippleFactor + 0.5), 16.0));"
2146 EOL" if (!occStipplePattern[aBit]) discard;")
2147 + EOL" vec4 aColor = getFinalColor();"
ac116c22 2148 EOL" if (aColor.a <= 0.1) discard;"
b17e5bae 2149 EOL" occSetFragColor (aColor);";
ac116c22 2150 }
2151 else
2152 {
3b4c6945 2153 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning: stipple lines in GLSL will be ignored.");
ac116c22 2154 }
2155 }
2156
8625ef7e 2157 aSrcVert =
e135a155 2158 aSrcVertExtraFunc
8625ef7e 2159 + EOL"void main()"
2160 EOL"{"
2161 + aSrcVertExtraMain
6ef0d6f1 2162 + THE_VERT_gl_Position
ac116c22 2163 + aSrcVertEndMain
2164 + EOL"}";
8625ef7e 2165
2a332745 2166 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2167 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2168 ? THE_FRAG_WIREFRAME_COLOR
2169 : EOL"#define getFinalColor getColor";
2170
8625ef7e 2171 aSrcFrag =
3b4c6945 2172 aSrcFragGetColor
299e0ab9 2173 + aSrcGetAlpha
8625ef7e 2174 + EOL"void main()"
2175 EOL"{"
2176 + aSrcFragExtraMain
2177 + aSrcFragMainGetColor
2178 + EOL"}";
2179
6ef0d6f1 2180 defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits);
737e9a8d 2181 aProgramSrc->SetDefaultSampler (false);
daf73ab7 2182 aProgramSrc->SetNbLightsMax (0);
2183 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
c40eb6b9 2184 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2a332745 2185 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2186 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2187 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2188 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
8625ef7e 2189 TCollection_AsciiString aKey;
2190 if (!Create (aProgramSrc, aKey, theProgram))
2191 {
2192 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2193 return Standard_False;
2194 }
2195 return Standard_True;
2196}
2197
299e0ab9 2198// =======================================================================
2199// function : pointSpriteShadingSrc
2200// purpose :
2201// =======================================================================
737e9a8d 2202TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc,
2203 Standard_Integer theBits)
299e0ab9 2204{
2205 TCollection_AsciiString aSrcFragGetColor;
737e9a8d 2206 if ((theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
299e0ab9 2207 {
fd59283a 2208 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
299e0ab9 2209 EOL"vec4 getColor(void)"
2210 EOL"{"
2211 EOL" vec4 aColor = " + theBaseColorSrc + ";"
2212 EOL" aColor.a = getAlpha();"
2213 EOL" if (aColor.a <= 0.1) discard;"
2214 EOL" return aColor;"
2215 EOL"}";
2216 }
737e9a8d 2217 else if ((theBits & OpenGl_PO_PointSprite) == OpenGl_PO_PointSprite)
299e0ab9 2218 {
2219 aSrcFragGetColor = TCollection_AsciiString() +
2220 EOL"vec4 getColor(void)"
2221 EOL"{"
2222 EOL" vec4 aColor = " + theBaseColorSrc + ";"
737e9a8d 2223 EOL" aColor = occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ") * aColor;"
299e0ab9 2224 EOL" if (aColor.a <= 0.1) discard;"
2225 EOL" return aColor;"
2226 EOL"}";
2227 }
2228
2229 return aSrcFragGetColor;
2230}
2231
256f9ac0 2232// =======================================================================
2233// function : stdComputeLighting
2234// purpose :
2235// =======================================================================
daf73ab7 2236TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
67312b79 2237 Standard_Boolean theHasVertColor,
72f6dc61 2238 Standard_Boolean theIsPBR,
2239 Standard_Boolean theHasEmissive)
256f9ac0 2240{
256f9ac0 2241 TCollection_AsciiString aLightsFunc, aLightsLoop;
daf73ab7 2242 theNbLights = 0;
992ed6b3 2243 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
2244 if (!aLights.IsNull())
256f9ac0 2245 {
992ed6b3 2246 theNbLights = aLights->NbEnabled();
2247 if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
2248 {
2249 Standard_Integer anIndex = 0;
2250 for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
2251 aLightIter.More(); aLightIter.Next(), ++anIndex)
2252 {
2253 switch (aLightIter.Value()->Type())
2254 {
2255 case Graphic3d_TOLS_AMBIENT:
2256 --anIndex;
2257 break; // skip ambient
2258 case Graphic3d_TOLS_DIRECTIONAL:
2259 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
2260 break;
2261 case Graphic3d_TOLS_POSITIONAL:
2262 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2263 break;
2264 case Graphic3d_TOLS_SPOT:
2265 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2266 break;
2267 }
2268 }
2269 }
2270 else
256f9ac0 2271 {
992ed6b3 2272 theNbLights = roundUpMaxLightSources (theNbLights);
2273 bool isFirstInLoop = true;
2274 aLightsLoop = aLightsLoop +
2275 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
2276 EOL" {"
2277 EOL" int aType = occLight_Type (anIndex);";
2278 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
256f9ac0 2279 {
992ed6b3 2280 isFirstInLoop = false;
2281 aLightsLoop +=
2282 EOL" if (aType == OccLightType_Direct)"
2283 EOL" {"
2284 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
2285 EOL" }";
2286 }
2287 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2288 {
2289 if (!isFirstInLoop)
2290 {
2291 aLightsLoop += EOL" else ";
2292 }
2293 isFirstInLoop = false;
2294 aLightsLoop +=
2295 EOL" if (aType == OccLightType_Point)"
2296 EOL" {"
2297 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2298 EOL" }";
2299 }
2300 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2301 {
2302 if (!isFirstInLoop)
2303 {
2304 aLightsLoop += EOL" else ";
2305 }
2306 isFirstInLoop = false;
2307 aLightsLoop +=
2308 EOL" if (aType == OccLightType_Spot)"
2309 EOL" {"
2310 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2311 EOL" }";
256f9ac0 2312 }
992ed6b3 2313 aLightsLoop += EOL" }";
f68acbf4 2314 }
67312b79 2315
2316 if (theIsPBR)
2317 {
2318 aLightsFunc += Shaders_PBRDistribution_glsl;
2319 aLightsFunc += Shaders_PBRGeometry_glsl;
2320 aLightsFunc += Shaders_PBRFresnel_glsl;
2321 aLightsFunc += Shaders_PBRCookTorrance_glsl;
2322 aLightsFunc += Shaders_PBRIllumination_glsl;
2323 }
2324
992ed6b3 2325 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
67312b79 2326 && theNbLights == 1
2327 && !theIsPBR)
f68acbf4 2328 {
2329 // use the version with hard-coded first index
2330 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
2331 aLightsFunc += THE_FUNC_directionalLightFirst;
2332 }
992ed6b3 2333 else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
f68acbf4 2334 {
67312b79 2335 aLightsFunc += theIsPBR ? THE_FUNC_PBR_directionalLight : THE_FUNC_directionalLight;
f68acbf4 2336 }
992ed6b3 2337 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
f68acbf4 2338 {
67312b79 2339 aLightsFunc += theIsPBR ? THE_FUNC_PBR_pointLight : THE_FUNC_pointLight;
f68acbf4 2340 }
992ed6b3 2341 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
f68acbf4 2342 {
67312b79 2343 aLightsFunc += theIsPBR ? THE_FUNC_PBR_spotLight : THE_FUNC_spotLight;
256f9ac0 2344 }
2345 }
2346
abdf0b10 2347 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
2348 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
2349 if (theHasVertColor)
2350 {
2351 aGetMatAmbient = "getVertColor();";
2352 aGetMatDiffuse = "getVertColor();";
2353 }
2354
67312b79 2355 if (!theIsPBR)
2356 {
2357 return TCollection_AsciiString()
256f9ac0 2358 + THE_FUNC_lightDef
88b312d3 2359 + Shaders_PointLightAttenuation_glsl
256f9ac0 2360 + aLightsFunc
2361 + EOL
2362 EOL"vec4 computeLighting (in vec3 theNormal,"
2363 EOL" in vec3 theView,"
2364 EOL" in vec4 thePoint,"
2365 EOL" in bool theIsFront)"
2366 EOL"{"
2367 EOL" Ambient = occLightAmbient.rgb;"
2368 EOL" Diffuse = vec3 (0.0);"
2369 EOL" Specular = vec3 (0.0);"
2370 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2371 + aLightsLoop
363bc51b 2372 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
2373 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
2374 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
72f6dc61 2375 EOL" vec3 aColor = Ambient * aMatAmbient.rgb + Diffuse * aMatDiffuse.rgb + Specular * aMatSpecular.rgb;"
2376 EOL" occTextureOcclusion(aColor, TexCoord.st);"
2377 + (theHasEmissive
2378 ? EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
2379 EOL" aColor += aMatEmission.rgb;" : "")
2380 + EOL" return vec4 (aColor, aMatDiffuse.a);"
256f9ac0 2381 EOL"}";
67312b79 2382 }
2383 else
2384 {
2385 return TCollection_AsciiString()
2386 + THE_FUNC_PBR_lightDef
88b312d3 2387 + Shaders_PointLightAttenuation_glsl
67312b79 2388 + aLightsFunc
2389 + EOL
2390 EOL"vec4 computeLighting (in vec3 theNormal,"
2391 EOL" in vec3 theView,"
2392 EOL" in vec4 thePoint,"
2393 EOL" in bool theIsFront)"
2394 EOL"{"
2395 EOL" DirectLighting = vec3(0.0);"
c8bead47 2396 EOL" BaseColor = " + (theHasVertColor ? "getVertColor();" : "occTextureColor(occPBRMaterial_Color (theIsFront), TexCoord.st / TexCoord.w);")
2397 + EOL" Emission = occTextureEmissive(occPBRMaterial_Emission (theIsFront), TexCoord.st / TexCoord.w);"
2398 EOL" Metallic = occTextureMetallic(occPBRMaterial_Metallic (theIsFront), TexCoord.st / TexCoord.w);"
2399 EOL" NormalizedRoughness = occTextureRoughness(occPBRMaterial_NormalizedRoughness (theIsFront), TexCoord.st / TexCoord.w);"
72f6dc61 2400 EOL" Roughness = occRoughness (NormalizedRoughness);"
2401 EOL" IOR = occPBRMaterial_IOR (theIsFront);"
67312b79 2402 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2403 + aLightsLoop
2404 + EOL" vec3 aColor = DirectLighting;"
2405 EOL" vec3 anIndirectLightingSpec = occPBRFresnel (BaseColor.rgb, Metallic, IOR);"
72f6dc61 2406 EOL" vec2 aCoeff = occTexture2D (occEnvLUT, vec2(abs(dot(theView, theNormal)), NormalizedRoughness)).xy;"
67312b79 2407 EOL" anIndirectLightingSpec *= aCoeff.x;"
2408 EOL" anIndirectLightingSpec += aCoeff.y;"
72f6dc61 2409 EOL" anIndirectLightingSpec *= occTextureCubeLod (occSpecIBLMap, -reflect (theView, theNormal), NormalizedRoughness * float (occNbSpecIBLLevels - 1)).rgb;"
2410 EOL" vec3 aRefractionCoeff = 1.0 - occPBRFresnel (BaseColor.rgb, Metallic, NormalizedRoughness, IOR, abs(dot(theView, theNormal)));"
67312b79 2411 EOL" aRefractionCoeff *= (1.0 - Metallic);"
2412 EOL" vec3 anIndirectLightingDiff = aRefractionCoeff * BaseColor.rgb * BaseColor.a;"
2413 EOL" anIndirectLightingDiff *= occDiffIBLMap (theNormal).rgb;"
2414 EOL" aColor += occLightAmbient.rgb * (anIndirectLightingDiff + anIndirectLightingSpec);"
2415 EOL" aColor += Emission;"
c8bead47 2416 EOL" occTextureOcclusion(aColor, TexCoord.st / TexCoord.w);"
67312b79 2417 EOL" return vec4 (aColor, mix(1.0, BaseColor.a, aRefractionCoeff.x));"
2418 EOL"}";
2419 }
256f9ac0 2420}
2421
8625ef7e 2422// =======================================================================
2423// function : prepareStdProgramGouraud
2424// purpose :
2425// =======================================================================
2426Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
2427 const Standard_Integer theBits)
2428{
2429 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3b4c6945 2430 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain;
2a332745 2431 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
6c6aadb1 2432 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
3b4c6945 2433 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2434
737e9a8d 2435 if ((theBits & OpenGl_PO_IsPoint) != 0)
8625ef7e 2436 {
2437 #if defined(GL_ES_VERSION_2_0)
2438 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2439 #endif
299e0ab9 2440
737e9a8d 2441 if ((theBits & OpenGl_PO_PointSprite) != 0)
6c6aadb1 2442 {
737e9a8d 2443 #if !defined(GL_ES_VERSION_2_0)
2444 if (myContext->core11 != NULL
2445 && myContext->IsGlGreaterEqual (2, 1))
2446 {
2447 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2448 }
2449 #endif
299e0ab9 2450
737e9a8d 2451 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
299e0ab9 2452 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
6c6aadb1 2453 }
737e9a8d 2454
72f6dc61 2455 if ((theBits & OpenGl_PO_TextureRGB) != 0
737e9a8d 2456 && (theBits & OpenGl_PO_VertColor) == 0)
2457 {
72f6dc61 2458 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
737e9a8d 2459 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2460 aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }";
2461 }
6c6aadb1 2462 }
2463 else
2464 {
72f6dc61 2465 if ((theBits & OpenGl_PO_TextureRGB) != 0)
6c6aadb1 2466 {
72f6dc61 2467 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
737e9a8d 2468 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
3b4c6945 2469 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
79f4f036 2470 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 2471
2472 aSrcFragGetColor =
2473 EOL"vec4 getColor(void)"
2474 EOL"{"
2475 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
cc8cbabe 2476 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
6c6aadb1 2477 EOL"}";
2478 }
2479 }
299e0ab9 2480
2481 if ((theBits & OpenGl_PO_VertColor) != 0)
2482 {
2483 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
2484 }
2485
daf73ab7 2486 int aNbClipPlanes = 0;
1a7ece8f 2487 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 2488 {
3b4c6945 2489 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2490 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
8625ef7e 2491 aSrcVertExtraMain +=
2492 EOL" PositionWorld = aPositionWorld;"
2493 EOL" Position = aPosition;";
1a7ece8f 2494
2a332745 2495 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2496 {
2497 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2498 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2499 ? THE_FRAG_CLIP_CHAINS_N
2500 : THE_FRAG_CLIP_PLANES_N;
2501 }
2502 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1a7ece8f 2503 {
daf73ab7 2504 aNbClipPlanes = 1;
1a7ece8f 2505 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2506 }
2507 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2508 {
daf73ab7 2509 aNbClipPlanes = 2;
25c35042 2510 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2511 ? THE_FRAG_CLIP_CHAINS_2
2512 : THE_FRAG_CLIP_PLANES_2;
1a7ece8f 2513 }
8625ef7e 2514 }
a1073ae2 2515 if ((theBits & OpenGl_PO_WriteOit) != 0)
2516 {
b17e5bae 2517 aProgramSrc->SetNbFragmentOutputs (2);
2518 aProgramSrc->SetWeightOitOutput (true);
a1073ae2 2519 }
8625ef7e 2520
3b4c6945 2521 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2522 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2523
daf73ab7 2524 Standard_Integer aNbLights = 0;
72f6dc61 2525 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false, true);
8625ef7e 2526 aSrcVert = TCollection_AsciiString()
67312b79 2527 + THE_FUNC_transformNormal_view
8625ef7e 2528 + EOL
abdf0b10 2529 + aSrcVertColor
256f9ac0 2530 + aLights
8625ef7e 2531 + EOL"void main()"
2532 EOL"{"
2533 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
2534 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
2535 EOL" vec3 aNormal = transformNormal (occNormal);"
2536 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
2537 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
2538 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
2539 + aSrcVertExtraMain
6ef0d6f1 2540 + THE_VERT_gl_Position
2541 + EOL"}";
8625ef7e 2542
2a332745 2543 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2544 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2545 ? THE_FRAG_WIREFRAME_COLOR
2546 : EOL"#define getFinalColor getColor";
2547
8625ef7e 2548 aSrcFrag = TCollection_AsciiString()
6c6aadb1 2549 + aSrcFragGetColor
8625ef7e 2550 + EOL"void main()"
2551 EOL"{"
2552 + aSrcFragExtraMain
2a332745 2553 + EOL" occSetFragColor (getFinalColor());"
a1073ae2 2554 + EOL"}";
8625ef7e 2555
d95f5ce1 2556 const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-";
2557 defaultGlslVersion (aProgramSrc, aProgId, theBits);
737e9a8d 2558 aProgramSrc->SetDefaultSampler (false);
daf73ab7 2559 aProgramSrc->SetNbLightsMax (aNbLights);
2560 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
c40eb6b9 2561 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2a332745 2562 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2563 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2564 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2565 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
8625ef7e 2566 TCollection_AsciiString aKey;
2567 if (!Create (aProgramSrc, aKey, theProgram))
2568 {
2569 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2570 return Standard_False;
2571 }
2572 return Standard_True;
2573}
2574
2575// =======================================================================
2576// function : prepareStdProgramPhong
2577// purpose :
2578// =======================================================================
2579Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
8c3237d4 2580 const Standard_Integer theBits,
67312b79 2581 const Standard_Boolean theIsFlatNormal,
2582 const Standard_Boolean theIsPBR)
8625ef7e 2583{
67312b79 2584 TCollection_AsciiString aPosition = theIsPBR ? "PositionWorld" : "Position";
2585 TCollection_AsciiString aPhongCompLight = TCollection_AsciiString() +
2586 "computeLighting (normalize (Normal), normalize (View), " + aPosition + ", gl_FrontFacing)";
8c3237d4 2587 const bool isFlatNormal = theIsFlatNormal
c39bb31b 2588 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable;
2589 const char* aDFdxSignReversion = "";
2590#if defined(GL_ES_VERSION_2_0)
2591 if (isFlatNormal != theIsFlatNormal)
2592 {
2593 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
2594 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2595 "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension.");
2596 }
2597 else if (isFlatNormal
6997ff1c 2598 && myContext->Vendor().Search("qualcomm") != -1)
c39bb31b 2599 {
2600 // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
2601 aDFdxSignReversion = "-";
2602 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2603 "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno");
2604 }
8c3237d4 2605#endif
8625ef7e 2606 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
67312b79 2607 aProgramSrc->SetPBR (theIsPBR);
2608
3b4c6945 2609 TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain;
9504a30d 2610 TCollection_AsciiString aSrcFrag, aSrcFragGetVertColor, aSrcFragExtraMain;
67312b79 2611 TCollection_AsciiString aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void) { return " + aPhongCompLight + "; }";
3b4c6945 2612 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
737e9a8d 2613 if ((theBits & OpenGl_PO_IsPoint) != 0)
8625ef7e 2614 {
2615 #if defined(GL_ES_VERSION_2_0)
2616 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2617 #endif
6c6aadb1 2618
737e9a8d 2619 if ((theBits & OpenGl_PO_PointSprite) != 0)
6c6aadb1 2620 {
737e9a8d 2621 #if !defined(GL_ES_VERSION_2_0)
2622 if (myContext->core11 != NULL
2623 && myContext->IsGlGreaterEqual (2, 1))
2624 {
2625 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2626 }
2627 #endif
299e0ab9 2628
737e9a8d 2629 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
67312b79 2630 aSrcFragGetColor = pointSpriteShadingSrc (aPhongCompLight, theBits);
6c6aadb1 2631 }
737e9a8d 2632
72f6dc61 2633 if ((theBits & OpenGl_PO_TextureRGB) != 0
737e9a8d 2634 && (theBits & OpenGl_PO_VertColor) == 0)
2635 {
72f6dc61 2636 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
737e9a8d 2637 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2638 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2639
2640 aSrcVertExtraMain += EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
2641 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2642 }
6c6aadb1 2643 }
2644 else
2645 {
72f6dc61 2646 if ((theBits & OpenGl_PO_TextureRGB) != 0)
6c6aadb1 2647 {
737e9a8d 2648 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
3b4c6945 2649 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
79f4f036 2650 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
6c6aadb1 2651
72f6dc61 2652 Standard_Integer aTextureBits = Graphic3d_TextureSetBits_BaseColor | Graphic3d_TextureSetBits_Occlusion | Graphic3d_TextureSetBits_Emissive;
67312b79 2653 if (!theIsPBR)
2654 {
2655 aSrcFragGetColor = TCollection_AsciiString() +
2656 EOL"vec4 getColor(void)"
2657 EOL"{"
72f6dc61 2658 EOL" vec2 aTexUV = TexCoord.st / TexCoord.w;"
67312b79 2659 EOL" vec4 aColor = " + aPhongCompLight + ";"
72f6dc61 2660 EOL" aColor *= occTexture2D(occSamplerBaseColor, aTexUV);"
2661 EOL" vec3 anEmission = occTextureEmissive((gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission()).rgb, aTexUV);"
2662 EOL" aColor.rgb += anEmission;"
2663 EOL" return aColor;"
67312b79 2664 EOL"}";
2665 }
2666 else
2667 {
72f6dc61 2668 aTextureBits |= Graphic3d_TextureSetBits_MetallicRoughness;
2669 }
2670 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal
2671 && !isFlatNormal)
2672 {
2673 if (myContext->hasFlatShading != OpenGl_FeatureNotAvailable)
2674 {
2675 aTextureBits |= Graphic3d_TextureSetBits_Normal;
2676 }
2677 else
2678 {
2679 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2680 "Warning: ignoring Normal Map texture due to hardware capabilities");
2681 }
67312b79 2682 }
72f6dc61 2683 aProgramSrc->SetTextureSetBits (aTextureBits);
6c6aadb1 2684 }
2685 }
2686
299e0ab9 2687 if ((theBits & OpenGl_PO_VertColor) != 0)
2688 {
3b4c6945 2689 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
299e0ab9 2690 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
3b4c6945 2691 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
299e0ab9 2692 }
2693
daf73ab7 2694 int aNbClipPlanes = 0;
1a7ece8f 2695 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
8625ef7e 2696 {
2a332745 2697 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2698 {
2699 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2700 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2701 ? THE_FRAG_CLIP_CHAINS_N
2702 : THE_FRAG_CLIP_PLANES_N;
2703 }
2704 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1a7ece8f 2705 {
daf73ab7 2706 aNbClipPlanes = 1;
1a7ece8f 2707 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2708 }
2709 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2710 {
daf73ab7 2711 aNbClipPlanes = 2;
25c35042 2712 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2713 ? THE_FRAG_CLIP_CHAINS_2
2714 : THE_FRAG_CLIP_PLANES_2;
1a7ece8f 2715 }
8625ef7e 2716 }
a1073ae2 2717 if ((theBits & OpenGl_PO_WriteOit) != 0)
2718 {
b17e5bae 2719 aProgramSrc->SetNbFragmentOutputs (2);
2720 aProgramSrc->SetWeightOitOutput (true);
a1073ae2 2721 }
8625ef7e 2722
3b4c6945 2723 if (isFlatNormal)
2724 {
3b4c6945 2725 aSrcFragExtraMain += TCollection_AsciiString()
67312b79 2726 + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (" + aPosition + ".xyz / " + aPosition + ".w), dFdy (" + aPosition + ".xyz / " + aPosition + ".w)));"
3b4c6945 2727 EOL" if (!gl_FrontFacing) { Normal = -Normal; }";
2728 }
2729 else
2730 {
72f6dc61 2731 aStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable("vec3 vNormal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2732 aSrcVertExtraFunc += THE_FUNC_transformNormal_world;
2733 aSrcVertExtraMain += EOL" vNormal = transformNormal (occNormal);";
9504a30d 2734 aSrcFragExtraMain += EOL" Normal = vNormal;";
72f6dc61 2735
2736 if ((theBits & OpenGl_PO_IsPoint) == 0
2737 && (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal
2738 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable)
2739 {
78607702 2740 aSrcFrag += Shaders_TangentSpaceNormal_glsl;
72f6dc61 2741 // apply normal map texture
2742 aSrcFragExtraMain +=
2743 EOL"#if defined(THE_HAS_TEXTURE_NORMAL)"
c8bead47 2744 EOL" vec2 aTexCoord = TexCoord.st / TexCoord.w;"
2745 EOL" vec4 aMapNormalValue = occTextureNormal(aTexCoord);"
72f6dc61 2746 EOL" if (aMapNormalValue.w > 0.5)"
2747 EOL" {"
c8bead47 2748 EOL" mat2 aDeltaUVMatrix = mat2 (dFdx(aTexCoord), dFdy(aTexCoord));"
72f6dc61 2749 EOL" mat2x3 aDeltaVectorMatrix = mat2x3 (dFdx (PositionWorld.xyz), dFdy (PositionWorld.xyz));"
78607702 2750 EOL" Normal = TangentSpaceNormal (aDeltaUVMatrix, aDeltaVectorMatrix, aMapNormalValue.xyz, Normal, !gl_FrontFacing);"
72f6dc61 2751 EOL" }"
2752 EOL"#endif";
2753 }
2754 if (!theIsPBR)
2755 {
2756 aSrcFragExtraMain +=
2757 EOL" Normal = normalize ((occWorldViewMatrixInverseTranspose * vec4 (Normal, 0.0)).xyz);";
2758 }
3b4c6945 2759 }
2760
2761 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2762 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2763 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2764
8625ef7e 2765 aSrcVert = TCollection_AsciiString()
3b4c6945 2766 + aSrcVertExtraFunc
8625ef7e 2767 + EOL"void main()"
2768 EOL"{"
2769 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2770 EOL" Position = occWorldViewMatrix * PositionWorld;"
67312b79 2771 EOL" if (occProjectionMatrix[3][3] == 1.0)"
2772 EOL" {"
2773 EOL" View = vec3(0.0, 0.0, 1.0);"
2774 EOL" }"
2775 EOL" else"
2776 EOL" {"
2777 EOL" View = -Position.xyz;"
2778 EOL" }"
2779 + (theIsPBR ? EOL" View = (occWorldViewMatrixInverse * vec4(View, 0.0)).xyz;" : "")
8625ef7e 2780 + aSrcVertExtraMain
6ef0d6f1 2781 + THE_VERT_gl_Position
2782 + EOL"}";
8625ef7e 2783
2a332745 2784 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2785 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2786 ? THE_FRAG_WIREFRAME_COLOR
2787 : EOL"#define getFinalColor getColor";
2788
daf73ab7 2789 Standard_Integer aNbLights = 0;
72f6dc61 2790 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR,
2791 (theBits & OpenGl_PO_TextureRGB) == 0
2792 || (theBits & OpenGl_PO_IsPoint) != 0);
78607702 2793 aSrcFrag += TCollection_AsciiString()
8625ef7e 2794 + EOL
6c6aadb1 2795 + aSrcFragGetVertColor
9504a30d 2796 + EOL"vec3 Normal;"
256f9ac0 2797 + aLights
6c6aadb1 2798 + aSrcFragGetColor
8625ef7e 2799 + EOL
2800 EOL"void main()"
2801 EOL"{"
2802 + aSrcFragExtraMain
2a332745 2803 + EOL" occSetFragColor (getFinalColor());"
a1073ae2 2804 + EOL"}";
8625ef7e 2805
67312b79 2806 const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") + genLightKey (myLightSourceState.LightSources()) + "-";
d95f5ce1 2807 defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal);
737e9a8d 2808 aProgramSrc->SetDefaultSampler (false);
daf73ab7 2809 aProgramSrc->SetNbLightsMax (aNbLights);
2810 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
c40eb6b9 2811 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
67312b79 2812
2a332745 2813 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2814 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2815 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2816 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
8625ef7e 2817 TCollection_AsciiString aKey;
2818 if (!Create (aProgramSrc, aKey, theProgram))
2819 {
2820 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2821 return Standard_False;
2822 }
2823 return Standard_True;
2824}
2825
38a0206f 2826// =======================================================================
f978241f 2827// function : prepareStdProgramStereo
38a0206f 2828// purpose :
2829// =======================================================================
f978241f 2830Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
2831 const Graphic3d_StereoMode theStereoMode)
38a0206f 2832{
2833 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3b4c6945 2834 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2835
2836 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
38a0206f 2837 TCollection_AsciiString aSrcVert =
38a0206f 2838 EOL"void main()"
2839 EOL"{"
2840 EOL" TexCoord = occVertex.zw;"
2841 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
2842 EOL"}";
2843
f978241f 2844 TCollection_AsciiString aSrcFrag;
3b4c6945 2845 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT));
2846 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT));
d95f5ce1 2847 const char* aName = "stereo";
f978241f 2848 switch (theStereoMode)
2849 {
2850 case Graphic3d_StereoMode_Anaglyph:
2851 {
d95f5ce1 2852 aName = "anaglyph";
3b4c6945 2853 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT));
2854 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT));
ba00aab7 2855 const TCollection_AsciiString aNormalize = mySRgbState
2856 ? EOL"#define sRgb2linear(theColor) theColor"
2857 EOL"#define linear2sRgb(theColor) theColor"
2858 : EOL"#define sRgb2linear(theColor) pow(theColor, vec4(2.2, 2.2, 2.2, 1.0))"
2859 EOL"#define linear2sRgb(theColor) pow(theColor, 1.0 / vec4(2.2, 2.2, 2.2, 1.0))";
2860 aSrcFrag = aNormalize
2861 + EOL"void main()"
2862 EOL"{"
2863 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2864 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2865 EOL" aColorL = sRgb2linear (aColorL);"
2866 EOL" aColorR = sRgb2linear (aColorR);"
2867 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2868 EOL" occSetFragColor (linear2sRgb (aColor));"
2869 EOL"}";
f978241f 2870 break;
2871 }
2872 case Graphic3d_StereoMode_RowInterlaced:
2873 {
d95f5ce1 2874 aName = "row-interlaced";
f978241f 2875 aSrcFrag =
f978241f 2876 EOL"void main()"
2877 EOL"{"
2878 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2879 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 2880 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
f978241f 2881 EOL" {"
b17e5bae 2882 EOL" occSetFragColor (aColorL);"
f978241f 2883 EOL" }"
2884 EOL" else"
2885 EOL" {"
b17e5bae 2886 EOL" occSetFragColor (aColorR);"
f978241f 2887 EOL" }"
2888 EOL"}";
2889 break;
2890 }
2891 case Graphic3d_StereoMode_ColumnInterlaced:
2892 {
d95f5ce1 2893 aName = "column-interlaced";
f978241f 2894 aSrcFrag =
f978241f 2895 EOL"void main()"
2896 EOL"{"
2897 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2898 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 2899 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
f978241f 2900 EOL" {"
b17e5bae 2901 EOL" occSetFragColor (aColorL);"
f978241f 2902 EOL" }"
2903 EOL" else"
2904 EOL" {"
b17e5bae 2905 EOL" occSetFragColor (aColorR);"
f978241f 2906 EOL" }"
2907 EOL"}";
2908 break;
2909 }
2910 case Graphic3d_StereoMode_ChessBoard:
2911 {
d95f5ce1 2912 aName = "chessboard";
f978241f 2913 aSrcFrag =
f978241f 2914 EOL"void main()"
2915 EOL"{"
2916 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2917 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
6e66a3fa 2918 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2919 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
f978241f 2920 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2921 EOL" {"
b17e5bae 2922 EOL" occSetFragColor (aColorL);"
f978241f 2923 EOL" }"
2924 EOL" else"
2925 EOL" {"
b17e5bae 2926 EOL" occSetFragColor (aColorR);"
f978241f 2927 EOL" }"
2928 EOL"}";
2929 break;
2930 }
2931 case Graphic3d_StereoMode_SideBySide:
2932 {
d95f5ce1 2933 aName = "sidebyside";
f978241f 2934 aSrcFrag =
f978241f 2935 EOL"void main()"
2936 EOL"{"
2937 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2938 EOL" if (TexCoord.x > 0.5)"
2939 EOL" {"
2940 EOL" aTexCoord.x -= 1.0;"
2941 EOL" }"
2942 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2943 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2944 EOL" if (TexCoord.x <= 0.5)"
2945 EOL" {"
b17e5bae 2946 EOL" occSetFragColor (aColorL);"
f978241f 2947 EOL" }"
2948 EOL" else"
2949 EOL" {"
b17e5bae 2950 EOL" occSetFragColor (aColorR);"
f978241f 2951 EOL" }"
2952 EOL"}";
2953 break;
2954 }
2955 case Graphic3d_StereoMode_OverUnder:
2956 {
d95f5ce1 2957 aName = "overunder";
f978241f 2958 aSrcFrag =
f978241f 2959 EOL"void main()"
2960 EOL"{"
2961 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2962 EOL" if (TexCoord.y > 0.5)"
2963 EOL" {"
2964 EOL" aTexCoord.y -= 1.0;"
2965 EOL" }"
2966 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2967 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2968 EOL" if (TexCoord.y <= 0.5)"
2969 EOL" {"
b17e5bae 2970 EOL" occSetFragColor (aColorL);"
f978241f 2971 EOL" }"
2972 EOL" else"
2973 EOL" {"
b17e5bae 2974 EOL" occSetFragColor (aColorR);"
f978241f 2975 EOL" }"
2976 EOL"}";
2977 break;
2978 }
2979 case Graphic3d_StereoMode_QuadBuffer:
2980 case Graphic3d_StereoMode_SoftPageFlip:
b40cdc2b 2981 case Graphic3d_StereoMode_OpenVR:
f978241f 2982 default:
2983 {
2984 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2985 if (!aProgram.IsNull())
2986 {
2987 return aProgram->IsValid();
2988 }*/
2989 aSrcFrag =
f978241f 2990 EOL"void main()"
2991 EOL"{"
2992 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2993 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2994 EOL" aColorL.b = 0.0;"
2995 EOL" aColorL.g = 0.0;"
2996 EOL" aColorR.r = 0.0;"
b17e5bae 2997 EOL" occSetFragColor (aColorL + aColorR);"
f978241f 2998 EOL"}";
2999 break;
3000 }
3001 }
38a0206f 3002
d95f5ce1 3003 defaultGlslVersion (aProgramSrc, aName, 0);
737e9a8d 3004 aProgramSrc->SetDefaultSampler (false);
daf73ab7 3005 aProgramSrc->SetNbLightsMax (0);
3006 aProgramSrc->SetNbClipPlanesMax (0);
3b4c6945 3007 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3008 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
38a0206f 3009 TCollection_AsciiString aKey;
f978241f 3010 if (!Create (aProgramSrc, aKey, theProgram))
38a0206f 3011 {
f978241f 3012 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
38a0206f 3013 return Standard_False;
3014 }
3015
f978241f 3016 myContext->BindProgram (theProgram);
cc8cbabe 3017 theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0);
3018 theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
38a0206f 3019 myContext->BindProgram (NULL);
3020 return Standard_True;
3021}
3022
98b15dbf 3023// =======================================================================
3024// function : prepareStdProgramBoundBox
3025// purpose :
3026// =======================================================================
3027Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
3028{
3029 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3b4c6945 3030
3031 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3032 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX));
3033 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX));
3034
98b15dbf 3035 TCollection_AsciiString aSrcVert =
98b15dbf 3036 EOL"void main()"
3037 EOL"{"
3038 EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
3039 EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
3040 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
3041 EOL"}";
3042
3043 TCollection_AsciiString aSrcFrag =
3044 EOL"void main()"
3045 EOL"{"
3046 EOL" occSetFragColor (occColor);"
3047 EOL"}";
3048
d95f5ce1 3049 defaultGlslVersion (aProgramSrc, "bndbox", 0);
737e9a8d 3050 aProgramSrc->SetDefaultSampler (false);
98b15dbf 3051 aProgramSrc->SetNbLightsMax (0);
3052 aProgramSrc->SetNbClipPlanesMax (0);
3b4c6945 3053 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3054 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
98b15dbf 3055 TCollection_AsciiString aKey;
3056 if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
3057 {
3058 myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3059 return Standard_False;
3060 }
3061
3062 const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
3063 const OpenGl_Vec4 anAxisShifts[3] =
3064 {
3065 OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
3066 OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
3067 OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
3068 };
3069
3070 const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
3071 const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
3072 OpenGl_Vec4 aLinesVertices[24];
3073 for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
3074 {
3075 for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
3076 {
3077 aLinesVertices[aVertex++] = aMin
3078 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
3079 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
3080
3081 aLinesVertices[aVertex++] = aMin
3082 + anAxisShifts[anAxis]
3083 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
3084 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
3085 }
3086 }
3087 if (myContext->ToUseVbo())
3088 {
3089 myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
3090 if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
3091 {
3092 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
3093 return Standard_True;
3094 }
3095 }
3096 myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
3097 myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
3098 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
3099 return Standard_True;
3100}
3101
67312b79 3102// =======================================================================
3103// function : preparePBREnvBakingProgram
3104// purpose :
3105// =======================================================================
3106Standard_Boolean OpenGl_ShaderManager::preparePBREnvBakingProgram()
3107{
3108 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3109 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3110
3111 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
3112 + THE_FUNC_cubemap_vector_transform
3113 + Shaders_PBREnvBaking_vs;
3114
3115 TCollection_AsciiString aSrcFrag = TCollection_AsciiString()
3116 + THE_FUNC_cubemap_vector_transform
3117 + Shaders_PBRDistribution_glsl
3118 + Shaders_PBREnvBaking_fs;
3119
3120 // constant array definition requires OpenGL 2.1+ or OpenGL ES 3.0+
3121#if defined(GL_ES_VERSION_2_0)
3122 aProgramSrc->SetHeader ("#version 300 es");
3123#else
3124 aProgramSrc->SetHeader ("#version 120");
3125#endif
3126
3127 defaultGlslVersion (aProgramSrc, "pbr_env_baking", 0);
3128 aProgramSrc->SetDefaultSampler (false);
3129 aProgramSrc->SetNbLightsMax (0);
3130 aProgramSrc->SetNbClipPlanesMax (0);
3131 aProgramSrc->SetPBR (true);
3132 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3133 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3134 TCollection_AsciiString aKey;
3135 if (!Create (aProgramSrc, aKey, myPBREnvBakingProgram))
3136 {
3137 myPBREnvBakingProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3138 return Standard_False;
3139 }
3140
3141 return Standard_True;
3142}
3143
077a220c 3144// =======================================================================
3145// function : GetBgCubeMapProgram
3146// purpose :
3147// =======================================================================
3148const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram ()
3149{
3150 if (myBgCubeMapProgram.IsNull())
3151 {
67312b79 3152 myBgCubeMapProgram = new Graphic3d_ShaderProgram();
077a220c 3153
3154 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3155 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable("vec3 ViewDirection", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
077a220c 3156 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("samplerCube occSampler0", Graphic3d_TOS_FRAGMENT));
67312b79 3157 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX));
3158 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX));
077a220c 3159
67312b79 3160 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
3161 + THE_FUNC_cubemap_vector_transform
3162 + EOL"void main()"
077a220c 3163 EOL"{"
cdc54fb0 3164 EOL" ViewDirection = cubemapVectorTransform (occVertex.xyz, uYCoeff, uZCoeff);"
3165 EOL" vec4 aPos = occProjectionMatrix * occWorldViewMatrix * vec4(occVertex.xyz, 1.0);"
3166 EOL" gl_Position = aPos.xyww;"
077a220c 3167 EOL"}";
3168
3169 TCollection_AsciiString aSrcFrag =
3170 EOL"#define occEnvCubemap occSampler0"
3171 EOL"void main()"
3172 EOL"{"
67312b79 3173 EOL" occSetFragColor (vec4(occTextureCube (occEnvCubemap, ViewDirection).rgb, 1.0));"
077a220c 3174 EOL"}";
3175
67312b79 3176 defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0);
3177 myBgCubeMapProgram->SetDefaultSampler (false);
3178 myBgCubeMapProgram->SetNbLightsMax (0);
3179 myBgCubeMapProgram->SetNbClipPlanesMax (0);
3180 myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3181 myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
077a220c 3182 }
3183
3184 return myBgCubeMapProgram;
3185}
3186
8625ef7e 3187// =======================================================================
3188// function : bindProgramWithState
3189// purpose :
3190// =======================================================================
08669adf 3191Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
3192 Graphic3d_TypeOfShadingModel theShadingModel)
8625ef7e 3193{
8613985b 3194 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
3195 if (isBound
3196 && !theProgram.IsNull())
8625ef7e 3197 {
8613985b 3198 theProgram->ApplyVariables (myContext);
8625ef7e 3199 }
08669adf 3200 PushState (theProgram, theShadingModel);
8613985b 3201 return isBound;
8625ef7e 3202}
737e9a8d 3203
3204// =======================================================================
3205// function : BindMarkerProgram
3206// purpose :
3207// =======================================================================
3208Standard_Boolean OpenGl_ShaderManager::BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures,
3209 Graphic3d_TypeOfShadingModel theShadingModel,
3210 Graphic3d_AlphaMode theAlphaMode,
3211 Standard_Boolean theHasVertColor,
3212 const Handle(OpenGl_ShaderProgram)& theCustomProgram)
3213{
3214 if (!theCustomProgram.IsNull()
3215 || myContext->caps->ffpEnable)
3216 {
08669adf 3217 return bindProgramWithState (theCustomProgram, theShadingModel);
737e9a8d 3218 }
3219
3220 Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false);
3221 if (!theTextures.IsNull()
3222 && theTextures->HasPointSprite())
3223 {
3224 aBits |= theTextures->Last()->IsAlpha() ? OpenGl_PO_PointSpriteA : OpenGl_PO_PointSprite;
3225 }
3226 else
3227 {
3228 aBits |= OpenGl_PO_PointSimple;
3229 }
3230 Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits);
08669adf 3231 return bindProgramWithState (aProgram, theShadingModel);
737e9a8d 3232}