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 | |
4bf072e4 |
16 | #include <OpenGl_ShaderManager.hxx> |
30f0ad28 |
17 | |
4bf072e4 |
18 | #include <Graphic3d_CubeMapPacked.hxx> |
e135a155 |
19 | #include <Graphic3d_TextureParams.hxx> |
bf5f0ca2 |
20 | #include <OpenGl_Aspects.hxx> |
25c35042 |
21 | #include <OpenGl_ClippingIterator.hxx> |
30f0ad28 |
22 | #include <OpenGl_Context.hxx> |
d84e8669 |
23 | #include <OpenGl_ShadowMap.hxx> |
30f0ad28 |
24 | #include <OpenGl_ShaderProgram.hxx> |
98b15dbf |
25 | #include <OpenGl_VertexBufferCompat.hxx> |
0adbd30f |
26 | #include <OpenGl_Workspace.hxx> |
4bf072e4 |
27 | |
28 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Graphic3d_ShaderManager) |
92efcf78 |
29 | |
8625ef7e |
30 | namespace |
31 | { |
8613985b |
32 | static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; |
33 | static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f }; |
34 | static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f; |
35 | static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f; |
36 | |
37 | //! Bind FFP light source. |
992ed6b3 |
38 | static void bindLight (const Graphic3d_CLight& theLight, |
8613985b |
39 | const GLenum theLightGlId, |
40 | const OpenGl_Mat4& theModelView, |
41 | OpenGl_Context* theCtx) |
42 | { |
43 | // the light is a headlight? |
992ed6b3 |
44 | if (theLight.IsHeadlight()) |
8613985b |
45 | { |
43eddb47 |
46 | theCtx->core11ffp->glMatrixMode (GL_MODELVIEW); |
47 | theCtx->core11ffp->glLoadIdentity(); |
8613985b |
48 | } |
49 | |
50 | // setup light type |
992ed6b3 |
51 | const Graphic3d_Vec4& aLightColor = theLight.PackedColor(); |
52 | switch (theLight.Type()) |
8613985b |
53 | { |
06d40093 |
54 | case Graphic3d_TypeOfLightSource_Ambient: |
55 | { |
56 | break; // handled by separate if-clause at beginning of method |
57 | } |
58 | case Graphic3d_TypeOfLightSource_Directional: |
8613985b |
59 | { |
60 | // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one |
88b312d3 |
61 | const OpenGl_Vec4 anInfDir = -theLight.PackedDirectionRange(); |
8613985b |
62 | |
63 | // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE. |
43eddb47 |
64 | theCtx->core11ffp->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
65 | theCtx->core11ffp->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData()); |
66 | theCtx->core11ffp->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData()); |
67 | theCtx->core11ffp->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData()); |
68 | theCtx->core11ffp->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR); |
69 | theCtx->core11ffp->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT); |
70 | theCtx->core11ffp->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF); |
8613985b |
71 | break; |
72 | } |
06d40093 |
73 | case Graphic3d_TypeOfLightSource_Positional: |
8613985b |
74 | { |
75 | // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE |
992ed6b3 |
76 | const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f); |
43eddb47 |
77 | theCtx->core11ffp->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
78 | theCtx->core11ffp->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData()); |
79 | theCtx->core11ffp->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData()); |
80 | theCtx->core11ffp->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData()); |
81 | theCtx->core11ffp->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR); |
82 | theCtx->core11ffp->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT); |
83 | theCtx->core11ffp->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF); |
84 | theCtx->core11ffp->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation()); |
85 | theCtx->core11ffp->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation()); |
86 | theCtx->core11ffp->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f); |
8613985b |
87 | break; |
88 | } |
06d40093 |
89 | case Graphic3d_TypeOfLightSource_Spot: |
8613985b |
90 | { |
992ed6b3 |
91 | const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f); |
43eddb47 |
92 | theCtx->core11ffp->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
93 | theCtx->core11ffp->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData()); |
94 | theCtx->core11ffp->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData()); |
95 | theCtx->core11ffp->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData()); |
96 | theCtx->core11ffp->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.PackedDirectionRange().GetData()); |
97 | theCtx->core11ffp->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f); |
98 | theCtx->core11ffp->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI)); |
99 | theCtx->core11ffp->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation()); |
100 | theCtx->core11ffp->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation()); |
101 | theCtx->core11ffp->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f); |
8613985b |
102 | break; |
103 | } |
104 | } |
105 | |
106 | // restore matrix in case of headlight |
992ed6b3 |
107 | if (theLight.IsHeadlight()) |
8613985b |
108 | { |
43eddb47 |
109 | theCtx->core11ffp->glLoadMatrixf (theModelView.GetData()); |
8613985b |
110 | } |
111 | |
8f7159cb |
112 | theCtx->core11fwd->glEnable (theLightGlId); |
8613985b |
113 | } |
8625ef7e |
114 | } |
115 | |
30f0ad28 |
116 | // ======================================================================= |
117 | // function : OpenGl_ShaderManager |
118 | // purpose : Creates new empty shader manager |
119 | // ======================================================================= |
120 | OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext) |
8f7159cb |
121 | : Graphic3d_ShaderManager (theContext->GraphicsLibrary()), |
4bf072e4 |
122 | myFfpProgram (new OpenGl_ShaderProgramFFP()), |
13b36bb1 |
123 | myShadingModel (Graphic3d_TypeOfShadingModel_Gouraud), |
6ef0d6f1 |
124 | myUnlitPrograms (new OpenGl_SetOfPrograms()), |
8625ef7e |
125 | myContext (theContext), |
37f80e16 |
126 | myHasLocalOrigin (Standard_False) |
30f0ad28 |
127 | { |
4bf072e4 |
128 | mySRgbState = theContext->ToRenderSRGB(); |
30f0ad28 |
129 | } |
130 | |
131 | // ======================================================================= |
132 | // function : ~OpenGl_ShaderManager |
133 | // purpose : Releases resources of shader manager |
134 | // ======================================================================= |
135 | OpenGl_ShaderManager::~OpenGl_ShaderManager() |
136 | { |
137 | myProgramList.Clear(); |
67312b79 |
138 | if (!myPBREnvironment.IsNull()) |
139 | { |
140 | myPBREnvironment->Release (myContext); |
141 | } |
30f0ad28 |
142 | } |
143 | |
05e2200b |
144 | // ======================================================================= |
145 | // function : clear |
146 | // purpose : |
147 | // ======================================================================= |
148 | void OpenGl_ShaderManager::clear() |
149 | { |
150 | myProgramList.Clear(); |
151 | myLightPrograms.Nullify(); |
6ef0d6f1 |
152 | myUnlitPrograms = new OpenGl_SetOfPrograms(); |
153 | myOutlinePrograms.Nullify(); |
05e2200b |
154 | myMapOfLightPrograms.Clear(); |
155 | myFontProgram.Nullify(); |
ba00aab7 |
156 | myBlitPrograms[0].Init (Handle(OpenGl_ShaderProgram)()); |
157 | myBlitPrograms[1].Init (Handle(OpenGl_ShaderProgram)()); |
98b15dbf |
158 | myBoundBoxProgram.Nullify(); |
159 | myBoundBoxVertBuffer.Nullify(); |
f978241f |
160 | for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter) |
161 | { |
162 | myStereoPrograms[aModeIter].Nullify(); |
163 | } |
05e2200b |
164 | switchLightPrograms(); |
165 | } |
166 | |
30f0ad28 |
167 | // ======================================================================= |
168 | // function : Create |
169 | // purpose : Creates new shader program |
170 | // ======================================================================= |
8625ef7e |
171 | Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy, |
172 | TCollection_AsciiString& theShareKey, |
173 | Handle(OpenGl_ShaderProgram)& theProgram) |
30f0ad28 |
174 | { |
392ac980 |
175 | theProgram.Nullify(); |
176 | if (theProxy.IsNull()) |
30f0ad28 |
177 | { |
8625ef7e |
178 | return Standard_False; |
30f0ad28 |
179 | } |
392ac980 |
180 | |
181 | theShareKey = theProxy->GetId(); |
182 | if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram)) |
183 | { |
05dd08ce |
184 | if (theProgram->Share()) |
185 | { |
186 | myProgramList.Append (theProgram); |
187 | } |
8625ef7e |
188 | return Standard_True; |
392ac980 |
189 | } |
190 | |
191 | theProgram = new OpenGl_ShaderProgram (theProxy); |
192 | if (!theProgram->Initialize (myContext, theProxy->ShaderObjects())) |
30f0ad28 |
193 | { |
392ac980 |
194 | theProgram->Release (myContext); |
195 | theShareKey.Clear(); |
196 | theProgram.Nullify(); |
8625ef7e |
197 | return Standard_False; |
30f0ad28 |
198 | } |
30f0ad28 |
199 | |
392ac980 |
200 | myProgramList.Append (theProgram); |
201 | myContext->ShareResource (theShareKey, theProgram); |
8625ef7e |
202 | return Standard_True; |
30f0ad28 |
203 | } |
204 | |
205 | // ======================================================================= |
206 | // function : Unregister |
207 | // purpose : Removes specified shader program from the manager |
208 | // ======================================================================= |
392ac980 |
209 | void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey, |
210 | Handle(OpenGl_ShaderProgram)& theProgram) |
30f0ad28 |
211 | { |
212 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
213 | { |
214 | if (anIt.Value() == theProgram) |
215 | { |
392ac980 |
216 | if (!theProgram->UnShare()) |
217 | { |
218 | theShareKey.Clear(); |
219 | theProgram.Nullify(); |
220 | return; |
221 | } |
222 | |
30f0ad28 |
223 | myProgramList.Remove (anIt); |
224 | break; |
225 | } |
226 | } |
227 | |
228 | const TCollection_AsciiString anID = theProgram->myProxy->GetId(); |
229 | if (anID.IsEmpty()) |
230 | { |
231 | myContext->DelayedRelease (theProgram); |
232 | theProgram.Nullify(); |
233 | } |
234 | else |
235 | { |
236 | theProgram.Nullify(); |
05dd08ce |
237 | myContext->ReleaseResource (anID, Standard_True); |
30f0ad28 |
238 | } |
239 | } |
240 | |
256f9ac0 |
241 | // ======================================================================= |
242 | // function : switchLightPrograms |
243 | // purpose : |
244 | // ======================================================================= |
245 | void OpenGl_ShaderManager::switchLightPrograms() |
246 | { |
992ed6b3 |
247 | const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources(); |
dc89236f |
248 | if (aLights.IsNull()) |
256f9ac0 |
249 | { |
6ef0d6f1 |
250 | if (!myMapOfLightPrograms.Find ("unlit", myLightPrograms)) |
251 | { |
252 | myLightPrograms = new OpenGl_SetOfShaderPrograms (myUnlitPrograms); |
253 | myMapOfLightPrograms.Bind ("unlit", myLightPrograms); |
254 | } |
dc89236f |
255 | return; |
256 | } |
257 | |
d84e8669 |
258 | const TCollection_AsciiString aKey = genLightKey (aLights, myLightSourceState.HasShadowMaps()); |
256f9ac0 |
259 | if (!myMapOfLightPrograms.Find (aKey, myLightPrograms)) |
260 | { |
261 | myLightPrograms = new OpenGl_SetOfShaderPrograms(); |
262 | myMapOfLightPrograms.Bind (aKey, myLightPrograms); |
263 | } |
264 | } |
265 | |
ba00aab7 |
266 | // ======================================================================= |
267 | // function : UpdateSRgbState |
268 | // purpose : |
269 | // ======================================================================= |
270 | void OpenGl_ShaderManager::UpdateSRgbState() |
271 | { |
272 | if (mySRgbState == myContext->ToRenderSRGB()) |
273 | { |
274 | return; |
275 | } |
276 | |
277 | mySRgbState = myContext->ToRenderSRGB(); |
278 | |
279 | // special cases - GLSL programs dealing with sRGB/linearRGB internally |
280 | myStereoPrograms[Graphic3d_StereoMode_Anaglyph].Nullify(); |
281 | } |
282 | |
30f0ad28 |
283 | // ======================================================================= |
284 | // function : UpdateLightSourceStateTo |
285 | // purpose : Updates state of OCCT light sources |
286 | // ======================================================================= |
67312b79 |
287 | void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights, |
d84e8669 |
288 | Standard_Integer theSpecIBLMapLevels, |
289 | const Handle(OpenGl_ShadowMapArray)& theShadowMaps) |
30f0ad28 |
290 | { |
291 | myLightSourceState.Set (theLights); |
67312b79 |
292 | myLightSourceState.SetSpecIBLMapLevels (theSpecIBLMapLevels); |
d84e8669 |
293 | myLightSourceState.SetShadowMaps (theShadowMaps); |
30f0ad28 |
294 | myLightSourceState.Update(); |
256f9ac0 |
295 | switchLightPrograms(); |
296 | } |
297 | |
7c3ef2f7 |
298 | // ======================================================================= |
299 | // function : UpdateLightSourceState |
300 | // purpose : |
301 | // ======================================================================= |
302 | void OpenGl_ShaderManager::UpdateLightSourceState() |
303 | { |
304 | myLightSourceState.Update(); |
305 | } |
306 | |
256f9ac0 |
307 | // ======================================================================= |
308 | // function : SetShadingModel |
309 | // purpose : |
310 | // ======================================================================= |
c357e426 |
311 | void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel) |
256f9ac0 |
312 | { |
13b36bb1 |
313 | if (theModel == Graphic3d_TypeOfShadingModel_DEFAULT) |
dc89236f |
314 | { |
315 | throw Standard_ProgramError ("OpenGl_ShaderManager::SetShadingModel() - attempt to set invalid Shading Model!"); |
316 | } |
317 | |
256f9ac0 |
318 | myShadingModel = theModel; |
319 | switchLightPrograms(); |
30f0ad28 |
320 | } |
321 | |
322 | // ======================================================================= |
323 | // function : SetProjectionState |
324 | // purpose : Sets new state of OCCT projection transform |
325 | // ======================================================================= |
c827ea3a |
326 | void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix) |
30f0ad28 |
327 | { |
328 | myProjectionState.Set (theProjectionMatrix); |
329 | myProjectionState.Update(); |
330 | } |
331 | |
332 | // ======================================================================= |
333 | // function : SetModelWorldState |
334 | // purpose : Sets new state of OCCT model-world transform |
335 | // ======================================================================= |
c827ea3a |
336 | void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix) |
30f0ad28 |
337 | { |
338 | myModelWorldState.Set (theModelWorldMatrix); |
339 | myModelWorldState.Update(); |
340 | } |
341 | |
342 | // ======================================================================= |
343 | // function : SetWorldViewState |
344 | // purpose : Sets new state of OCCT world-view transform |
345 | // ======================================================================= |
c827ea3a |
346 | void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix) |
30f0ad28 |
347 | { |
348 | myWorldViewState.Set (theWorldViewMatrix); |
349 | myWorldViewState.Update(); |
350 | } |
351 | |
30f0ad28 |
352 | // ======================================================================= |
8cf3bf84 |
353 | // function : pushLightSourceState |
354 | // purpose : |
30f0ad28 |
355 | // ======================================================================= |
8cf3bf84 |
356 | void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
30f0ad28 |
357 | { |
8613985b |
358 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
359 | if (theProgram == myFfpProgram) |
30f0ad28 |
360 | { |
43eddb47 |
361 | if (myContext->core11ffp == NULL) |
8613985b |
362 | { |
363 | return; |
364 | } |
365 | |
daf73ab7 |
366 | GLenum aLightGlId = GL_LIGHT0; |
daf73ab7 |
367 | const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix(); |
992ed6b3 |
368 | for (Graphic3d_LightSet::Iterator aLightIt (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); |
369 | aLightIt.More(); aLightIt.Next()) |
8613985b |
370 | { |
992ed6b3 |
371 | if (aLightGlId > GL_LIGHT7) // only 8 lights in FFP... |
8613985b |
372 | { |
992ed6b3 |
373 | myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, |
374 | "Warning: light sources limit (8) has been exceeded within Fixed-function pipeline."); |
375 | continue; |
8613985b |
376 | } |
992ed6b3 |
377 | |
378 | bindLight (*aLightIt.Value(), aLightGlId, aModelView, myContext); |
379 | ++aLightGlId; |
daf73ab7 |
380 | } |
8613985b |
381 | |
daf73ab7 |
382 | // apply accumulated ambient color |
992ed6b3 |
383 | const Graphic3d_Vec4 anAmbient = !myLightSourceState.LightSources().IsNull() |
384 | ? myLightSourceState.LightSources()->AmbientColor() |
385 | : Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 1.0f); |
43eddb47 |
386 | myContext->core11ffp->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData()); |
8613985b |
387 | |
daf73ab7 |
388 | // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output, |
389 | // therefore managing the state here does not have any effect - do it just for consistency. |
390 | if (aLightGlId != GL_LIGHT0) |
391 | { |
43eddb47 |
392 | myContext->core11fwd->glEnable (GL_LIGHTING); |
daf73ab7 |
393 | } |
394 | else |
395 | { |
43eddb47 |
396 | myContext->core11fwd->glDisable (GL_LIGHTING); |
daf73ab7 |
397 | } |
398 | // switch off unused lights |
399 | for (; aLightGlId <= GL_LIGHT7; ++aLightGlId) |
400 | { |
43eddb47 |
401 | myContext->core11fwd->glDisable (aLightGlId); |
8613985b |
402 | } |
30f0ad28 |
403 | return; |
404 | } |
30f0ad28 |
405 | |
daf73ab7 |
406 | const Standard_Integer aNbLightsMax = theProgram->NbLightsMax(); |
407 | const GLint anAmbientLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT); |
408 | if (aNbLightsMax == 0 |
409 | && anAmbientLoc == OpenGl_ShaderProgram::INVALID_LOCATION) |
01eaf654 |
410 | { |
daf73ab7 |
411 | return; |
01eaf654 |
412 | } |
413 | |
daf73ab7 |
414 | if (myLightTypeArray.Size() < aNbLightsMax) |
415 | { |
416 | myLightTypeArray .Resize (0, aNbLightsMax - 1, false); |
417 | myLightParamsArray.Resize (0, aNbLightsMax - 1, false); |
418 | } |
419 | for (Standard_Integer aLightIt = 0; aLightIt < aNbLightsMax; ++aLightIt) |
420 | { |
9504a30d |
421 | myLightTypeArray.SetValue (aLightIt, -1); |
daf73ab7 |
422 | } |
423 | |
992ed6b3 |
424 | if (myLightSourceState.LightSources().IsNull() |
daf73ab7 |
425 | || myLightSourceState.LightSources()->IsEmpty()) |
12381341 |
426 | { |
30f0ad28 |
427 | theProgram->SetUniform (myContext, |
12381341 |
428 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
429 | 0); |
30f0ad28 |
430 | theProgram->SetUniform (myContext, |
daf73ab7 |
431 | anAmbientLoc, |
12381341 |
432 | OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
01eaf654 |
433 | theProgram->SetUniform (myContext, |
434 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), |
9504a30d |
435 | aNbLightsMax, |
436 | &myLightTypeArray.First()); |
12381341 |
437 | return; |
438 | } |
30f0ad28 |
439 | |
12381341 |
440 | Standard_Integer aLightsNb = 0; |
992ed6b3 |
441 | for (Graphic3d_LightSet::Iterator anIter (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); |
442 | anIter.More(); anIter.Next()) |
12381341 |
443 | { |
992ed6b3 |
444 | const Graphic3d_CLight& aLight = *anIter.Value(); |
445 | if (aLightsNb >= aNbLightsMax) |
12381341 |
446 | { |
daf73ab7 |
447 | if (aNbLightsMax != 0) |
448 | { |
449 | myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, |
450 | TCollection_AsciiString("Warning: light sources limit (") + aNbLightsMax + ") has been exceeded."); |
451 | } |
12381341 |
452 | continue; |
453 | } |
30f0ad28 |
454 | |
9504a30d |
455 | Standard_Integer& aLightType = myLightTypeArray .ChangeValue (aLightsNb); |
daf73ab7 |
456 | OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray.ChangeValue (aLightsNb); |
992ed6b3 |
457 | if (!aLight.IsEnabled()) // has no affect with Graphic3d_LightSet::IterationFilter_ExcludeDisabled - here just for consistency |
7c3ef2f7 |
458 | { |
992ed6b3 |
459 | // 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 |
06d40093 |
460 | aLightType = -1; // Graphic3d_TypeOfLightSource_Ambient can be used instead |
9504a30d |
461 | aLightParams.Color = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f); |
992ed6b3 |
462 | ++aLightsNb; |
463 | continue; |
7c3ef2f7 |
464 | } |
992ed6b3 |
465 | |
ba00aab7 |
466 | // ignoring OpenGl_Context::ToRenderSRGB() for light colors, |
467 | // as non-absolute colors for lights are rare and require tuning anyway |
9504a30d |
468 | aLightType = aLight.Type(); |
992ed6b3 |
469 | aLightParams.Color = aLight.PackedColor(); |
67312b79 |
470 | aLightParams.Color.a() = aLight.Intensity(); // used by PBR and ignored by old shading model |
37f80e16 |
471 | aLightParams.Parameters = aLight.PackedParams(); |
472 | switch (aLight.Type()) |
88b312d3 |
473 | { |
06d40093 |
474 | case Graphic3d_TypeOfLightSource_Ambient: |
37f80e16 |
475 | { |
476 | break; |
477 | } |
06d40093 |
478 | case Graphic3d_TypeOfLightSource_Directional: |
37f80e16 |
479 | { |
480 | if (aLight.IsHeadlight()) |
481 | { |
482 | const Graphic3d_Mat4& anOrientInv = myWorldViewState.WorldViewMatrixInverse(); |
483 | aLightParams.Position = anOrientInv * Graphic3d_Vec4 (-aLight.PackedDirection(), 0.0f); |
b470ebea |
484 | aLightParams.Position.SetValues (aLightParams.Position.xyz().Normalized(), 0.0f); |
37f80e16 |
485 | } |
486 | else |
487 | { |
488 | aLightParams.Position = Graphic3d_Vec4 (-aLight.PackedDirection(), 0.0f); |
489 | } |
490 | break; |
491 | } |
06d40093 |
492 | case Graphic3d_TypeOfLightSource_Spot: |
37f80e16 |
493 | { |
494 | if (aLight.IsHeadlight()) |
495 | { |
496 | const Graphic3d_Mat4& anOrientInv = myWorldViewState.WorldViewMatrixInverse(); |
497 | aLightParams.Direction = anOrientInv * Graphic3d_Vec4 (aLight.PackedDirection(), 0.0f); |
b470ebea |
498 | aLightParams.Direction.SetValues (aLightParams.Direction.xyz().Normalized(), 0.0f); |
37f80e16 |
499 | } |
500 | else |
501 | { |
502 | aLightParams.Direction = Graphic3d_Vec4 (aLight.PackedDirection(), 0.0f); |
503 | } |
504 | } |
505 | Standard_FALLTHROUGH |
06d40093 |
506 | case Graphic3d_TypeOfLightSource_Positional: |
37f80e16 |
507 | { |
508 | if (aLight.IsHeadlight()) |
509 | { |
510 | aLightParams.Position.x() = static_cast<float>(aLight.Position().X()); |
511 | aLightParams.Position.y() = static_cast<float>(aLight.Position().Y()); |
512 | aLightParams.Position.z() = static_cast<float>(aLight.Position().Z()); |
513 | const Graphic3d_Mat4& anOrientInv = myWorldViewState.WorldViewMatrixInverse(); |
514 | aLightParams.Position = anOrientInv * Graphic3d_Vec4 (aLightParams.Position.xyz(), 1.0f); |
515 | } |
516 | else |
517 | { |
518 | aLightParams.Position.x() = static_cast<float>(aLight.Position().X() - myLocalOrigin.X()); |
519 | aLightParams.Position.y() = static_cast<float>(aLight.Position().Y() - myLocalOrigin.Y()); |
520 | aLightParams.Position.z() = static_cast<float>(aLight.Position().Z() - myLocalOrigin.Z()); |
521 | aLightParams.Position.w() = 0.0f; |
522 | } |
523 | aLightParams.Direction.w() = aLight.Range(); |
524 | break; |
525 | } |
30f0ad28 |
526 | } |
12381341 |
527 | ++aLightsNb; |
528 | } |
30f0ad28 |
529 | |
992ed6b3 |
530 | const Graphic3d_Vec4& anAmbient = myLightSourceState.LightSources()->AmbientColor(); |
12381341 |
531 | theProgram->SetUniform (myContext, |
532 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
533 | aLightsNb); |
534 | theProgram->SetUniform (myContext, |
daf73ab7 |
535 | anAmbientLoc, |
12381341 |
536 | anAmbient); |
01eaf654 |
537 | theProgram->SetUniform (myContext, |
538 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), |
9504a30d |
539 | aNbLightsMax, |
540 | &myLightTypeArray.First()); |
12381341 |
541 | if (aLightsNb > 0) |
542 | { |
4fe9ad57 |
543 | theProgram->SetUniform (myContext, |
544 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS), |
545 | aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(), |
daf73ab7 |
546 | myLightParamsArray.First().Packed()); |
30f0ad28 |
547 | } |
67312b79 |
548 | |
549 | if (const OpenGl_ShaderUniformLocation aLocation = theProgram->GetStateLocation (OpenGl_OCCT_NB_SPEC_IBL_LEVELS)) |
550 | { |
551 | theProgram->SetUniform (myContext, aLocation, myLightSourceState.SpecIBLMapLevels()); |
552 | } |
d84e8669 |
553 | |
554 | // update shadow map variables |
555 | if (const OpenGl_ShaderUniformLocation aShadowMatLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES)) |
556 | { |
557 | if (myShadowMatArray.Size() < theProgram->NbShadowMaps()) |
558 | { |
559 | myShadowMatArray.Resize (0, theProgram->NbShadowMaps() - 1, false); |
560 | } |
561 | |
562 | Graphic3d_Vec2 aSizeBias; |
563 | if (myLightSourceState.HasShadowMaps()) |
564 | { |
565 | aSizeBias.SetValues (1.0f / (float )myLightSourceState.ShadowMaps()->First()->Texture()->SizeX(), |
566 | myLightSourceState.ShadowMaps()->First()->ShadowMapBias()); |
567 | const Standard_Integer aNbShadows = Min (theProgram->NbShadowMaps(), myLightSourceState.ShadowMaps()->Size()); |
568 | for (Standard_Integer aShadowIter = 0; aShadowIter < aNbShadows; ++aShadowIter) |
569 | { |
570 | const Handle(OpenGl_ShadowMap)& aShadow = myLightSourceState.ShadowMaps()->Value (aShadowIter); |
571 | myShadowMatArray[aShadowIter] = aShadow->LightSourceMatrix(); |
572 | } |
573 | } |
574 | |
575 | theProgram->SetUniform (myContext, aShadowMatLoc, theProgram->NbShadowMaps(), &myShadowMatArray.First()); |
576 | theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS), aSizeBias); |
577 | } |
30f0ad28 |
578 | } |
579 | |
580 | // ======================================================================= |
8cf3bf84 |
581 | // function : pushProjectionState |
582 | // purpose : |
30f0ad28 |
583 | // ======================================================================= |
8cf3bf84 |
584 | void OpenGl_ShaderManager::pushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
30f0ad28 |
585 | { |
8613985b |
586 | theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index()); |
587 | if (theProgram == myFfpProgram) |
588 | { |
43eddb47 |
589 | if (myContext->core11ffp != NULL) |
8613985b |
590 | { |
43eddb47 |
591 | myContext->core11ffp->glMatrixMode (GL_PROJECTION); |
a2af24d1 |
592 | myContext->core11ffp->glLoadMatrixf (myProjectionState.ProjectionMatrix().GetData()); |
8613985b |
593 | } |
8613985b |
594 | return; |
595 | } |
596 | |
30f0ad28 |
597 | theProgram->SetUniform (myContext, |
598 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX), |
599 | myProjectionState.ProjectionMatrix()); |
600 | |
601 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE); |
602 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
603 | { |
604 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse()); |
605 | } |
606 | |
607 | theProgram->SetUniform (myContext, |
608 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE), |
609 | myProjectionState.ProjectionMatrix(), true); |
610 | |
611 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE); |
612 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
613 | { |
614 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true); |
615 | } |
30f0ad28 |
616 | } |
617 | |
618 | // ======================================================================= |
8cf3bf84 |
619 | // function : pushModelWorldState |
620 | // purpose : |
30f0ad28 |
621 | // ======================================================================= |
8cf3bf84 |
622 | void OpenGl_ShaderManager::pushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
30f0ad28 |
623 | { |
8613985b |
624 | theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index()); |
625 | if (theProgram == myFfpProgram) |
626 | { |
43eddb47 |
627 | if (myContext->core11ffp != NULL) |
8613985b |
628 | { |
629 | const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix(); |
43eddb47 |
630 | myContext->core11ffp->glMatrixMode (GL_MODELVIEW); |
631 | myContext->core11ffp->glLoadMatrixf (aModelView.GetData()); |
8613985b |
632 | theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index()); |
633 | } |
8613985b |
634 | return; |
635 | } |
636 | |
30f0ad28 |
637 | theProgram->SetUniform (myContext, |
638 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX), |
639 | myModelWorldState.ModelWorldMatrix()); |
640 | |
641 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE); |
642 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
643 | { |
644 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse()); |
645 | } |
646 | |
647 | theProgram->SetUniform (myContext, |
648 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE), |
649 | myModelWorldState.ModelWorldMatrix(), true); |
650 | |
651 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE); |
652 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
653 | { |
654 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true); |
655 | } |
30f0ad28 |
656 | } |
657 | |
658 | // ======================================================================= |
8cf3bf84 |
659 | // function : pushWorldViewState |
660 | // purpose : |
30f0ad28 |
661 | // ======================================================================= |
8cf3bf84 |
662 | void OpenGl_ShaderManager::pushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
30f0ad28 |
663 | { |
664 | if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE)) |
665 | { |
666 | return; |
667 | } |
668 | |
8613985b |
669 | theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index()); |
670 | if (theProgram == myFfpProgram) |
671 | { |
43eddb47 |
672 | if (myContext->core11ffp != NULL) |
8613985b |
673 | { |
674 | const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix(); |
43eddb47 |
675 | myContext->core11ffp->glMatrixMode (GL_MODELVIEW); |
676 | myContext->core11ffp->glLoadMatrixf (aModelView.GetData()); |
8613985b |
677 | theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index()); |
678 | } |
8613985b |
679 | return; |
680 | } |
681 | |
30f0ad28 |
682 | theProgram->SetUniform (myContext, |
683 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX), |
684 | myWorldViewState.WorldViewMatrix()); |
685 | |
686 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE); |
687 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
688 | { |
689 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse()); |
690 | } |
691 | |
692 | theProgram->SetUniform (myContext, |
693 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE), |
694 | myWorldViewState.WorldViewMatrix(), true); |
695 | |
696 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE); |
697 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
698 | { |
699 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true); |
700 | } |
30f0ad28 |
701 | } |
702 | |
703 | // ======================================================================= |
704 | // function : UpdateClippingState |
705 | // purpose : Updates state of OCCT clipping planes |
706 | // ======================================================================= |
707 | void OpenGl_ShaderManager::UpdateClippingState() |
708 | { |
709 | myClippingState.Update(); |
710 | } |
711 | |
712 | // ======================================================================= |
713 | // function : RevertClippingState |
714 | // purpose : Reverts state of OCCT clipping planes |
715 | // ======================================================================= |
716 | void OpenGl_ShaderManager::RevertClippingState() |
717 | { |
718 | myClippingState.Revert(); |
719 | } |
720 | |
721 | // ======================================================================= |
8cf3bf84 |
722 | // function : pushClippingState |
723 | // purpose : |
30f0ad28 |
724 | // ======================================================================= |
8cf3bf84 |
725 | void OpenGl_ShaderManager::pushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
30f0ad28 |
726 | { |
12381341 |
727 | theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index()); |
8613985b |
728 | if (theProgram == myFfpProgram) |
729 | { |
43eddb47 |
730 | if (myContext->core11ffp == NULL) |
8613985b |
731 | { |
732 | return; |
733 | } |
734 | |
daf73ab7 |
735 | const Standard_Integer aNbMaxPlanes = myContext->MaxClipPlanes(); |
736 | if (myClipPlaneArrayFfp.Size() < aNbMaxPlanes) |
737 | { |
738 | myClipPlaneArrayFfp.Resize (0, aNbMaxPlanes - 1, false); |
739 | } |
740 | |
8613985b |
741 | Standard_Integer aPlaneId = 0; |
742 | Standard_Boolean toRestoreModelView = Standard_False; |
25c35042 |
743 | const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain(); |
8613985b |
744 | for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next()) |
745 | { |
746 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value(); |
25c35042 |
747 | if (aPlaneIter.IsDisabled() |
748 | || aPlane->IsChain() |
749 | || (aPlane == aCappedChain |
750 | && myContext->Clipping().IsCappingEnableAllExcept())) |
8613985b |
751 | { |
752 | continue; |
753 | } |
754 | else if (aPlaneId >= aNbMaxPlanes) |
755 | { |
4bf072e4 |
756 | Message::SendWarning() << "OpenGl_ShaderManager, warning: clipping planes limit (" << aNbMaxPlanes << ") has been exceeded"; |
8613985b |
757 | break; |
758 | } |
759 | |
760 | const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation(); |
daf73ab7 |
761 | OpenGl_Vec4d& aPlaneEq = myClipPlaneArrayFfp.ChangeValue (aPlaneId); |
8613985b |
762 | aPlaneEq.x() = anEquation.x(); |
763 | aPlaneEq.y() = anEquation.y(); |
764 | aPlaneEq.z() = anEquation.z(); |
765 | aPlaneEq.w() = anEquation.w(); |
766 | if (myHasLocalOrigin) |
767 | { |
768 | const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin; |
769 | const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z()); |
770 | aPlaneEq.w() = aD; |
771 | } |
772 | |
773 | const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId; |
774 | if (anFfpPlaneID == GL_CLIP_PLANE0) |
775 | { |
776 | // set either identity or pure view matrix |
777 | toRestoreModelView = Standard_True; |
43eddb47 |
778 | myContext->core11ffp->glMatrixMode (GL_MODELVIEW); |
779 | myContext->core11ffp->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData()); |
8613985b |
780 | } |
781 | |
43eddb47 |
782 | myContext->core11fwd->glEnable (anFfpPlaneID); |
783 | myContext->core11ffp->glClipPlane (anFfpPlaneID, aPlaneEq); |
8613985b |
784 | |
785 | ++aPlaneId; |
786 | } |
787 | |
788 | // switch off unused lights |
789 | for (; aPlaneId < aNbMaxPlanes; ++aPlaneId) |
790 | { |
43eddb47 |
791 | myContext->core11fwd->glDisable (GL_CLIP_PLANE0 + aPlaneId); |
8613985b |
792 | } |
793 | |
794 | // restore combined model-view matrix |
795 | if (toRestoreModelView) |
796 | { |
797 | const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix(); |
43eddb47 |
798 | myContext->core11ffp->glLoadMatrixf (aModelView.GetData()); |
8613985b |
799 | } |
8613985b |
800 | return; |
801 | } |
802 | |
12381341 |
803 | const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS); |
89a929ea |
804 | if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION) |
12381341 |
805 | { |
806 | return; |
807 | } |
808 | |
daf73ab7 |
809 | const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax(); |
25c35042 |
810 | const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax); |
3202bf1e |
811 | if (aNbPlanes < 1) |
12381341 |
812 | { |
25c35042 |
813 | theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0); |
12381341 |
814 | return; |
815 | } |
816 | |
daf73ab7 |
817 | if (myClipPlaneArray.Size() < aNbClipPlanesMax) |
818 | { |
819 | myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false); |
25c35042 |
820 | myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false); |
daf73ab7 |
821 | } |
822 | |
823 | Standard_Integer aPlaneId = 0; |
25c35042 |
824 | const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain(); |
3202bf1e |
825 | for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next()) |
12381341 |
826 | { |
3202bf1e |
827 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value(); |
828 | if (aPlaneIter.IsDisabled()) |
30f0ad28 |
829 | { |
12381341 |
830 | continue; |
30f0ad28 |
831 | } |
25c35042 |
832 | |
833 | if (myContext->Clipping().IsCappingDisableAllExcept()) |
89a929ea |
834 | { |
25c35042 |
835 | // enable only specific (sub) plane |
836 | if (aPlane != aCappedChain) |
837 | { |
838 | continue; |
839 | } |
840 | |
841 | Standard_Integer aSubPlaneIndex = 1; |
842 | for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex) |
843 | { |
844 | if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane()) |
845 | { |
846 | addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1); |
847 | break; |
848 | } |
849 | } |
89a929ea |
850 | break; |
851 | } |
25c35042 |
852 | else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept() |
853 | { |
854 | // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane |
855 | if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax) |
856 | { |
857 | myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, |
858 | TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded."); |
859 | break; |
860 | } |
30f0ad28 |
861 | |
25c35042 |
862 | Standard_Integer aSubPlaneIndex = 1; |
863 | for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex) |
864 | { |
865 | if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane()) |
866 | { |
867 | addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1); |
868 | } |
869 | } |
870 | } |
871 | else |
7c3ef2f7 |
872 | { |
25c35042 |
873 | // normal case |
874 | if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax) |
875 | { |
876 | myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, |
877 | TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded."); |
878 | break; |
879 | } |
880 | for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get()) |
881 | { |
882 | addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes()); |
883 | } |
7c3ef2f7 |
884 | } |
30f0ad28 |
885 | } |
5495fa7e |
886 | |
25c35042 |
887 | theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId); |
daf73ab7 |
888 | theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First()); |
25c35042 |
889 | theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First()); |
30f0ad28 |
890 | } |
891 | |
8613985b |
892 | // ======================================================================= |
8cf3bf84 |
893 | // function : pushMaterialState |
8613985b |
894 | // purpose : |
895 | // ======================================================================= |
8cf3bf84 |
896 | void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
8613985b |
897 | { |
941f6cae |
898 | const OpenGl_Material& aMat = myMaterialState.Material(); |
8613985b |
899 | theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index()); |
900 | if (theProgram == myFfpProgram) |
901 | { |
43eddb47 |
902 | if (myContext->core11ffp == NULL) |
8613985b |
903 | { |
904 | return; |
905 | } |
906 | |
c40eb6b9 |
907 | if (myMaterialState.AlphaCutoff() < ShortRealLast()) |
908 | { |
43eddb47 |
909 | myContext->core11fwd->glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff()); |
910 | myContext->core11fwd->glEnable (GL_ALPHA_TEST); |
c40eb6b9 |
911 | } |
912 | else |
913 | { |
43eddb47 |
914 | myContext->core11fwd->glDisable (GL_ALPHA_TEST); |
c40eb6b9 |
915 | } |
916 | |
8613985b |
917 | const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK; |
941f6cae |
918 | const OpenGl_MaterialCommon& aFrontMat = aMat.Common[0]; |
919 | const OpenGl_MaterialCommon& aBackMat = aMat.Common[1]; |
920 | const Graphic3d_Vec4 aSpec4 (aFrontMat.SpecularShininess.rgb(), 1.0f); |
43eddb47 |
921 | myContext->core11ffp->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Ambient.GetData()); |
922 | myContext->core11ffp->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Diffuse.GetData()); |
923 | myContext->core11ffp->glMaterialfv(aFrontFace, GL_SPECULAR, aSpec4.GetData()); |
924 | myContext->core11ffp->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Emission.GetData()); |
925 | myContext->core11ffp->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Shine()); |
8613985b |
926 | if (myMaterialState.ToDistinguish()) |
927 | { |
941f6cae |
928 | const Graphic3d_Vec4 aSpec4Back (aBackMat.SpecularShininess.rgb(), 1.0f); |
43eddb47 |
929 | myContext->core11ffp->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Ambient.GetData()); |
930 | myContext->core11ffp->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Diffuse.GetData()); |
931 | myContext->core11ffp->glMaterialfv(GL_BACK, GL_SPECULAR, aSpec4Back.GetData()); |
932 | myContext->core11ffp->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Emission.GetData()); |
933 | myContext->core11ffp->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Shine()); |
8613985b |
934 | } |
8613985b |
935 | return; |
936 | } |
937 | |
c40eb6b9 |
938 | theProgram->SetUniform (myContext, |
939 | theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF), |
940 | myMaterialState.AlphaCutoff()); |
8613985b |
941 | theProgram->SetUniform (myContext, |
942 | theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), |
943 | myMaterialState.ToMapTexture() ? 1 : 0); |
944 | theProgram->SetUniform (myContext, |
945 | theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), |
946 | myMaterialState.ToDistinguish() ? 1 : 0); |
947 | |
941f6cae |
948 | if (const OpenGl_ShaderUniformLocation& aLocPbrFront = theProgram->GetStateLocation (OpenGl_OCCT_PBR_MATERIAL)) |
8613985b |
949 | { |
941f6cae |
950 | theProgram->SetUniform (myContext, aLocPbrFront, OpenGl_Material::NbOfVec4Pbr(), aMat.PackedPbr()); |
8613985b |
951 | } |
941f6cae |
952 | if (const OpenGl_ShaderUniformLocation& aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_MATERIAL)) |
8613985b |
953 | { |
941f6cae |
954 | theProgram->SetUniform (myContext, aLocFront, OpenGl_Material::NbOfVec4Common(), aMat.PackedCommon()); |
8613985b |
955 | } |
956 | } |
957 | |
a1073ae2 |
958 | // ======================================================================= |
8cf3bf84 |
959 | // function : pushOitState |
960 | // purpose : |
a1073ae2 |
961 | // ======================================================================= |
8cf3bf84 |
962 | void OpenGl_ShaderManager::pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
a1073ae2 |
963 | { |
78c4e836 |
964 | if (const OpenGl_ShaderUniformLocation& aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT)) |
a1073ae2 |
965 | { |
78c4e836 |
966 | theProgram->SetUniform (myContext, aLocOutput, (GLint )myOitState.ActiveMode()); |
a1073ae2 |
967 | } |
78c4e836 |
968 | if (const OpenGl_ShaderUniformLocation& aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR)) |
a1073ae2 |
969 | { |
970 | theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor()); |
971 | } |
972 | } |
973 | |
2a332745 |
974 | // ======================================================================= |
975 | // function : PushInteriorState |
976 | // purpose : |
977 | // ======================================================================= |
978 | void OpenGl_ShaderManager::PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram, |
bf5f0ca2 |
979 | const Handle(Graphic3d_Aspects)& theAspect) const |
2a332745 |
980 | { |
981 | if (theProgram.IsNull() |
982 | || !theProgram->IsValid()) |
983 | { |
984 | return; |
985 | } |
986 | |
2a332745 |
987 | if (const OpenGl_ShaderUniformLocation aLocLineWidth = theProgram->GetStateLocation (OpenGl_OCCT_LINE_WIDTH)) |
988 | { |
989 | theProgram->SetUniform (myContext, aLocLineWidth, theAspect->EdgeWidth() * myContext->LineWidthScale()); |
990 | theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCCT_LINE_FEATHER), myContext->LineFeather() * myContext->LineWidthScale()); |
991 | } |
992 | if (const OpenGl_ShaderUniformLocation aLocWireframeColor = theProgram->GetStateLocation (OpenGl_OCCT_WIREFRAME_COLOR)) |
993 | { |
994 | if (theAspect->InteriorStyle() == Aspect_IS_HOLLOW) |
995 | { |
996 | theProgram->SetUniform (myContext, aLocWireframeColor, OpenGl_Vec4 (-1.0f, -1.0f, -1.0f, -1.0f)); |
997 | } |
998 | else |
999 | { |
ba00aab7 |
1000 | theProgram->SetUniform (myContext, aLocWireframeColor, myContext->Vec4FromQuantityColor (theAspect->EdgeColorRGBA())); |
2a332745 |
1001 | } |
1002 | } |
1003 | if (const OpenGl_ShaderUniformLocation aLocQuadModeState = theProgram->GetStateLocation (OpenGl_OCCT_QUAD_MODE_STATE)) |
1004 | { |
1005 | theProgram->SetUniform (myContext, aLocQuadModeState, theAspect->ToSkipFirstEdge() ? 1 : 0); |
1006 | } |
1007 | } |
1008 | |
30f0ad28 |
1009 | // ======================================================================= |
e135a155 |
1010 | // function : PushState |
30f0ad28 |
1011 | // purpose : Pushes state of OCCT graphics parameters to the program |
1012 | // ======================================================================= |
08669adf |
1013 | void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram, |
1014 | Graphic3d_TypeOfShadingModel theShadingModel) const |
30f0ad28 |
1015 | { |
8613985b |
1016 | const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram; |
1017 | PushClippingState (aProgram); |
37f80e16 |
1018 | PushLightSourceState (aProgram); // should be before PushWorldViewState() |
8613985b |
1019 | PushWorldViewState (aProgram); |
1020 | PushModelWorldState (aProgram); |
1021 | PushProjectionState (aProgram); |
8613985b |
1022 | PushMaterialState (aProgram); |
a1073ae2 |
1023 | PushOitState (aProgram); |
8cf3bf84 |
1024 | |
1025 | if (!theProgram.IsNull()) |
1026 | { |
1027 | if (const OpenGl_ShaderUniformLocation& aLocViewPort = theProgram->GetStateLocation (OpenGl_OCCT_VIEWPORT)) |
1028 | { |
1029 | theProgram->SetUniform (myContext, aLocViewPort, OpenGl_Vec4 ((float )myContext->Viewport()[0], (float )myContext->Viewport()[1], |
1030 | (float )myContext->Viewport()[2], (float )myContext->Viewport()[3])); |
1031 | } |
1032 | } |
43eddb47 |
1033 | else if (myContext->core11ffp != NULL) |
08669adf |
1034 | { |
1035 | // manage FFP lighting |
1036 | myContext->SetShadeModel (theShadingModel); |
13b36bb1 |
1037 | if (theShadingModel == Graphic3d_TypeOfShadingModel_Unlit) |
08669adf |
1038 | { |
43eddb47 |
1039 | myContext->core11fwd->glDisable (GL_LIGHTING); |
08669adf |
1040 | } |
1041 | else |
1042 | { |
43eddb47 |
1043 | myContext->core11fwd->glEnable (GL_LIGHTING); |
08669adf |
1044 | } |
1045 | } |
12381341 |
1046 | } |
8625ef7e |
1047 | |
1048 | // ======================================================================= |
4bf072e4 |
1049 | // function : BindFontProgram |
8625ef7e |
1050 | // purpose : |
1051 | // ======================================================================= |
4bf072e4 |
1052 | Standard_Boolean OpenGl_ShaderManager::BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram) |
8625ef7e |
1053 | { |
4bf072e4 |
1054 | if (!theCustomProgram.IsNull() |
1055 | || myContext->caps->ffpEnable) |
4e1523ef |
1056 | { |
13b36bb1 |
1057 | return bindProgramWithState (theCustomProgram, Graphic3d_TypeOfShadingModel_Unlit); |
4e1523ef |
1058 | } |
4e1523ef |
1059 | |
4bf072e4 |
1060 | if (myFontProgram.IsNull()) |
8625ef7e |
1061 | { |
4bf072e4 |
1062 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramFont(); |
1063 | TCollection_AsciiString aKey; |
1064 | if (!Create (aProgramSrc, aKey, myFontProgram)) |
1065 | { |
1066 | myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1067 | return false; |
1068 | } |
8625ef7e |
1069 | } |
4bf072e4 |
1070 | |
13b36bb1 |
1071 | return bindProgramWithState (myFontProgram, Graphic3d_TypeOfShadingModel_Unlit); |
8625ef7e |
1072 | } |
1073 | |
ba00aab7 |
1074 | // ======================================================================= |
1075 | // function : BindFboBlitProgram |
1076 | // purpose : |
1077 | // ======================================================================= |
1078 | Standard_Boolean OpenGl_ShaderManager::BindFboBlitProgram (Standard_Integer theNbSamples, |
1079 | Standard_Boolean theIsFallback_sRGB) |
1080 | { |
1081 | NCollection_Array1<Handle(OpenGl_ShaderProgram)>& aList = myBlitPrograms[theIsFallback_sRGB ? 1 : 0]; |
1082 | Standard_Integer aNbSamples = Max (theNbSamples, 1); |
1083 | if (aNbSamples > aList.Upper()) |
1084 | { |
1085 | aList.Resize (1, aNbSamples, true); |
1086 | } |
1087 | |
1088 | Handle(OpenGl_ShaderProgram)& aProg = aList[aNbSamples]; |
4bf072e4 |
1089 | if (!aProg.IsNull()) |
ba00aab7 |
1090 | { |
4bf072e4 |
1091 | return myContext->BindProgram (aProg); |
ba00aab7 |
1092 | } |
ba00aab7 |
1093 | |
4bf072e4 |
1094 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramFboBlit (aNbSamples, theIsFallback_sRGB); |
b86bb3df |
1095 | TCollection_AsciiString aKey; |
4bf072e4 |
1096 | if (!Create (aProgramSrc, aKey, aProg)) |
b86bb3df |
1097 | { |
4bf072e4 |
1098 | aProg = new OpenGl_ShaderProgram(); // just mark as invalid |
1099 | return false; |
b86bb3df |
1100 | } |
1101 | |
4bf072e4 |
1102 | myContext->BindProgram (aProg); |
1103 | aProg->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0); |
1104 | aProg->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1); |
1105 | return true; |
b86bb3df |
1106 | } |
1107 | |
a1073ae2 |
1108 | // ======================================================================= |
4bf072e4 |
1109 | // function : BindOitCompositingProgram |
a1073ae2 |
1110 | // purpose : |
1111 | // ======================================================================= |
4bf072e4 |
1112 | Standard_Boolean OpenGl_ShaderManager::BindOitCompositingProgram (Standard_Boolean theIsMSAAEnabled) |
a1073ae2 |
1113 | { |
4bf072e4 |
1114 | const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; |
1115 | Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[aProgramIdx]; |
1116 | if (!aProgram.IsNull()) |
a1073ae2 |
1117 | { |
4bf072e4 |
1118 | return myContext->BindProgram (aProgram); |
1119 | } |
1120 | |
1121 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramOitCompositing (theIsMSAAEnabled); |
a1073ae2 |
1122 | TCollection_AsciiString aKey; |
1123 | if (!Create (aProgramSrc, aKey, aProgram)) |
1124 | { |
1125 | aProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
4bf072e4 |
1126 | return false; |
a1073ae2 |
1127 | } |
1128 | |
1129 | myContext->BindProgram (aProgram); |
cc8cbabe |
1130 | aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0); |
1131 | aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1); |
4bf072e4 |
1132 | return true; |
a1073ae2 |
1133 | } |
1134 | |
78c4e836 |
1135 | // ======================================================================= |
4bf072e4 |
1136 | // function : BindOitDepthPeelingBlendProgram |
78c4e836 |
1137 | // purpose : |
1138 | // ======================================================================= |
4bf072e4 |
1139 | Standard_Boolean OpenGl_ShaderManager::BindOitDepthPeelingBlendProgram (bool theIsMSAAEnabled) |
78c4e836 |
1140 | { |
4bf072e4 |
1141 | const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; |
1142 | Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingBlendProgram [aProgramIdx]; |
1143 | if (!aProgram.IsNull()) |
1144 | { |
1145 | return myContext->BindProgram (aProgram); |
1146 | } |
1147 | |
1148 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramOitDepthPeelingBlend (theIsMSAAEnabled); |
78c4e836 |
1149 | TCollection_AsciiString aKey; |
1150 | if (!Create (aProgramSrc, aKey, aProgram)) |
1151 | { |
1152 | aProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1153 | return false; |
1154 | } |
1155 | |
1156 | myContext->BindProgram (aProgram); |
1157 | aProgram->SetSampler (myContext, "uDepthPeelingBackColor", Graphic3d_TextureUnit_0); |
78c4e836 |
1158 | return true; |
1159 | } |
1160 | |
1161 | // ======================================================================= |
4bf072e4 |
1162 | // function : BindOitDepthPeelingFlushProgram |
78c4e836 |
1163 | // purpose : |
1164 | // ======================================================================= |
4bf072e4 |
1165 | Standard_Boolean OpenGl_ShaderManager::BindOitDepthPeelingFlushProgram (bool theIsMSAAEnabled) |
78c4e836 |
1166 | { |
4bf072e4 |
1167 | const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0; |
1168 | Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingFlushProgram [aProgramIdx]; |
1169 | if (!aProgram.IsNull()) |
1170 | { |
1171 | return myContext->BindProgram (aProgram); |
1172 | } |
1173 | |
1174 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramOitDepthPeelingFlush (theIsMSAAEnabled); |
78c4e836 |
1175 | TCollection_AsciiString aKey; |
1176 | if (!Create (aProgramSrc, aKey, aProgram)) |
1177 | { |
1178 | aProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1179 | return false; |
1180 | } |
1181 | |
1182 | myContext->BindProgram (aProgram); |
1183 | aProgram->SetSampler (myContext, "uDepthPeelingFrontColor", Graphic3d_TextureUnit_0); |
1184 | aProgram->SetSampler (myContext, "uDepthPeelingBackColor", Graphic3d_TextureUnit_1); |
78c4e836 |
1185 | return true; |
1186 | } |
1187 | |
b86bb3df |
1188 | // ======================================================================= |
dc89236f |
1189 | // function : prepareStdProgramUnlit |
8625ef7e |
1190 | // purpose : |
1191 | // ======================================================================= |
dc89236f |
1192 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram, |
6ef0d6f1 |
1193 | Standard_Integer theBits, |
1194 | Standard_Boolean theIsOutline) |
8625ef7e |
1195 | { |
4bf072e4 |
1196 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramUnlit (theBits, theIsOutline); |
8625ef7e |
1197 | TCollection_AsciiString aKey; |
1198 | if (!Create (aProgramSrc, aKey, theProgram)) |
1199 | { |
1200 | theProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1201 | return Standard_False; |
1202 | } |
1203 | return Standard_True; |
1204 | } |
1205 | |
1206 | // ======================================================================= |
1207 | // function : prepareStdProgramGouraud |
1208 | // purpose : |
1209 | // ======================================================================= |
1210 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram, |
1211 | const Standard_Integer theBits) |
1212 | { |
4bf072e4 |
1213 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramGouraud (myLightSourceState.LightSources(), theBits); |
8625ef7e |
1214 | TCollection_AsciiString aKey; |
1215 | if (!Create (aProgramSrc, aKey, theProgram)) |
1216 | { |
1217 | theProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1218 | return Standard_False; |
1219 | } |
1220 | return Standard_True; |
1221 | } |
1222 | |
1223 | // ======================================================================= |
1224 | // function : prepareStdProgramPhong |
1225 | // purpose : |
1226 | // ======================================================================= |
1227 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram, |
8c3237d4 |
1228 | const Standard_Integer theBits, |
67312b79 |
1229 | const Standard_Boolean theIsFlatNormal, |
1230 | const Standard_Boolean theIsPBR) |
8625ef7e |
1231 | { |
d84e8669 |
1232 | Standard_Integer aNbShadowMaps = myLightSourceState.HasShadowMaps() |
1233 | ? myLightSourceState.LightSources()->NbCastShadows() |
1234 | : 0; |
4bf072e4 |
1235 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramPhong (myLightSourceState.LightSources(), theBits, theIsFlatNormal, theIsPBR, aNbShadowMaps); |
8625ef7e |
1236 | TCollection_AsciiString aKey; |
1237 | if (!Create (aProgramSrc, aKey, theProgram)) |
1238 | { |
1239 | theProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1240 | return Standard_False; |
1241 | } |
1242 | return Standard_True; |
1243 | } |
1244 | |
38a0206f |
1245 | // ======================================================================= |
4bf072e4 |
1246 | // function : BindStereoProgram |
38a0206f |
1247 | // purpose : |
1248 | // ======================================================================= |
4bf072e4 |
1249 | Standard_Boolean OpenGl_ShaderManager::BindStereoProgram (Graphic3d_StereoMode theStereoMode) |
38a0206f |
1250 | { |
2275caec |
1251 | if (theStereoMode < 0 || (int )theStereoMode >= Graphic3d_StereoMode_NB) |
4bf072e4 |
1252 | { |
1253 | return false; |
f978241f |
1254 | } |
38a0206f |
1255 | |
4bf072e4 |
1256 | Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[theStereoMode]; |
1257 | if (!aProgram.IsNull()) |
1258 | { |
1259 | return myContext->BindProgram (aProgram); |
1260 | } |
1261 | |
1262 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramStereo (theStereoMode); |
38a0206f |
1263 | TCollection_AsciiString aKey; |
4bf072e4 |
1264 | if (!Create (aProgramSrc, aKey, aProgram)) |
38a0206f |
1265 | { |
4bf072e4 |
1266 | aProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1267 | return false; |
38a0206f |
1268 | } |
1269 | |
4bf072e4 |
1270 | myContext->BindProgram (aProgram); |
1271 | aProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0); |
1272 | aProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1); |
2275caec |
1273 | aProgram->SetUniform (myContext, "uTexOffset", Graphic3d_Vec2(0.0f)); |
4bf072e4 |
1274 | return true; |
38a0206f |
1275 | } |
1276 | |
98b15dbf |
1277 | // ======================================================================= |
1278 | // function : prepareStdProgramBoundBox |
1279 | // purpose : |
1280 | // ======================================================================= |
1281 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox() |
1282 | { |
4bf072e4 |
1283 | Handle(Graphic3d_ShaderProgram) aProgramSrc = Graphic3d_ShaderManager::getStdProgramBoundBox(); |
98b15dbf |
1284 | TCollection_AsciiString aKey; |
1285 | if (!Create (aProgramSrc, aKey, myBoundBoxProgram)) |
1286 | { |
1287 | myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1288 | return Standard_False; |
1289 | } |
1290 | |
1291 | const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f); |
1292 | const OpenGl_Vec4 anAxisShifts[3] = |
1293 | { |
1294 | OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f), |
1295 | OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f), |
1296 | OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f) |
1297 | }; |
1298 | |
1299 | const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f); |
1300 | const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f); |
1301 | OpenGl_Vec4 aLinesVertices[24]; |
1302 | for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis) |
1303 | { |
1304 | for (int aCompIter = 0; aCompIter < 4; ++aCompIter) |
1305 | { |
1306 | aLinesVertices[aVertex++] = aMin |
1307 | + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter] |
1308 | + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter]; |
1309 | |
1310 | aLinesVertices[aVertex++] = aMin |
1311 | + anAxisShifts[anAxis] |
1312 | + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter] |
1313 | + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter]; |
1314 | } |
1315 | } |
1316 | if (myContext->ToUseVbo()) |
1317 | { |
1318 | myBoundBoxVertBuffer = new OpenGl_VertexBuffer(); |
1319 | if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData())) |
1320 | { |
1321 | myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer); |
1322 | return Standard_True; |
1323 | } |
1324 | } |
1325 | myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat(); |
1326 | myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()); |
1327 | myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer); |
1328 | return Standard_True; |
1329 | } |
1330 | |
67312b79 |
1331 | // ======================================================================= |
1332 | // function : preparePBREnvBakingProgram |
1333 | // purpose : |
1334 | // ======================================================================= |
8f8fe4a9 |
1335 | Standard_Boolean OpenGl_ShaderManager::preparePBREnvBakingProgram (Standard_Integer theIndex) |
67312b79 |
1336 | { |
4bf072e4 |
1337 | Handle(Graphic3d_ShaderProgram) aProgramSrc = getPBREnvBakingProgram (theIndex); |
67312b79 |
1338 | TCollection_AsciiString aKey; |
8f8fe4a9 |
1339 | if (!Create (aProgramSrc, aKey, myPBREnvBakingProgram[theIndex])) |
67312b79 |
1340 | { |
8f8fe4a9 |
1341 | myPBREnvBakingProgram[theIndex] = new OpenGl_ShaderProgram(); // just mark as invalid |
67312b79 |
1342 | return Standard_False; |
1343 | } |
1344 | |
8f8fe4a9 |
1345 | if (theIndex == 0 |
1346 | || theIndex == 2) |
1347 | { |
1348 | // workaround for old GLSL - load constants as uniform |
1349 | myContext->BindProgram (myPBREnvBakingProgram[theIndex]); |
1350 | const float aSHBasisFuncCoeffs[9] = |
1351 | { |
1352 | 0.282095f * 0.282095f, 0.488603f * 0.488603f, 0.488603f * 0.488603f, 0.488603f * 0.488603f, |
1353 | 1.092548f * 1.092548f, 1.092548f * 1.092548f, 1.092548f * 1.092548f, 0.315392f * 0.315392f, 0.546274f * 0.546274f |
1354 | }; |
1355 | const float aSHCosCoeffs[9] = { 3.141593f, 2.094395f, 2.094395f, 2.094395f, 0.785398f, 0.785398f, 0.785398f, 0.785398f, 0.785398f }; |
1356 | myPBREnvBakingProgram[theIndex]->SetUniform (myContext, myPBREnvBakingProgram[theIndex]->GetUniformLocation (myContext, "aSHBasisFuncCoeffs"), 9, aSHBasisFuncCoeffs); |
1357 | myPBREnvBakingProgram[theIndex]->SetUniform (myContext, myPBREnvBakingProgram[theIndex]->GetUniformLocation (myContext, "aSHCosCoeffs"), 9, aSHCosCoeffs); |
1358 | myContext->BindProgram (NULL); |
1359 | } |
1360 | |
67312b79 |
1361 | return Standard_True; |
1362 | } |
1363 | |
077a220c |
1364 | // ======================================================================= |
1365 | // function : GetBgCubeMapProgram |
1366 | // purpose : |
1367 | // ======================================================================= |
1368 | const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram () |
1369 | { |
1370 | if (myBgCubeMapProgram.IsNull()) |
1371 | { |
4bf072e4 |
1372 | myBgCubeMapProgram = getBgCubeMapProgram(); |
077a220c |
1373 | } |
077a220c |
1374 | return myBgCubeMapProgram; |
1375 | } |
1376 | |
16a263dc |
1377 | // ======================================================================= |
1378 | // function : GetBgSkydomeProgram |
1379 | // purpose : |
1380 | // ======================================================================= |
1381 | const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgSkydomeProgram () |
1382 | { |
1383 | if (myBgSkydomeProgram.IsNull()) |
1384 | { |
1385 | myBgSkydomeProgram = getBgSkydomeProgram(); |
1386 | } |
1387 | return myBgSkydomeProgram; |
1388 | } |
1389 | |
956d9157 |
1390 | // ======================================================================= |
1391 | // function : GetColoredQuadProgram |
1392 | // purpose : |
1393 | // ======================================================================= |
1394 | const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetColoredQuadProgram () |
1395 | { |
1396 | if (myColoredQuadProgram.IsNull()) |
1397 | { |
1398 | myColoredQuadProgram = getColoredQuadProgram(); |
1399 | } |
1400 | return myColoredQuadProgram; |
1401 | } |
1402 | |
8625ef7e |
1403 | // ======================================================================= |
1404 | // function : bindProgramWithState |
1405 | // purpose : |
1406 | // ======================================================================= |
08669adf |
1407 | Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram, |
1408 | Graphic3d_TypeOfShadingModel theShadingModel) |
8625ef7e |
1409 | { |
8613985b |
1410 | const Standard_Boolean isBound = myContext->BindProgram (theProgram); |
1411 | if (isBound |
1412 | && !theProgram.IsNull()) |
8625ef7e |
1413 | { |
8613985b |
1414 | theProgram->ApplyVariables (myContext); |
8625ef7e |
1415 | } |
08669adf |
1416 | PushState (theProgram, theShadingModel); |
8613985b |
1417 | return isBound; |
8625ef7e |
1418 | } |
737e9a8d |
1419 | |
1420 | // ======================================================================= |
1421 | // function : BindMarkerProgram |
1422 | // purpose : |
1423 | // ======================================================================= |
1424 | Standard_Boolean OpenGl_ShaderManager::BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures, |
1425 | Graphic3d_TypeOfShadingModel theShadingModel, |
1426 | Graphic3d_AlphaMode theAlphaMode, |
1427 | Standard_Boolean theHasVertColor, |
1428 | const Handle(OpenGl_ShaderProgram)& theCustomProgram) |
1429 | { |
1430 | if (!theCustomProgram.IsNull() |
1431 | || myContext->caps->ffpEnable) |
1432 | { |
08669adf |
1433 | return bindProgramWithState (theCustomProgram, theShadingModel); |
737e9a8d |
1434 | } |
1435 | |
1436 | Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false); |
1437 | if (!theTextures.IsNull() |
1438 | && theTextures->HasPointSprite()) |
1439 | { |
4bf072e4 |
1440 | aBits |= theTextures->Last()->IsAlpha() ? Graphic3d_ShaderFlags_PointSpriteA : Graphic3d_ShaderFlags_PointSprite; |
737e9a8d |
1441 | } |
1442 | else |
1443 | { |
4bf072e4 |
1444 | aBits |= Graphic3d_ShaderFlags_PointSimple; |
737e9a8d |
1445 | } |
1446 | Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits); |
08669adf |
1447 | return bindProgramWithState (aProgram, theShadingModel); |
737e9a8d |
1448 | } |