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