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 | |
18 | #include <OpenGl_AspectFace.hxx> |
19 | #include <OpenGl_AspectLine.hxx> |
20 | #include <OpenGl_AspectMarker.hxx> |
21 | #include <OpenGl_AspectText.hxx> |
22 | #include <OpenGl_Clipping.hxx> |
23 | #include <OpenGl_Context.hxx> |
24 | #include <OpenGl_ShaderManager.hxx> |
25 | #include <OpenGl_ShaderProgram.hxx> |
0adbd30f |
26 | #include <OpenGl_Workspace.hxx> |
30f0ad28 |
27 | |
28 | IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient) |
29 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient) |
30 | |
8625ef7e |
31 | namespace |
32 | { |
33 | |
34 | #define EOL "\n" |
35 | |
36 | //! Auxiliary function to transform normal |
37 | const char THE_FUNC_transformNormal[] = |
38 | EOL"vec3 transformNormal (in vec3 theNormal)" |
39 | EOL"{" |
40 | EOL" vec4 aResult = occWorldViewMatrixInverseTranspose" |
41 | EOL" * occModelWorldMatrixInverseTranspose" |
42 | EOL" * vec4 (theNormal, 0.0);" |
43 | EOL" return normalize (aResult.xyz);" |
44 | EOL"}"; |
45 | |
46 | //! Global shader variable for color definition with lighting enabled. |
47 | const char THE_FUNC_lightDef[] = |
48 | EOL"vec3 Ambient;" //!< Ambient contribution of light sources |
49 | EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources |
50 | EOL"vec3 Specular;"; //!< Specular contribution of light sources |
51 | |
52 | //! Computes illumination from light sources |
53 | const char THE_FUNC_computeLighting[] = |
54 | EOL"vec4 computeLighting (in vec3 theNormal," |
55 | EOL" in vec3 theView," |
56 | EOL" in vec4 thePoint," |
57 | EOL" in bool theIsFront)" |
58 | EOL"{" |
59 | // clear the light intensity accumulators |
60 | EOL" Ambient = occLightAmbient.rgb;" |
61 | EOL" Diffuse = vec3 (0.0);" |
62 | EOL" Specular = vec3 (0.0);" |
63 | EOL" vec3 aPoint = thePoint.xyz / thePoint.w;" |
64 | EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)" |
65 | EOL" {" |
66 | EOL" int aType = occLight_Type (anIndex);" |
67 | EOL" if (aType == OccLightType_Direct)" |
68 | EOL" {" |
69 | EOL" directionalLight (anIndex, theNormal, theView, theIsFront);" |
70 | EOL" }" |
71 | EOL" else if (aType == OccLightType_Point)" |
72 | EOL" {" |
73 | EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);" |
74 | EOL" }" |
75 | EOL" else if (aType == OccLightType_Spot)" |
76 | EOL" {" |
77 | EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);" |
78 | EOL" }" |
79 | EOL" }" |
80 | EOL |
81 | EOL" vec4 aMaterialAmbient = theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();" |
82 | EOL" vec4 aMaterialDiffuse = theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();" |
83 | EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();" |
84 | EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();" |
85 | EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient" |
86 | EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse" |
87 | EOL" + vec4 (Specular, 1.0) * aMaterialSpecular" |
88 | EOL" + aMaterialEmission;" |
89 | EOL"}"; |
90 | |
91 | //! Function computes contribution of isotropic point light source |
92 | const char THE_FUNC_pointLight[] = |
93 | EOL"void pointLight (in int theId," |
94 | EOL" in vec3 theNormal," |
95 | EOL" in vec3 theView," |
96 | EOL" in vec3 thePoint," |
97 | EOL" in bool theIsFront)" |
98 | EOL"{" |
99 | EOL" vec3 aLight = occLight_Position (theId).xyz;" |
100 | EOL" if (occLight_IsHeadlight (theId) == 0)" |
101 | EOL" {" |
102 | EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));" |
103 | EOL" }" |
104 | EOL" aLight -= thePoint;" |
105 | EOL |
106 | EOL" float aDist = length (aLight);" |
107 | EOL" aLight = aLight * (1.0 / aDist);" |
108 | EOL |
109 | EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)" |
110 | EOL" + occLight_LinearAttenuation (theId) * aDist);" |
111 | EOL |
112 | EOL" vec3 aHalf = normalize (aLight + theView);" |
113 | EOL |
114 | EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;" |
115 | EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));" |
116 | EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));" |
117 | EOL |
118 | EOL" float aSpecl = 0.0;" |
119 | EOL" if (aNdotL > 0.0)" |
120 | EOL" {" |
121 | EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());" |
122 | EOL" }" |
123 | EOL |
124 | EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;" |
125 | EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;" |
126 | EOL"}"; |
127 | |
128 | //! Function computes contribution of spotlight source |
129 | const char THE_FUNC_spotLight[] = |
130 | EOL"void spotLight (in int theId," |
131 | EOL" in vec3 theNormal," |
132 | EOL" in vec3 theView," |
133 | EOL" in vec3 thePoint," |
134 | EOL" in bool theIsFront)" |
135 | EOL"{" |
136 | EOL" vec3 aLight = occLight_Position (theId).xyz;" |
137 | EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;" |
138 | EOL" if (occLight_IsHeadlight (theId) == 0)" |
139 | EOL" {" |
140 | EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));" |
141 | EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));" |
142 | EOL" }" |
143 | EOL" aLight -= thePoint;" |
144 | EOL |
145 | EOL" float aDist = length (aLight);" |
146 | EOL" aLight = aLight * (1.0 / aDist);" |
147 | EOL |
148 | EOL" aSpotDir = normalize (aSpotDir);" |
149 | // light cone |
150 | EOL" float aCosA = dot (aSpotDir, -aLight);" |
151 | EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))" |
152 | EOL" {" |
153 | EOL" return;" |
154 | EOL" }" |
155 | EOL |
156 | EOL" float anExponent = occLight_SpotExponent (theId);" |
157 | EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)" |
158 | EOL" + occLight_LinearAttenuation (theId) * aDist);" |
159 | EOL" if (anExponent > 0.0)" |
160 | EOL" {" |
161 | EOL" anAtten *= pow (aCosA, anExponent * 128.0);" |
162 | EOL" }" |
163 | EOL |
164 | EOL" vec3 aHalf = normalize (aLight + theView);" |
165 | EOL |
166 | EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;" |
167 | EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));" |
168 | EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));" |
169 | EOL |
170 | EOL" float aSpecl = 0.0;" |
171 | EOL" if (aNdotL > 0.0)" |
172 | EOL" {" |
173 | EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());" |
174 | EOL" }" |
175 | EOL |
176 | EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;" |
177 | EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;" |
178 | EOL"}"; |
179 | |
180 | //! Function computes contribution of directional light source |
181 | const char THE_FUNC_directionalLight[] = |
182 | EOL"void directionalLight (in int theId," |
183 | EOL" in vec3 theNormal," |
184 | EOL" in vec3 theView," |
185 | EOL" in bool theIsFront)" |
186 | EOL"{" |
187 | EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);" |
188 | EOL" if (occLight_IsHeadlight (theId) == 0)" |
189 | EOL" {" |
190 | EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.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 |
205 | EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;" |
206 | EOL" Specular += occLight_Specular (theId).rgb * aSpecl;" |
207 | EOL"}"; |
208 | |
209 | //! Process clipping planes in Fragment Shader. |
210 | //! Should be added at the beginning of the main() function. |
211 | const char THE_FRAG_CLIP_PLANES[] = |
212 | EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)" |
213 | EOL" {" |
214 | EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];" |
215 | EOL" int aClipSpace = occClipPlaneSpaces[aPlaneIter];" |
216 | EOL" if (aClipSpace == OccEquationCoords_World)" |
217 | EOL" {" |
218 | EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)" |
219 | EOL" {" |
220 | EOL" discard;" |
221 | EOL" }" |
222 | EOL" }" |
223 | EOL" else if (aClipSpace == OccEquationCoords_View)" |
224 | EOL" {" |
225 | EOL" if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)" |
226 | EOL" {" |
227 | EOL" discard;" |
228 | EOL" }" |
229 | EOL" }" |
230 | EOL" }"; |
231 | |
232 | } |
233 | |
30f0ad28 |
234 | // ======================================================================= |
235 | // function : OpenGl_ShaderManager |
236 | // purpose : Creates new empty shader manager |
237 | // ======================================================================= |
238 | OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext) |
8625ef7e |
239 | : myShadingModel (Visual3d_TOM_VERTEX), |
240 | myContext (theContext), |
e6804ff7 |
241 | myLastView (NULL) |
30f0ad28 |
242 | { |
8625ef7e |
243 | myLightPrograms = myGouraudPrograms; |
30f0ad28 |
244 | } |
245 | |
246 | // ======================================================================= |
247 | // function : ~OpenGl_ShaderManager |
248 | // purpose : Releases resources of shader manager |
249 | // ======================================================================= |
250 | OpenGl_ShaderManager::~OpenGl_ShaderManager() |
251 | { |
252 | myProgramList.Clear(); |
253 | } |
254 | |
255 | // ======================================================================= |
256 | // function : Create |
257 | // purpose : Creates new shader program |
258 | // ======================================================================= |
8625ef7e |
259 | Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy, |
260 | TCollection_AsciiString& theShareKey, |
261 | Handle(OpenGl_ShaderProgram)& theProgram) |
30f0ad28 |
262 | { |
392ac980 |
263 | theProgram.Nullify(); |
264 | if (theProxy.IsNull()) |
30f0ad28 |
265 | { |
8625ef7e |
266 | return Standard_False; |
30f0ad28 |
267 | } |
392ac980 |
268 | |
269 | theShareKey = theProxy->GetId(); |
270 | if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram)) |
271 | { |
05dd08ce |
272 | if (theProgram->Share()) |
273 | { |
274 | myProgramList.Append (theProgram); |
275 | } |
8625ef7e |
276 | return Standard_True; |
392ac980 |
277 | } |
278 | |
279 | theProgram = new OpenGl_ShaderProgram (theProxy); |
280 | if (!theProgram->Initialize (myContext, theProxy->ShaderObjects())) |
30f0ad28 |
281 | { |
392ac980 |
282 | theProgram->Release (myContext); |
283 | theShareKey.Clear(); |
284 | theProgram.Nullify(); |
8625ef7e |
285 | return Standard_False; |
30f0ad28 |
286 | } |
30f0ad28 |
287 | |
392ac980 |
288 | myProgramList.Append (theProgram); |
289 | myContext->ShareResource (theShareKey, theProgram); |
8625ef7e |
290 | return Standard_True; |
30f0ad28 |
291 | } |
292 | |
293 | // ======================================================================= |
294 | // function : Unregister |
295 | // purpose : Removes specified shader program from the manager |
296 | // ======================================================================= |
392ac980 |
297 | void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey, |
298 | Handle(OpenGl_ShaderProgram)& theProgram) |
30f0ad28 |
299 | { |
300 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
301 | { |
302 | if (anIt.Value() == theProgram) |
303 | { |
392ac980 |
304 | if (!theProgram->UnShare()) |
305 | { |
306 | theShareKey.Clear(); |
307 | theProgram.Nullify(); |
308 | return; |
309 | } |
310 | |
30f0ad28 |
311 | myProgramList.Remove (anIt); |
392ac980 |
312 | myMaterialStates.UnBind (theProgram); |
30f0ad28 |
313 | break; |
314 | } |
315 | } |
316 | |
317 | const TCollection_AsciiString anID = theProgram->myProxy->GetId(); |
318 | if (anID.IsEmpty()) |
319 | { |
320 | myContext->DelayedRelease (theProgram); |
321 | theProgram.Nullify(); |
322 | } |
323 | else |
324 | { |
325 | theProgram.Nullify(); |
05dd08ce |
326 | myContext->ReleaseResource (anID, Standard_True); |
30f0ad28 |
327 | } |
328 | } |
329 | |
330 | // ======================================================================= |
331 | // function : ShaderPrograms |
332 | // purpose : Returns list of registered shader programs |
333 | // ======================================================================= |
334 | const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const |
335 | { |
336 | return myProgramList; |
337 | } |
338 | |
339 | // ======================================================================= |
340 | // function : Empty |
341 | // purpose : Returns true if no program objects are attached |
342 | // ======================================================================= |
343 | Standard_Boolean OpenGl_ShaderManager::IsEmpty() const |
344 | { |
345 | return myProgramList.IsEmpty(); |
346 | } |
347 | |
348 | // ======================================================================= |
349 | // function : UpdateLightSourceStateTo |
350 | // purpose : Updates state of OCCT light sources |
351 | // ======================================================================= |
352 | void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights) |
353 | { |
354 | myLightSourceState.Set (theLights); |
355 | myLightSourceState.Update(); |
356 | } |
357 | |
358 | // ======================================================================= |
359 | // function : SetProjectionState |
360 | // purpose : Sets new state of OCCT projection transform |
361 | // ======================================================================= |
b5ac8292 |
362 | void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3* theProjectionMatrix) |
30f0ad28 |
363 | { |
364 | myProjectionState.Set (theProjectionMatrix); |
365 | myProjectionState.Update(); |
366 | } |
367 | |
368 | // ======================================================================= |
369 | // function : SetModelWorldState |
370 | // purpose : Sets new state of OCCT model-world transform |
371 | // ======================================================================= |
b5ac8292 |
372 | void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3* theModelWorldMatrix) |
30f0ad28 |
373 | { |
374 | myModelWorldState.Set (theModelWorldMatrix); |
375 | myModelWorldState.Update(); |
376 | } |
377 | |
378 | // ======================================================================= |
379 | // function : SetWorldViewState |
380 | // purpose : Sets new state of OCCT world-view transform |
381 | // ======================================================================= |
b5ac8292 |
382 | void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3* theWorldViewMatrix) |
30f0ad28 |
383 | { |
384 | myWorldViewState.Set (theWorldViewMatrix); |
385 | myWorldViewState.Update(); |
386 | } |
387 | |
388 | // ======================================================================= |
389 | // function : RevertProjectionStateTo |
390 | // purpose : Reverts state of OCCT projection transform |
391 | // ======================================================================= |
b5ac8292 |
392 | void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3* theProjectionMatrix) |
30f0ad28 |
393 | { |
394 | myProjectionState.Set (theProjectionMatrix); |
395 | myProjectionState.Revert(); |
396 | } |
397 | |
398 | // ======================================================================= |
399 | // function : RevertModelWorldStateTo |
400 | // purpose : Reverts state of OCCT model-world transform |
401 | // ======================================================================= |
b5ac8292 |
402 | void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3* theModelWorldMatrix) |
30f0ad28 |
403 | { |
404 | myModelWorldState.Set (theModelWorldMatrix); |
405 | myModelWorldState.Revert(); |
406 | } |
407 | |
408 | // ======================================================================= |
409 | // function : RevertWorldViewStateTo |
410 | // purpose : Reverts state of OCCT world-view transform |
411 | // ======================================================================= |
b5ac8292 |
412 | void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3* theWorldViewMatrix) |
30f0ad28 |
413 | { |
414 | myWorldViewState.Set (theWorldViewMatrix); |
415 | myWorldViewState.Revert(); |
416 | } |
417 | |
418 | // ======================================================================= |
419 | // function : LightSourceState |
420 | // purpose : Returns current state of OCCT light sources |
421 | // ======================================================================= |
422 | const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const |
423 | { |
424 | return myLightSourceState; |
425 | } |
426 | |
427 | // ======================================================================= |
428 | // function : ProjectionState |
429 | // purpose : Returns current state of OCCT projection transform |
430 | // ======================================================================= |
431 | const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const |
432 | { |
433 | return myProjectionState; |
434 | } |
435 | |
436 | // ======================================================================= |
437 | // function : ModelWorldState |
438 | // purpose : Returns current state of OCCT model-world transform |
439 | // ======================================================================= |
440 | const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const |
441 | { |
442 | return myModelWorldState; |
443 | } |
444 | |
445 | // ======================================================================= |
446 | // function : WorldViewState |
447 | // purpose : Returns current state of OCCT world-view transform |
448 | // ======================================================================= |
449 | const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const |
450 | { |
451 | return myWorldViewState; |
452 | } |
453 | |
4fe9ad57 |
454 | //! Packed properties of light source |
455 | class OpenGl_ShaderLightParameters |
456 | { |
457 | public: |
458 | |
459 | OpenGl_Vec4 Color; |
460 | OpenGl_Vec4 Position; |
461 | OpenGl_Vec4 Direction; |
462 | OpenGl_Vec4 Parameters; |
463 | |
464 | //! Returns packed (serialized) representation of light source properties |
0adbd30f |
465 | const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); } |
01eaf654 |
466 | static Standard_Integer NbOfVec4() { return 4; } |
4fe9ad57 |
467 | |
468 | }; |
469 | |
470 | //! Packed light source type information |
471 | class OpenGl_ShaderLightType |
472 | { |
473 | public: |
474 | |
475 | Standard_Integer Type; |
476 | Standard_Integer IsHeadlight; |
477 | |
478 | //! Returns packed (serialized) representation of light source type |
0adbd30f |
479 | const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); } |
01eaf654 |
480 | static Standard_Integer NbOfVec2i() { return 1; } |
4fe9ad57 |
481 | |
482 | }; |
483 | |
30f0ad28 |
484 | // ======================================================================= |
485 | // function : PushLightSourceState |
486 | // purpose : Pushes state of OCCT light sources to the program |
487 | // ======================================================================= |
488 | void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
489 | { |
12381341 |
490 | if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE) |
491 | || !theProgram->IsValid()) |
30f0ad28 |
492 | { |
493 | return; |
494 | } |
30f0ad28 |
495 | |
01eaf654 |
496 | OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights]; |
497 | for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt) |
498 | { |
499 | aLightTypeArray[aLightIt].Type = -1; |
500 | } |
501 | |
12381341 |
502 | const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights); |
503 | if (aLightsDefNb < 1) |
504 | { |
30f0ad28 |
505 | theProgram->SetUniform (myContext, |
12381341 |
506 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
507 | 0); |
30f0ad28 |
508 | theProgram->SetUniform (myContext, |
12381341 |
509 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT), |
510 | OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
01eaf654 |
511 | theProgram->SetUniform (myContext, |
512 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), |
513 | OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(), |
514 | aLightTypeArray[0].Packed()); |
12381341 |
515 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
0c4033b4 |
516 | delete[] aLightTypeArray; |
12381341 |
517 | return; |
518 | } |
30f0ad28 |
519 | |
4fe9ad57 |
520 | OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb]; |
30f0ad28 |
521 | |
12381341 |
522 | OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f); |
523 | Standard_Integer aLightsNb = 0; |
524 | for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next()) |
525 | { |
526 | const OpenGl_Light& aLight = anIter.Value(); |
527 | if (aLight.Type == Visual3d_TOLS_AMBIENT) |
30f0ad28 |
528 | { |
12381341 |
529 | anAmbient += aLight.Color; |
530 | continue; |
531 | } |
532 | else if (aLightsNb >= OpenGLMaxLights) |
533 | { |
534 | continue; |
535 | } |
30f0ad28 |
536 | |
4fe9ad57 |
537 | OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb]; |
538 | aLightType.Type = aLight.Type; |
539 | aLightType.IsHeadlight = aLight.IsHeadlight; |
30f0ad28 |
540 | |
4fe9ad57 |
541 | OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb]; |
542 | aLightParams.Color = aLight.Color; |
543 | aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL |
544 | ? -aLight.Direction |
545 | : aLight.Position; |
12381341 |
546 | if (aLight.Type == Visual3d_TOLS_SPOT) |
547 | { |
4fe9ad57 |
548 | aLightParams.Direction = aLight.Direction; |
30f0ad28 |
549 | } |
4fe9ad57 |
550 | aLightParams.Parameters = aLight.Params; |
12381341 |
551 | ++aLightsNb; |
552 | } |
30f0ad28 |
553 | |
12381341 |
554 | theProgram->SetUniform (myContext, |
555 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
556 | aLightsNb); |
557 | theProgram->SetUniform (myContext, |
558 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT), |
559 | anAmbient); |
01eaf654 |
560 | theProgram->SetUniform (myContext, |
561 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), |
562 | OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(), |
563 | aLightTypeArray[0].Packed()); |
12381341 |
564 | if (aLightsNb > 0) |
565 | { |
4fe9ad57 |
566 | theProgram->SetUniform (myContext, |
567 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS), |
568 | aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(), |
569 | aLightParamsArray[0].Packed()); |
30f0ad28 |
570 | } |
4fe9ad57 |
571 | delete[] aLightParamsArray; |
572 | delete[] aLightTypeArray; |
30f0ad28 |
573 | |
574 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
575 | } |
576 | |
577 | // ======================================================================= |
578 | // function : PushProjectionState |
579 | // purpose : Pushes state of OCCT projection transform to the program |
580 | // ======================================================================= |
581 | void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
582 | { |
583 | if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE)) |
584 | { |
585 | return; |
586 | } |
587 | |
588 | theProgram->SetUniform (myContext, |
589 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX), |
590 | myProjectionState.ProjectionMatrix()); |
591 | |
592 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE); |
593 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
594 | { |
595 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse()); |
596 | } |
597 | |
598 | theProgram->SetUniform (myContext, |
599 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE), |
600 | myProjectionState.ProjectionMatrix(), true); |
601 | |
602 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE); |
603 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
604 | { |
605 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true); |
606 | } |
607 | |
608 | theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index()); |
609 | } |
610 | |
611 | // ======================================================================= |
612 | // function : PushModelWorldState |
613 | // purpose : Pushes state of OCCT model-world transform to the program |
614 | // ======================================================================= |
615 | void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
616 | { |
617 | if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE)) |
618 | { |
619 | return; |
620 | } |
621 | |
622 | theProgram->SetUniform (myContext, |
623 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX), |
624 | myModelWorldState.ModelWorldMatrix()); |
625 | |
626 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE); |
627 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
628 | { |
629 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse()); |
630 | } |
631 | |
632 | theProgram->SetUniform (myContext, |
633 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE), |
634 | myModelWorldState.ModelWorldMatrix(), true); |
635 | |
636 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE); |
637 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
638 | { |
639 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true); |
640 | } |
641 | |
642 | theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index()); |
643 | } |
644 | |
645 | // ======================================================================= |
646 | // function : PushWorldViewState |
647 | // purpose : Pushes state of OCCT world-view transform to the program |
648 | // ======================================================================= |
649 | void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
650 | { |
651 | if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE)) |
652 | { |
653 | return; |
654 | } |
655 | |
656 | theProgram->SetUniform (myContext, |
657 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX), |
658 | myWorldViewState.WorldViewMatrix()); |
659 | |
660 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE); |
661 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
662 | { |
663 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse()); |
664 | } |
665 | |
666 | theProgram->SetUniform (myContext, |
667 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE), |
668 | myWorldViewState.WorldViewMatrix(), true); |
669 | |
670 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE); |
671 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
672 | { |
673 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true); |
674 | } |
675 | |
676 | theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index()); |
677 | } |
678 | |
679 | // ======================================================================= |
680 | // function : UpdateClippingState |
681 | // purpose : Updates state of OCCT clipping planes |
682 | // ======================================================================= |
683 | void OpenGl_ShaderManager::UpdateClippingState() |
684 | { |
685 | myClippingState.Update(); |
686 | } |
687 | |
688 | // ======================================================================= |
689 | // function : RevertClippingState |
690 | // purpose : Reverts state of OCCT clipping planes |
691 | // ======================================================================= |
692 | void OpenGl_ShaderManager::RevertClippingState() |
693 | { |
694 | myClippingState.Revert(); |
695 | } |
696 | |
697 | // ======================================================================= |
698 | // function : PushClippingState |
699 | // purpose : Pushes state of OCCT clipping planes to the program |
700 | // ======================================================================= |
701 | void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
702 | { |
703 | if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE)) |
704 | { |
705 | return; |
706 | } |
707 | |
12381341 |
708 | theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index()); |
709 | const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS); |
710 | const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES); |
711 | if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION |
712 | && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION) |
713 | { |
714 | return; |
715 | } |
716 | |
5495fa7e |
717 | GLint aPlanesNb = 0; |
51b10cd4 |
718 | for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); |
12381341 |
719 | anIter.More(); anIter.Next()) |
30f0ad28 |
720 | { |
721 | const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); |
722 | if (!myContext->Clipping().IsEnabled (aPlane)) |
723 | { |
724 | continue; |
725 | } |
726 | |
12381341 |
727 | ++aPlanesNb; |
728 | } |
729 | if (aPlanesNb < 1) |
730 | { |
731 | return; |
732 | } |
733 | |
5495fa7e |
734 | const Standard_Size MAX_CLIP_PLANES = 8; |
735 | OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES]; |
736 | GLint* aSpaces = new GLint [MAX_CLIP_PLANES]; |
12381341 |
737 | GLuint aPlaneId = 0; |
51b10cd4 |
738 | for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); |
12381341 |
739 | anIter.More(); anIter.Next()) |
740 | { |
741 | const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); |
742 | if (!myContext->Clipping().IsEnabled (aPlane)) |
30f0ad28 |
743 | { |
12381341 |
744 | continue; |
30f0ad28 |
745 | } |
746 | |
12381341 |
747 | const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation(); |
748 | anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(), |
749 | (float) anEquation.y(), |
750 | (float) anEquation.z(), |
751 | (float) anEquation.w()); |
752 | aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane); |
753 | ++aPlaneId; |
30f0ad28 |
754 | } |
5495fa7e |
755 | |
756 | theProgram->SetUniform (myContext, |
757 | theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), |
758 | aPlanesNb); |
759 | theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations); |
760 | theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces); |
4fe9ad57 |
761 | |
12381341 |
762 | delete[] anEquations; |
763 | delete[] aSpaces; |
30f0ad28 |
764 | } |
765 | |
766 | // ======================================================================= |
767 | // function : UpdateMaterialStateTo |
768 | // purpose : Updates state of OCCT material for specified program |
769 | // ======================================================================= |
770 | void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram, |
771 | const OpenGl_Element* theAspect) |
772 | { |
773 | if (myMaterialStates.IsBound (theProgram)) |
774 | { |
595a42a4 |
775 | OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram); |
776 | aState.Set (theAspect); |
777 | aState.Update(); |
30f0ad28 |
778 | } |
779 | else |
780 | { |
595a42a4 |
781 | myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect)); |
782 | myMaterialStates.ChangeFind (theProgram).Update(); |
30f0ad28 |
783 | } |
30f0ad28 |
784 | } |
785 | |
786 | // ======================================================================= |
787 | // function : ResetMaterialStates |
788 | // purpose : Resets state of OCCT material for all programs |
789 | // ======================================================================= |
790 | void OpenGl_ShaderManager::ResetMaterialStates() |
791 | { |
792 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
793 | { |
794 | anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0); |
795 | } |
796 | } |
797 | |
798 | // ======================================================================= |
799 | // function : MaterialState |
800 | // purpose : Returns state of OCCT material for specified program |
801 | // ======================================================================= |
802 | const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
803 | { |
804 | if (!myMaterialStates.IsBound (theProgram)) |
805 | return NULL; |
806 | |
807 | return &myMaterialStates.Find (theProgram); |
808 | } |
809 | |
810 | namespace |
811 | { |
812 | |
813 | static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f); |
814 | |
815 | // ======================================================================= |
816 | // function : PushAspectFace |
817 | // purpose : |
818 | // ======================================================================= |
819 | static void PushAspectFace (const Handle(OpenGl_Context)& theCtx, |
820 | const Handle(OpenGl_ShaderProgram)& theProgram, |
821 | const OpenGl_AspectFace* theAspect) |
822 | { |
823 | theProgram->SetUniform (theCtx, |
824 | theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), |
825 | theAspect->DoTextureMap()); |
30f0ad28 |
826 | theProgram->SetUniform (theCtx, |
827 | theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), |
828 | 0 /* GL_TEXTURE0 */); |
30f0ad28 |
829 | theProgram->SetUniform (theCtx, |
830 | theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), |
831 | theAspect->DistinguishingMode()); |
832 | |
0adbd30f |
833 | OpenGl_Material aParams; |
12381341 |
834 | for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex) |
30f0ad28 |
835 | { |
12381341 |
836 | const GLint aLoc = theProgram->GetStateLocation (anIndex == 0 |
837 | ? OpenGl_OCCT_FRONT_MATERIAL |
838 | : OpenGl_OCCT_BACK_MATERIAL); |
839 | if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION) |
30f0ad28 |
840 | { |
12381341 |
841 | continue; |
30f0ad28 |
842 | } |
30f0ad28 |
843 | |
0adbd30f |
844 | aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack()); |
845 | theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(), |
846 | aParams.Packed()); |
30f0ad28 |
847 | } |
848 | } |
849 | |
850 | // ======================================================================= |
851 | // function : PushAspectLine |
852 | // purpose : |
853 | // ======================================================================= |
854 | static void PushAspectLine (const Handle(OpenGl_Context)& theCtx, |
855 | const Handle(OpenGl_ShaderProgram)& theProgram, |
856 | const OpenGl_AspectLine* theAspect) |
857 | { |
858 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff); |
859 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
860 | |
861 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
862 | theAspect->Color().rgb[1], |
863 | theAspect->Color().rgb[2], |
864 | theAspect->Color().rgb[3]); |
12381341 |
865 | OpenGl_Vec4 aParams[5]; |
866 | aParams[0] = THE_COLOR_BLACK_VEC4; |
867 | aParams[1] = THE_COLOR_BLACK_VEC4; |
868 | aParams[2] = aDiffuse; |
869 | aParams[3] = THE_COLOR_BLACK_VEC4; |
870 | aParams[4].x() = 0.0f; // shininess |
871 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
872 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
873 | 5, aParams); |
30f0ad28 |
874 | } |
875 | |
876 | // ======================================================================= |
877 | // function : PushAspectText |
878 | // purpose : |
879 | // ======================================================================= |
880 | static void PushAspectText (const Handle(OpenGl_Context)& theCtx, |
881 | const Handle(OpenGl_ShaderProgram)& theProgram, |
882 | const OpenGl_AspectText* theAspect) |
883 | { |
884 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
885 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
886 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
887 | |
888 | OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
889 | theAspect->Color().rgb[1], |
890 | theAspect->Color().rgb[2], |
891 | theAspect->Color().rgb[3]); |
892 | if (theAspect->DisplayType() == Aspect_TODT_DEKALE |
893 | || theAspect->DisplayType() == Aspect_TODT_SUBTITLE) |
894 | { |
895 | aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0], |
896 | theAspect->SubtitleColor().rgb[1], |
897 | theAspect->SubtitleColor().rgb[2], |
898 | theAspect->SubtitleColor().rgb[3]); |
899 | } |
900 | |
12381341 |
901 | OpenGl_Vec4 aParams[5]; |
902 | aParams[0] = THE_COLOR_BLACK_VEC4; |
903 | aParams[1] = THE_COLOR_BLACK_VEC4; |
904 | aParams[2] = aDiffuse; |
905 | aParams[3] = THE_COLOR_BLACK_VEC4; |
906 | aParams[4].x() = 0.0f; // shininess |
907 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
908 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
909 | 5, aParams); |
30f0ad28 |
910 | } |
911 | |
912 | // ======================================================================= |
913 | // function : PushAspectMarker |
914 | // purpose : |
915 | // ======================================================================= |
916 | static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx, |
917 | const Handle(OpenGl_ShaderProgram)& theProgram, |
918 | const OpenGl_AspectMarker* theAspect) |
919 | { |
920 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
921 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
922 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
923 | |
924 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
925 | theAspect->Color().rgb[1], |
926 | theAspect->Color().rgb[2], |
927 | theAspect->Color().rgb[3]); |
12381341 |
928 | OpenGl_Vec4 aParams[5]; |
929 | aParams[0] = THE_COLOR_BLACK_VEC4; |
930 | aParams[1] = THE_COLOR_BLACK_VEC4; |
931 | aParams[2] = aDiffuse; |
932 | aParams[3] = THE_COLOR_BLACK_VEC4; |
933 | aParams[4].x() = 0.0f; // shininess |
934 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
935 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
936 | 5, aParams); |
30f0ad28 |
937 | } |
938 | |
939 | }; // nameless namespace |
940 | |
941 | // ======================================================================= |
942 | // function : PushMaterialState |
943 | // purpose : Pushes current state of OCCT material to the program |
944 | // ======================================================================= |
945 | void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
946 | { |
947 | if (!myMaterialStates.IsBound (theProgram)) |
948 | { |
949 | return; |
950 | } |
951 | |
952 | const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram); |
953 | if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE)) |
954 | { |
955 | return; |
956 | } |
957 | |
958 | if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace)) |
959 | { |
960 | PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect())); |
961 | } |
962 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine)) |
963 | { |
964 | PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect())); |
965 | } |
966 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText)) |
967 | { |
968 | PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect())); |
969 | } |
970 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker)) |
971 | { |
972 | PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect())); |
973 | } |
974 | |
975 | theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index()); |
976 | } |
977 | |
978 | // ======================================================================= |
979 | // function : PushWorldViewState |
980 | // purpose : Pushes state of OCCT graphics parameters to the program |
981 | // ======================================================================= |
982 | void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
983 | { |
984 | PushClippingState (theProgram); |
985 | PushMaterialState (theProgram); |
986 | PushWorldViewState (theProgram); |
987 | PushModelWorldState (theProgram); |
988 | PushProjectionState (theProgram); |
989 | PushLightSourceState (theProgram); |
12381341 |
990 | } |
8625ef7e |
991 | |
992 | // ======================================================================= |
993 | // function : prepareStdProgramFont |
994 | // purpose : |
995 | // ======================================================================= |
996 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont() |
997 | { |
998 | Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); |
999 | TCollection_AsciiString aSrcVert = |
1000 | EOL"void main()" |
1001 | EOL"{" |
1002 | EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;" |
1003 | EOL"}"; |
1004 | |
1005 | TCollection_AsciiString aSrcFrag = |
1006 | EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }" |
1007 | EOL"void main()" |
1008 | EOL"{" |
1009 | EOL" vec4 aColor = occColor;" |
1010 | EOL" aColor.a *= getAlpha();" |
1011 | EOL" if (aColor.a <= 0.285) discard;" |
1012 | EOL" gl_FragColor = aColor;" |
1013 | EOL"}"; |
1014 | |
1015 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); |
1016 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); |
1017 | TCollection_AsciiString aKey; |
1018 | if (!Create (aProgramSrc, aKey, myFontProgram)) |
1019 | { |
1020 | myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1021 | return Standard_False; |
1022 | } |
1023 | return Standard_True; |
1024 | } |
1025 | |
1026 | // ======================================================================= |
1027 | // function : prepareStdProgramFlat |
1028 | // purpose : |
1029 | // ======================================================================= |
1030 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram, |
1031 | const Standard_Integer theBits) |
1032 | { |
1033 | Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); |
1034 | TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain; |
1035 | TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }"; |
1036 | TCollection_AsciiString aSrcFragMainGetColor = EOL" gl_FragColor = getColor();"; |
1037 | if ((theBits & OpenGl_PO_Point) != 0) |
1038 | { |
1039 | #if defined(GL_ES_VERSION_2_0) |
1040 | aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; |
1041 | #endif |
1042 | if ((theBits & OpenGl_PO_TextureA) != 0) |
1043 | { |
1044 | aSrcFragGetColor = |
1045 | EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }" |
1046 | EOL"vec4 getColor(void)" |
1047 | EOL"{" |
1048 | EOL" vec4 aColor = occColor;" |
1049 | EOL" aColor.a *= getAlpha();" |
1050 | EOL" return aColor;" |
1051 | EOL"}"; |
1052 | |
1053 | aSrcFragMainGetColor = |
1054 | EOL" vec4 aColor = getColor();" |
1055 | EOL" if (aColor.a <= 0.1) discard;" |
1056 | EOL" gl_FragColor = aColor;"; |
1057 | } |
1058 | else if ((theBits & OpenGl_PO_TextureRGB) != 0) |
1059 | { |
1060 | aSrcFragGetColor = |
1061 | EOL"vec4 getColor(void) { return texture2D(occActiveSampler, gl_PointCoord); }"; |
1062 | aSrcFragMainGetColor = |
1063 | EOL" vec4 aColor = getColor();" |
1064 | EOL" if (aColor.a <= 0.1) discard;" |
1065 | EOL" gl_FragColor = aColor;"; |
1066 | } |
1067 | } |
1068 | if ((theBits & OpenGl_PO_VertColor) != 0) |
1069 | { |
1070 | aSrcVertExtraOut += EOL"varying vec4 VertColor;"; |
1071 | aSrcVertExtraMain += EOL" VertColor = occVertColor;"; |
1072 | aSrcFragExtraOut += EOL"varying vec4 VertColor;"; |
1073 | aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }"; |
1074 | } |
1075 | if ((theBits & OpenGl_PO_ClipPlanes) != 0) |
1076 | { |
1077 | const char THE_POS_VARY[] = |
1078 | EOL"varying vec4 PositionWorld;" |
1079 | EOL"varying vec4 Position;"; |
1080 | |
1081 | aSrcVertExtraOut += THE_POS_VARY; |
1082 | aSrcFragExtraOut += THE_POS_VARY; |
1083 | aSrcVertExtraMain += |
1084 | EOL" PositionWorld = occModelWorldMatrix * occVertex;" |
1085 | EOL" Position = occWorldViewMatrix * PositionWorld;"; |
1086 | aSrcFragExtraMain += THE_FRAG_CLIP_PLANES; |
1087 | } |
1088 | |
1089 | aSrcVert = |
1090 | aSrcVertExtraOut |
1091 | + EOL"void main()" |
1092 | EOL"{" |
1093 | + aSrcVertExtraMain |
1094 | + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;" |
1095 | EOL"}"; |
1096 | |
1097 | aSrcFrag = |
1098 | aSrcFragExtraOut |
1099 | + aSrcFragGetColor |
1100 | + EOL"void main()" |
1101 | EOL"{" |
1102 | + aSrcFragExtraMain |
1103 | + aSrcFragMainGetColor |
1104 | + EOL"}"; |
1105 | |
1106 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); |
1107 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); |
1108 | |
1109 | TCollection_AsciiString aKey; |
1110 | if (!Create (aProgramSrc, aKey, theProgram)) |
1111 | { |
1112 | theProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1113 | return Standard_False; |
1114 | } |
1115 | return Standard_True; |
1116 | } |
1117 | |
1118 | // ======================================================================= |
1119 | // function : prepareStdProgramGouraud |
1120 | // purpose : |
1121 | // ======================================================================= |
1122 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram, |
1123 | const Standard_Integer theBits) |
1124 | { |
1125 | Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); |
1126 | TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain; |
1127 | if ((theBits & OpenGl_PO_Point) != 0) |
1128 | { |
1129 | #if defined(GL_ES_VERSION_2_0) |
1130 | aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; |
1131 | #endif |
1132 | } |
1133 | if ((theBits & OpenGl_PO_ClipPlanes) != 0) |
1134 | { |
1135 | const char THE_POS_VARY[] = |
1136 | EOL"varying vec4 PositionWorld;" |
1137 | EOL"varying vec4 Position;"; |
1138 | |
1139 | aSrcVertExtraOut += THE_POS_VARY; |
1140 | aSrcFragExtraOut += THE_POS_VARY; |
1141 | aSrcVertExtraMain += |
1142 | EOL" PositionWorld = aPositionWorld;" |
1143 | EOL" Position = aPosition;"; |
1144 | aSrcFragExtraMain += THE_FRAG_CLIP_PLANES; |
1145 | } |
1146 | |
1147 | aSrcVert = TCollection_AsciiString() |
1148 | + THE_FUNC_transformNormal |
1149 | + EOL |
1150 | + THE_FUNC_lightDef |
1151 | + THE_FUNC_pointLight |
1152 | + THE_FUNC_spotLight |
1153 | + THE_FUNC_directionalLight |
1154 | + EOL |
1155 | + THE_FUNC_computeLighting |
1156 | + EOL |
1157 | EOL"varying vec4 FrontColor;" |
1158 | EOL"varying vec4 BackColor;" |
1159 | EOL |
1160 | + aSrcVertExtraOut |
1161 | + EOL"void main()" |
1162 | EOL"{" |
1163 | EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;" |
1164 | EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;" |
1165 | EOL" vec3 aNormal = transformNormal (occNormal);" |
1166 | EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);" |
1167 | EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);" |
1168 | EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);" |
1169 | + aSrcVertExtraMain |
1170 | + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;" |
1171 | EOL"}"; |
1172 | |
1173 | aSrcFrag = TCollection_AsciiString() |
1174 | + EOL"varying vec4 FrontColor;" |
1175 | EOL"varying vec4 BackColor;" |
1176 | + aSrcFragExtraOut |
1177 | + EOL"void main()" |
1178 | EOL"{" |
1179 | + aSrcFragExtraMain |
1180 | + EOL" gl_FragColor = gl_FrontFacing ? FrontColor : BackColor;" |
1181 | EOL"}"; |
1182 | |
1183 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); |
1184 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); |
1185 | TCollection_AsciiString aKey; |
1186 | if (!Create (aProgramSrc, aKey, theProgram)) |
1187 | { |
1188 | theProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1189 | return Standard_False; |
1190 | } |
1191 | return Standard_True; |
1192 | } |
1193 | |
1194 | // ======================================================================= |
1195 | // function : prepareStdProgramPhong |
1196 | // purpose : |
1197 | // ======================================================================= |
1198 | Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram, |
1199 | const Standard_Integer theBits) |
1200 | { |
1201 | Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); |
1202 | TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraMain; |
1203 | if ((theBits & OpenGl_PO_Point) != 0) |
1204 | { |
1205 | #if defined(GL_ES_VERSION_2_0) |
1206 | aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;"; |
1207 | #endif |
1208 | } |
1209 | if ((theBits & OpenGl_PO_ClipPlanes) != 0) |
1210 | { |
1211 | aSrcFragExtraMain += THE_FRAG_CLIP_PLANES; |
1212 | } |
1213 | |
1214 | aSrcVert = TCollection_AsciiString() |
1215 | + THE_FUNC_transformNormal |
1216 | + EOL |
1217 | EOL"varying vec4 PositionWorld;" |
1218 | EOL"varying vec4 Position;" |
1219 | EOL"varying vec3 Normal;" |
1220 | EOL"varying vec3 View;" |
1221 | EOL |
1222 | + aSrcVertExtraOut |
1223 | + EOL"void main()" |
1224 | EOL"{" |
1225 | EOL" PositionWorld = occModelWorldMatrix * occVertex;" |
1226 | EOL" Position = occWorldViewMatrix * PositionWorld;" |
1227 | EOL" Normal = transformNormal (occNormal);" |
1228 | EOL" View = vec3 (0.0, 0.0, 1.0);" |
1229 | + aSrcVertExtraMain |
1230 | + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;" |
1231 | EOL"}"; |
1232 | |
1233 | aSrcFrag = TCollection_AsciiString() |
1234 | + EOL"varying vec4 PositionWorld;" |
1235 | EOL"varying vec4 Position;" |
1236 | EOL"varying vec3 Normal;" |
1237 | EOL"varying vec3 View;" |
1238 | + EOL |
1239 | + THE_FUNC_lightDef |
1240 | + THE_FUNC_pointLight |
1241 | + THE_FUNC_spotLight |
1242 | + THE_FUNC_directionalLight |
1243 | + EOL |
1244 | + THE_FUNC_computeLighting |
1245 | + EOL |
1246 | EOL"void main()" |
1247 | EOL"{" |
1248 | + aSrcFragExtraMain |
1249 | + EOL" gl_FragColor = computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing);" |
1250 | EOL"}"; |
1251 | |
1252 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); |
1253 | aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); |
1254 | TCollection_AsciiString aKey; |
1255 | if (!Create (aProgramSrc, aKey, theProgram)) |
1256 | { |
1257 | theProgram = new OpenGl_ShaderProgram(); // just mark as invalid |
1258 | return Standard_False; |
1259 | } |
1260 | return Standard_True; |
1261 | } |
1262 | |
1263 | // ======================================================================= |
1264 | // function : bindProgramWithState |
1265 | // purpose : |
1266 | // ======================================================================= |
1267 | Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram, |
1268 | const OpenGl_Element* theAspect) |
1269 | { |
1270 | if (!myContext->BindProgram (theProgram)) |
1271 | { |
1272 | return Standard_False; |
1273 | } |
1274 | theProgram->ApplyVariables (myContext); |
1275 | |
1276 | const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram); |
1277 | if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect) |
1278 | { |
1279 | UpdateMaterialStateTo (theProgram, theAspect); |
1280 | } |
1281 | |
1282 | PushState (theProgram); |
1283 | return Standard_True; |
1284 | } |