30f0ad28 |
1 | // Created on: 2013-09-26 |
2 | // Created by: Denis BOGOLEPOV |
3 | // Copyright (c) 2013 OPEN CASCADE SAS |
4 | // |
5 | // The content of this file is subject to the Open CASCADE Technology Public |
6 | // License Version 6.5 (the "License"). You may not use the content of this file |
7 | // except in compliance with the License. Please obtain a copy of the License |
8 | // at http://www.opencascade.org and read it completely before using this file. |
9 | // |
10 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
11 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
12 | // |
13 | // The Original Code and all software distributed under the License is |
14 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
15 | // Initial Developer hereby disclaims all such warranties, including without |
16 | // limitation, any warranties of merchantability, fitness for a particular |
17 | // purpose or non-infringement. Please see the License for the specific terms |
18 | // and conditions governing the rights and limitations under the License. |
19 | |
20 | #include <typeinfo> |
21 | |
22 | #include <OpenGl_AspectFace.hxx> |
23 | #include <OpenGl_AspectLine.hxx> |
24 | #include <OpenGl_AspectMarker.hxx> |
25 | #include <OpenGl_AspectText.hxx> |
26 | #include <OpenGl_Clipping.hxx> |
27 | #include <OpenGl_Context.hxx> |
28 | #include <OpenGl_ShaderManager.hxx> |
29 | #include <OpenGl_ShaderProgram.hxx> |
30 | |
31 | IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient) |
32 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient) |
33 | |
34 | // ======================================================================= |
35 | // function : OpenGl_ShaderManager |
36 | // purpose : Creates new empty shader manager |
37 | // ======================================================================= |
38 | OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext) |
39 | : myContext (theContext), |
40 | myIsPP (Standard_False) |
41 | { |
42 | // |
43 | } |
44 | |
45 | // ======================================================================= |
46 | // function : ~OpenGl_ShaderManager |
47 | // purpose : Releases resources of shader manager |
48 | // ======================================================================= |
49 | OpenGl_ShaderManager::~OpenGl_ShaderManager() |
50 | { |
51 | myProgramList.Clear(); |
52 | } |
53 | |
54 | // ======================================================================= |
55 | // function : Create |
56 | // purpose : Creates new shader program |
57 | // ======================================================================= |
392ac980 |
58 | void OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy, |
59 | TCollection_AsciiString& theShareKey, |
60 | Handle(OpenGl_ShaderProgram)& theProgram) |
30f0ad28 |
61 | { |
392ac980 |
62 | theProgram.Nullify(); |
63 | if (theProxy.IsNull()) |
30f0ad28 |
64 | { |
392ac980 |
65 | return; |
30f0ad28 |
66 | } |
392ac980 |
67 | |
68 | theShareKey = theProxy->GetId(); |
69 | if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram)) |
70 | { |
05dd08ce |
71 | if (theProgram->Share()) |
72 | { |
73 | myProgramList.Append (theProgram); |
74 | } |
392ac980 |
75 | return; |
76 | } |
77 | |
78 | theProgram = new OpenGl_ShaderProgram (theProxy); |
79 | if (!theProgram->Initialize (myContext, theProxy->ShaderObjects())) |
30f0ad28 |
80 | { |
392ac980 |
81 | theProgram->Release (myContext); |
82 | theShareKey.Clear(); |
83 | theProgram.Nullify(); |
84 | return; |
30f0ad28 |
85 | } |
30f0ad28 |
86 | |
392ac980 |
87 | myProgramList.Append (theProgram); |
88 | myContext->ShareResource (theShareKey, theProgram); |
30f0ad28 |
89 | } |
90 | |
91 | // ======================================================================= |
92 | // function : Unregister |
93 | // purpose : Removes specified shader program from the manager |
94 | // ======================================================================= |
392ac980 |
95 | void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey, |
96 | Handle(OpenGl_ShaderProgram)& theProgram) |
30f0ad28 |
97 | { |
98 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
99 | { |
100 | if (anIt.Value() == theProgram) |
101 | { |
392ac980 |
102 | if (!theProgram->UnShare()) |
103 | { |
104 | theShareKey.Clear(); |
105 | theProgram.Nullify(); |
106 | return; |
107 | } |
108 | |
30f0ad28 |
109 | myProgramList.Remove (anIt); |
392ac980 |
110 | myMaterialStates.UnBind (theProgram); |
30f0ad28 |
111 | break; |
112 | } |
113 | } |
114 | |
115 | const TCollection_AsciiString anID = theProgram->myProxy->GetId(); |
116 | if (anID.IsEmpty()) |
117 | { |
118 | myContext->DelayedRelease (theProgram); |
119 | theProgram.Nullify(); |
120 | } |
121 | else |
122 | { |
123 | theProgram.Nullify(); |
05dd08ce |
124 | myContext->ReleaseResource (anID, Standard_True); |
30f0ad28 |
125 | } |
126 | } |
127 | |
128 | // ======================================================================= |
129 | // function : ShaderPrograms |
130 | // purpose : Returns list of registered shader programs |
131 | // ======================================================================= |
132 | const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const |
133 | { |
134 | return myProgramList; |
135 | } |
136 | |
137 | // ======================================================================= |
138 | // function : Empty |
139 | // purpose : Returns true if no program objects are attached |
140 | // ======================================================================= |
141 | Standard_Boolean OpenGl_ShaderManager::IsEmpty() const |
142 | { |
143 | return myProgramList.IsEmpty(); |
144 | } |
145 | |
146 | // ======================================================================= |
147 | // function : UpdateLightSourceStateTo |
148 | // purpose : Updates state of OCCT light sources |
149 | // ======================================================================= |
150 | void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights) |
151 | { |
152 | myLightSourceState.Set (theLights); |
153 | myLightSourceState.Update(); |
154 | } |
155 | |
156 | // ======================================================================= |
157 | // function : SetProjectionState |
158 | // purpose : Sets new state of OCCT projection transform |
159 | // ======================================================================= |
160 | void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3& theProjectionMatrix) |
161 | { |
162 | myProjectionState.Set (theProjectionMatrix); |
163 | myProjectionState.Update(); |
164 | } |
165 | |
166 | // ======================================================================= |
167 | // function : SetModelWorldState |
168 | // purpose : Sets new state of OCCT model-world transform |
169 | // ======================================================================= |
170 | void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3& theModelWorldMatrix) |
171 | { |
172 | myModelWorldState.Set (theModelWorldMatrix); |
173 | myModelWorldState.Update(); |
174 | } |
175 | |
176 | // ======================================================================= |
177 | // function : SetWorldViewState |
178 | // purpose : Sets new state of OCCT world-view transform |
179 | // ======================================================================= |
180 | void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3& theWorldViewMatrix) |
181 | { |
182 | myWorldViewState.Set (theWorldViewMatrix); |
183 | myWorldViewState.Update(); |
184 | } |
185 | |
186 | // ======================================================================= |
187 | // function : RevertProjectionStateTo |
188 | // purpose : Reverts state of OCCT projection transform |
189 | // ======================================================================= |
190 | void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3& theProjectionMatrix) |
191 | { |
192 | myProjectionState.Set (theProjectionMatrix); |
193 | myProjectionState.Revert(); |
194 | } |
195 | |
196 | // ======================================================================= |
197 | // function : RevertModelWorldStateTo |
198 | // purpose : Reverts state of OCCT model-world transform |
199 | // ======================================================================= |
200 | void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3& theModelWorldMatrix) |
201 | { |
202 | myModelWorldState.Set (theModelWorldMatrix); |
203 | myModelWorldState.Revert(); |
204 | } |
205 | |
206 | // ======================================================================= |
207 | // function : RevertWorldViewStateTo |
208 | // purpose : Reverts state of OCCT world-view transform |
209 | // ======================================================================= |
210 | void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3& theWorldViewMatrix) |
211 | { |
212 | myWorldViewState.Set (theWorldViewMatrix); |
213 | myWorldViewState.Revert(); |
214 | } |
215 | |
216 | // ======================================================================= |
217 | // function : LightSourceState |
218 | // purpose : Returns current state of OCCT light sources |
219 | // ======================================================================= |
220 | const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const |
221 | { |
222 | return myLightSourceState; |
223 | } |
224 | |
225 | // ======================================================================= |
226 | // function : ProjectionState |
227 | // purpose : Returns current state of OCCT projection transform |
228 | // ======================================================================= |
229 | const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const |
230 | { |
231 | return myProjectionState; |
232 | } |
233 | |
234 | // ======================================================================= |
235 | // function : ModelWorldState |
236 | // purpose : Returns current state of OCCT model-world transform |
237 | // ======================================================================= |
238 | const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const |
239 | { |
240 | return myModelWorldState; |
241 | } |
242 | |
243 | // ======================================================================= |
244 | // function : WorldViewState |
245 | // purpose : Returns current state of OCCT world-view transform |
246 | // ======================================================================= |
247 | const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const |
248 | { |
249 | return myWorldViewState; |
250 | } |
251 | |
4fe9ad57 |
252 | //! Packed properties of light source |
253 | class OpenGl_ShaderLightParameters |
254 | { |
255 | public: |
256 | |
257 | OpenGl_Vec4 Color; |
258 | OpenGl_Vec4 Position; |
259 | OpenGl_Vec4 Direction; |
260 | OpenGl_Vec4 Parameters; |
261 | |
262 | //! Returns packed (serialized) representation of light source properties |
263 | const OpenGl_Vec4* Packed() { return reinterpret_cast<OpenGl_Vec4*> (this); } |
01eaf654 |
264 | static Standard_Integer NbOfVec4() { return 4; } |
4fe9ad57 |
265 | |
266 | }; |
267 | |
268 | //! Packed light source type information |
269 | class OpenGl_ShaderLightType |
270 | { |
271 | public: |
272 | |
273 | Standard_Integer Type; |
274 | Standard_Integer IsHeadlight; |
275 | |
276 | //! Returns packed (serialized) representation of light source type |
277 | const OpenGl_Vec2i* Packed() { return reinterpret_cast<OpenGl_Vec2i*> (this); } |
01eaf654 |
278 | static Standard_Integer NbOfVec2i() { return 1; } |
4fe9ad57 |
279 | |
280 | }; |
281 | |
30f0ad28 |
282 | // ======================================================================= |
283 | // function : PushLightSourceState |
284 | // purpose : Pushes state of OCCT light sources to the program |
285 | // ======================================================================= |
286 | void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
287 | { |
12381341 |
288 | if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE) |
289 | || !theProgram->IsValid()) |
30f0ad28 |
290 | { |
291 | return; |
292 | } |
30f0ad28 |
293 | |
01eaf654 |
294 | OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights]; |
295 | for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt) |
296 | { |
297 | aLightTypeArray[aLightIt].Type = -1; |
298 | } |
299 | |
12381341 |
300 | const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights); |
301 | if (aLightsDefNb < 1) |
302 | { |
30f0ad28 |
303 | theProgram->SetUniform (myContext, |
12381341 |
304 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
305 | 0); |
30f0ad28 |
306 | theProgram->SetUniform (myContext, |
12381341 |
307 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT), |
308 | OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
01eaf654 |
309 | theProgram->SetUniform (myContext, |
310 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), |
311 | OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(), |
312 | aLightTypeArray[0].Packed()); |
12381341 |
313 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
314 | return; |
315 | } |
30f0ad28 |
316 | |
4fe9ad57 |
317 | OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb]; |
30f0ad28 |
318 | |
12381341 |
319 | OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f); |
320 | Standard_Integer aLightsNb = 0; |
321 | for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next()) |
322 | { |
323 | const OpenGl_Light& aLight = anIter.Value(); |
324 | if (aLight.Type == Visual3d_TOLS_AMBIENT) |
30f0ad28 |
325 | { |
12381341 |
326 | anAmbient += aLight.Color; |
327 | continue; |
328 | } |
329 | else if (aLightsNb >= OpenGLMaxLights) |
330 | { |
331 | continue; |
332 | } |
30f0ad28 |
333 | |
4fe9ad57 |
334 | OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb]; |
335 | aLightType.Type = aLight.Type; |
336 | aLightType.IsHeadlight = aLight.IsHeadlight; |
30f0ad28 |
337 | |
4fe9ad57 |
338 | OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb]; |
339 | aLightParams.Color = aLight.Color; |
340 | aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL |
341 | ? -aLight.Direction |
342 | : aLight.Position; |
12381341 |
343 | if (aLight.Type == Visual3d_TOLS_SPOT) |
344 | { |
4fe9ad57 |
345 | aLightParams.Direction = aLight.Direction; |
30f0ad28 |
346 | } |
4fe9ad57 |
347 | aLightParams.Parameters = aLight.Params; |
12381341 |
348 | ++aLightsNb; |
349 | } |
30f0ad28 |
350 | |
12381341 |
351 | theProgram->SetUniform (myContext, |
352 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
353 | aLightsNb); |
354 | theProgram->SetUniform (myContext, |
355 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT), |
356 | anAmbient); |
01eaf654 |
357 | theProgram->SetUniform (myContext, |
358 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), |
359 | OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(), |
360 | aLightTypeArray[0].Packed()); |
12381341 |
361 | if (aLightsNb > 0) |
362 | { |
4fe9ad57 |
363 | theProgram->SetUniform (myContext, |
364 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS), |
365 | aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(), |
366 | aLightParamsArray[0].Packed()); |
30f0ad28 |
367 | } |
4fe9ad57 |
368 | delete[] aLightParamsArray; |
369 | delete[] aLightTypeArray; |
30f0ad28 |
370 | |
371 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
372 | } |
373 | |
374 | // ======================================================================= |
375 | // function : PushProjectionState |
376 | // purpose : Pushes state of OCCT projection transform to the program |
377 | // ======================================================================= |
378 | void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
379 | { |
380 | if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE)) |
381 | { |
382 | return; |
383 | } |
384 | |
385 | theProgram->SetUniform (myContext, |
386 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX), |
387 | myProjectionState.ProjectionMatrix()); |
388 | |
389 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE); |
390 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
391 | { |
392 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse()); |
393 | } |
394 | |
395 | theProgram->SetUniform (myContext, |
396 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE), |
397 | myProjectionState.ProjectionMatrix(), true); |
398 | |
399 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE); |
400 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
401 | { |
402 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true); |
403 | } |
404 | |
405 | theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index()); |
406 | } |
407 | |
408 | // ======================================================================= |
409 | // function : PushModelWorldState |
410 | // purpose : Pushes state of OCCT model-world transform to the program |
411 | // ======================================================================= |
412 | void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
413 | { |
414 | if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE)) |
415 | { |
416 | return; |
417 | } |
418 | |
419 | theProgram->SetUniform (myContext, |
420 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX), |
421 | myModelWorldState.ModelWorldMatrix()); |
422 | |
423 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE); |
424 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
425 | { |
426 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse()); |
427 | } |
428 | |
429 | theProgram->SetUniform (myContext, |
430 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE), |
431 | myModelWorldState.ModelWorldMatrix(), true); |
432 | |
433 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE); |
434 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
435 | { |
436 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true); |
437 | } |
438 | |
439 | theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index()); |
440 | } |
441 | |
442 | // ======================================================================= |
443 | // function : PushWorldViewState |
444 | // purpose : Pushes state of OCCT world-view transform to the program |
445 | // ======================================================================= |
446 | void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
447 | { |
448 | if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE)) |
449 | { |
450 | return; |
451 | } |
452 | |
453 | theProgram->SetUniform (myContext, |
454 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX), |
455 | myWorldViewState.WorldViewMatrix()); |
456 | |
457 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE); |
458 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
459 | { |
460 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse()); |
461 | } |
462 | |
463 | theProgram->SetUniform (myContext, |
464 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE), |
465 | myWorldViewState.WorldViewMatrix(), true); |
466 | |
467 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE); |
468 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
469 | { |
470 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true); |
471 | } |
472 | |
473 | theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index()); |
474 | } |
475 | |
476 | // ======================================================================= |
477 | // function : UpdateClippingState |
478 | // purpose : Updates state of OCCT clipping planes |
479 | // ======================================================================= |
480 | void OpenGl_ShaderManager::UpdateClippingState() |
481 | { |
482 | myClippingState.Update(); |
483 | } |
484 | |
485 | // ======================================================================= |
486 | // function : RevertClippingState |
487 | // purpose : Reverts state of OCCT clipping planes |
488 | // ======================================================================= |
489 | void OpenGl_ShaderManager::RevertClippingState() |
490 | { |
491 | myClippingState.Revert(); |
492 | } |
493 | |
494 | // ======================================================================= |
495 | // function : PushClippingState |
496 | // purpose : Pushes state of OCCT clipping planes to the program |
497 | // ======================================================================= |
498 | void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
499 | { |
500 | if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE)) |
501 | { |
502 | return; |
503 | } |
504 | |
12381341 |
505 | theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index()); |
506 | const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS); |
507 | const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES); |
508 | if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION |
509 | && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION) |
510 | { |
511 | return; |
512 | } |
513 | |
514 | GLuint aPlanesNb = 0; |
51b10cd4 |
515 | for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); |
12381341 |
516 | anIter.More(); anIter.Next()) |
30f0ad28 |
517 | { |
518 | const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); |
519 | if (!myContext->Clipping().IsEnabled (aPlane)) |
520 | { |
521 | continue; |
522 | } |
523 | |
12381341 |
524 | ++aPlanesNb; |
525 | } |
526 | if (aPlanesNb < 1) |
527 | { |
528 | return; |
529 | } |
530 | |
531 | OpenGl_Vec4* anEquations = new OpenGl_Vec4[aPlanesNb]; |
532 | GLint* aSpaces = new GLint [aPlanesNb]; |
533 | GLuint aPlaneId = 0; |
51b10cd4 |
534 | for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); |
12381341 |
535 | anIter.More(); anIter.Next()) |
536 | { |
537 | const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); |
538 | if (!myContext->Clipping().IsEnabled (aPlane)) |
30f0ad28 |
539 | { |
12381341 |
540 | continue; |
30f0ad28 |
541 | } |
542 | |
12381341 |
543 | const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation(); |
544 | anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(), |
545 | (float) anEquation.y(), |
546 | (float) anEquation.z(), |
547 | (float) anEquation.w()); |
548 | aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane); |
549 | ++aPlaneId; |
30f0ad28 |
550 | } |
4fe9ad57 |
551 | theProgram->SetUniform (myContext, aLocEquations, aPlanesNb, anEquations[0].GetData()); |
552 | theProgram->SetUniform (myContext, aLocSpaces, aPlanesNb, aSpaces); |
553 | |
12381341 |
554 | delete[] anEquations; |
555 | delete[] aSpaces; |
30f0ad28 |
556 | } |
557 | |
558 | // ======================================================================= |
559 | // function : UpdateMaterialStateTo |
560 | // purpose : Updates state of OCCT material for specified program |
561 | // ======================================================================= |
562 | void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram, |
563 | const OpenGl_Element* theAspect) |
564 | { |
565 | if (myMaterialStates.IsBound (theProgram)) |
566 | { |
567 | myMaterialStates.ChangeFind (theProgram).Set (theAspect); |
568 | } |
569 | else |
570 | { |
571 | myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect)); |
572 | } |
573 | |
574 | myMaterialStates.ChangeFind (theProgram).Update(); |
575 | } |
576 | |
577 | // ======================================================================= |
578 | // function : ResetMaterialStates |
579 | // purpose : Resets state of OCCT material for all programs |
580 | // ======================================================================= |
581 | void OpenGl_ShaderManager::ResetMaterialStates() |
582 | { |
583 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
584 | { |
585 | anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0); |
586 | } |
587 | } |
588 | |
589 | // ======================================================================= |
590 | // function : MaterialState |
591 | // purpose : Returns state of OCCT material for specified program |
592 | // ======================================================================= |
593 | const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
594 | { |
595 | if (!myMaterialStates.IsBound (theProgram)) |
596 | return NULL; |
597 | |
598 | return &myMaterialStates.Find (theProgram); |
599 | } |
600 | |
601 | namespace |
602 | { |
603 | |
604 | static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f); |
605 | |
606 | // ======================================================================= |
607 | // function : PushAspectFace |
608 | // purpose : |
609 | // ======================================================================= |
610 | static void PushAspectFace (const Handle(OpenGl_Context)& theCtx, |
611 | const Handle(OpenGl_ShaderProgram)& theProgram, |
612 | const OpenGl_AspectFace* theAspect) |
613 | { |
614 | theProgram->SetUniform (theCtx, |
615 | theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), |
616 | theAspect->DoTextureMap()); |
30f0ad28 |
617 | theProgram->SetUniform (theCtx, |
618 | theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), |
619 | 0 /* GL_TEXTURE0 */); |
30f0ad28 |
620 | theProgram->SetUniform (theCtx, |
621 | theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), |
622 | theAspect->DistinguishingMode()); |
623 | |
64c759f8 |
624 | const float aDefSpecCol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; |
12381341 |
625 | OpenGl_Vec4 aParams[5]; |
626 | for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex) |
30f0ad28 |
627 | { |
12381341 |
628 | const GLint aLoc = theProgram->GetStateLocation (anIndex == 0 |
629 | ? OpenGl_OCCT_FRONT_MATERIAL |
630 | : OpenGl_OCCT_BACK_MATERIAL); |
631 | if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION) |
30f0ad28 |
632 | { |
12381341 |
633 | continue; |
30f0ad28 |
634 | } |
30f0ad28 |
635 | |
12381341 |
636 | const OPENGL_SURF_PROP& aProps = (anIndex == 0) ? theAspect->IntFront() : theAspect->IntBack(); |
64c759f8 |
637 | const float* aSrcEms = aProps.isphysic ? aProps.emscol.rgb : aProps.matcol.rgb; |
638 | const OpenGl_Vec4 anEmission (aSrcEms[0] * aProps.emsv, |
639 | aSrcEms[1] * aProps.emsv, |
640 | aSrcEms[2] * aProps.emsv, |
641 | 1.0f); |
642 | const float* aSrcAmb = aProps.isphysic ? aProps.ambcol.rgb : aProps.matcol.rgb; |
643 | const OpenGl_Vec4 anAmbient (aSrcAmb[0] * aProps.amb, |
644 | aSrcAmb[1] * aProps.amb, |
645 | aSrcAmb[2] * aProps.amb, |
646 | 1.0f); |
647 | const float* aSrcDif = aProps.isphysic ? aProps.difcol.rgb : aProps.matcol.rgb; |
648 | const OpenGl_Vec4 aDiffuse (aSrcDif[0] * aProps.diff, |
649 | aSrcDif[1] * aProps.diff, |
650 | aSrcDif[2] * aProps.diff, |
651 | 1.0f); |
652 | const float* aSrcSpe = aProps.isphysic ? aProps.speccol.rgb : aDefSpecCol; |
653 | const OpenGl_Vec4 aSpecular (aSrcSpe[0] * aProps.spec, |
654 | aSrcSpe[1] * aProps.spec, |
655 | aSrcSpe[2] * aProps.spec, |
656 | 1.0f); |
657 | |
12381341 |
658 | aParams[0] = anEmission; |
659 | aParams[1] = anAmbient; |
660 | aParams[2] = aDiffuse; |
661 | aParams[3] = aSpecular; |
662 | aParams[4].x() = aProps.shine; |
663 | aParams[4].y() = aProps.trans; |
4fe9ad57 |
664 | theProgram->SetUniform (theCtx, aLoc, 5, aParams); |
30f0ad28 |
665 | } |
666 | } |
667 | |
668 | // ======================================================================= |
669 | // function : PushAspectLine |
670 | // purpose : |
671 | // ======================================================================= |
672 | static void PushAspectLine (const Handle(OpenGl_Context)& theCtx, |
673 | const Handle(OpenGl_ShaderProgram)& theProgram, |
674 | const OpenGl_AspectLine* theAspect) |
675 | { |
676 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff); |
677 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
678 | |
679 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
680 | theAspect->Color().rgb[1], |
681 | theAspect->Color().rgb[2], |
682 | theAspect->Color().rgb[3]); |
12381341 |
683 | OpenGl_Vec4 aParams[5]; |
684 | aParams[0] = THE_COLOR_BLACK_VEC4; |
685 | aParams[1] = THE_COLOR_BLACK_VEC4; |
686 | aParams[2] = aDiffuse; |
687 | aParams[3] = THE_COLOR_BLACK_VEC4; |
688 | aParams[4].x() = 0.0f; // shininess |
689 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
690 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
691 | 5, aParams); |
30f0ad28 |
692 | } |
693 | |
694 | // ======================================================================= |
695 | // function : PushAspectText |
696 | // purpose : |
697 | // ======================================================================= |
698 | static void PushAspectText (const Handle(OpenGl_Context)& theCtx, |
699 | const Handle(OpenGl_ShaderProgram)& theProgram, |
700 | const OpenGl_AspectText* theAspect) |
701 | { |
702 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
703 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
704 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
705 | |
706 | OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
707 | theAspect->Color().rgb[1], |
708 | theAspect->Color().rgb[2], |
709 | theAspect->Color().rgb[3]); |
710 | if (theAspect->DisplayType() == Aspect_TODT_DEKALE |
711 | || theAspect->DisplayType() == Aspect_TODT_SUBTITLE) |
712 | { |
713 | aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0], |
714 | theAspect->SubtitleColor().rgb[1], |
715 | theAspect->SubtitleColor().rgb[2], |
716 | theAspect->SubtitleColor().rgb[3]); |
717 | } |
718 | |
12381341 |
719 | OpenGl_Vec4 aParams[5]; |
720 | aParams[0] = THE_COLOR_BLACK_VEC4; |
721 | aParams[1] = THE_COLOR_BLACK_VEC4; |
722 | aParams[2] = aDiffuse; |
723 | aParams[3] = THE_COLOR_BLACK_VEC4; |
724 | aParams[4].x() = 0.0f; // shininess |
725 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
726 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
727 | 5, aParams); |
30f0ad28 |
728 | } |
729 | |
730 | // ======================================================================= |
731 | // function : PushAspectMarker |
732 | // purpose : |
733 | // ======================================================================= |
734 | static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx, |
735 | const Handle(OpenGl_ShaderProgram)& theProgram, |
736 | const OpenGl_AspectMarker* theAspect) |
737 | { |
738 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
739 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
740 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
741 | |
742 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
743 | theAspect->Color().rgb[1], |
744 | theAspect->Color().rgb[2], |
745 | theAspect->Color().rgb[3]); |
12381341 |
746 | OpenGl_Vec4 aParams[5]; |
747 | aParams[0] = THE_COLOR_BLACK_VEC4; |
748 | aParams[1] = THE_COLOR_BLACK_VEC4; |
749 | aParams[2] = aDiffuse; |
750 | aParams[3] = THE_COLOR_BLACK_VEC4; |
751 | aParams[4].x() = 0.0f; // shininess |
752 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
753 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
754 | 5, aParams); |
30f0ad28 |
755 | } |
756 | |
757 | }; // nameless namespace |
758 | |
759 | // ======================================================================= |
760 | // function : PushMaterialState |
761 | // purpose : Pushes current state of OCCT material to the program |
762 | // ======================================================================= |
763 | void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
764 | { |
765 | if (!myMaterialStates.IsBound (theProgram)) |
766 | { |
767 | return; |
768 | } |
769 | |
770 | const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram); |
771 | if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE)) |
772 | { |
773 | return; |
774 | } |
775 | |
776 | if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace)) |
777 | { |
778 | PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect())); |
779 | } |
780 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine)) |
781 | { |
782 | PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect())); |
783 | } |
784 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText)) |
785 | { |
786 | PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect())); |
787 | } |
788 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker)) |
789 | { |
790 | PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect())); |
791 | } |
792 | |
793 | theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index()); |
794 | } |
795 | |
796 | // ======================================================================= |
797 | // function : PushWorldViewState |
798 | // purpose : Pushes state of OCCT graphics parameters to the program |
799 | // ======================================================================= |
800 | void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
801 | { |
802 | PushClippingState (theProgram); |
803 | PushMaterialState (theProgram); |
804 | PushWorldViewState (theProgram); |
805 | PushModelWorldState (theProgram); |
806 | PushProjectionState (theProgram); |
807 | PushLightSourceState (theProgram); |
12381341 |
808 | } |