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); } |
264 | static Standard_Size NbOfVec4() { return 4; } |
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); } |
278 | static Standard_Size NbOfVec2i() { return 1; } |
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 | |
12381341 |
294 | const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights); |
295 | if (aLightsDefNb < 1) |
296 | { |
30f0ad28 |
297 | theProgram->SetUniform (myContext, |
12381341 |
298 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
299 | 0); |
30f0ad28 |
300 | theProgram->SetUniform (myContext, |
12381341 |
301 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT), |
302 | OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
303 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
304 | return; |
305 | } |
30f0ad28 |
306 | |
4fe9ad57 |
307 | OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb]; |
308 | OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[aLightsDefNb]; |
30f0ad28 |
309 | |
12381341 |
310 | OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f); |
311 | Standard_Integer aLightsNb = 0; |
312 | for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next()) |
313 | { |
314 | const OpenGl_Light& aLight = anIter.Value(); |
315 | if (aLight.Type == Visual3d_TOLS_AMBIENT) |
30f0ad28 |
316 | { |
12381341 |
317 | anAmbient += aLight.Color; |
318 | continue; |
319 | } |
320 | else if (aLightsNb >= OpenGLMaxLights) |
321 | { |
322 | continue; |
323 | } |
30f0ad28 |
324 | |
4fe9ad57 |
325 | OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb]; |
326 | aLightType.Type = aLight.Type; |
327 | aLightType.IsHeadlight = aLight.IsHeadlight; |
30f0ad28 |
328 | |
4fe9ad57 |
329 | OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb]; |
330 | aLightParams.Color = aLight.Color; |
331 | aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL |
332 | ? -aLight.Direction |
333 | : aLight.Position; |
12381341 |
334 | if (aLight.Type == Visual3d_TOLS_SPOT) |
335 | { |
4fe9ad57 |
336 | aLightParams.Direction = aLight.Direction; |
30f0ad28 |
337 | } |
4fe9ad57 |
338 | aLightParams.Parameters = aLight.Params; |
12381341 |
339 | ++aLightsNb; |
340 | } |
30f0ad28 |
341 | |
12381341 |
342 | theProgram->SetUniform (myContext, |
343 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT), |
344 | aLightsNb); |
345 | theProgram->SetUniform (myContext, |
346 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT), |
347 | anAmbient); |
348 | if (aLightsNb > 0) |
349 | { |
4fe9ad57 |
350 | theProgram->SetUniform (myContext, |
351 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), |
352 | aLightsNb * OpenGl_ShaderLightType::NbOfVec2i(), |
353 | aLightTypeArray[0].Packed()); |
354 | theProgram->SetUniform (myContext, |
355 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS), |
356 | aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(), |
357 | aLightParamsArray[0].Packed()); |
30f0ad28 |
358 | } |
4fe9ad57 |
359 | delete[] aLightParamsArray; |
360 | delete[] aLightTypeArray; |
30f0ad28 |
361 | |
362 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
363 | } |
364 | |
365 | // ======================================================================= |
366 | // function : PushProjectionState |
367 | // purpose : Pushes state of OCCT projection transform to the program |
368 | // ======================================================================= |
369 | void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
370 | { |
371 | if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE)) |
372 | { |
373 | return; |
374 | } |
375 | |
376 | theProgram->SetUniform (myContext, |
377 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX), |
378 | myProjectionState.ProjectionMatrix()); |
379 | |
380 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE); |
381 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
382 | { |
383 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse()); |
384 | } |
385 | |
386 | theProgram->SetUniform (myContext, |
387 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE), |
388 | myProjectionState.ProjectionMatrix(), true); |
389 | |
390 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE); |
391 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
392 | { |
393 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true); |
394 | } |
395 | |
396 | theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index()); |
397 | } |
398 | |
399 | // ======================================================================= |
400 | // function : PushModelWorldState |
401 | // purpose : Pushes state of OCCT model-world transform to the program |
402 | // ======================================================================= |
403 | void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
404 | { |
405 | if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE)) |
406 | { |
407 | return; |
408 | } |
409 | |
410 | theProgram->SetUniform (myContext, |
411 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX), |
412 | myModelWorldState.ModelWorldMatrix()); |
413 | |
414 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE); |
415 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
416 | { |
417 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse()); |
418 | } |
419 | |
420 | theProgram->SetUniform (myContext, |
421 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE), |
422 | myModelWorldState.ModelWorldMatrix(), true); |
423 | |
424 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE); |
425 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
426 | { |
427 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true); |
428 | } |
429 | |
430 | theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index()); |
431 | } |
432 | |
433 | // ======================================================================= |
434 | // function : PushWorldViewState |
435 | // purpose : Pushes state of OCCT world-view transform to the program |
436 | // ======================================================================= |
437 | void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
438 | { |
439 | if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE)) |
440 | { |
441 | return; |
442 | } |
443 | |
444 | theProgram->SetUniform (myContext, |
445 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX), |
446 | myWorldViewState.WorldViewMatrix()); |
447 | |
448 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE); |
449 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
450 | { |
451 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse()); |
452 | } |
453 | |
454 | theProgram->SetUniform (myContext, |
455 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE), |
456 | myWorldViewState.WorldViewMatrix(), true); |
457 | |
458 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE); |
459 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
460 | { |
461 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true); |
462 | } |
463 | |
464 | theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index()); |
465 | } |
466 | |
467 | // ======================================================================= |
468 | // function : UpdateClippingState |
469 | // purpose : Updates state of OCCT clipping planes |
470 | // ======================================================================= |
471 | void OpenGl_ShaderManager::UpdateClippingState() |
472 | { |
473 | myClippingState.Update(); |
474 | } |
475 | |
476 | // ======================================================================= |
477 | // function : RevertClippingState |
478 | // purpose : Reverts state of OCCT clipping planes |
479 | // ======================================================================= |
480 | void OpenGl_ShaderManager::RevertClippingState() |
481 | { |
482 | myClippingState.Revert(); |
483 | } |
484 | |
485 | // ======================================================================= |
486 | // function : PushClippingState |
487 | // purpose : Pushes state of OCCT clipping planes to the program |
488 | // ======================================================================= |
489 | void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
490 | { |
491 | if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE)) |
492 | { |
493 | return; |
494 | } |
495 | |
12381341 |
496 | theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index()); |
497 | const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS); |
498 | const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES); |
499 | if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION |
500 | && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION) |
501 | { |
502 | return; |
503 | } |
504 | |
505 | GLuint aPlanesNb = 0; |
506 | for (Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); |
507 | anIter.More(); anIter.Next()) |
30f0ad28 |
508 | { |
509 | const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); |
510 | if (!myContext->Clipping().IsEnabled (aPlane)) |
511 | { |
512 | continue; |
513 | } |
514 | |
12381341 |
515 | ++aPlanesNb; |
516 | } |
517 | if (aPlanesNb < 1) |
518 | { |
519 | return; |
520 | } |
521 | |
522 | OpenGl_Vec4* anEquations = new OpenGl_Vec4[aPlanesNb]; |
523 | GLint* aSpaces = new GLint [aPlanesNb]; |
524 | GLuint aPlaneId = 0; |
525 | for (Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); |
526 | anIter.More(); anIter.Next()) |
527 | { |
528 | const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); |
529 | if (!myContext->Clipping().IsEnabled (aPlane)) |
30f0ad28 |
530 | { |
12381341 |
531 | continue; |
30f0ad28 |
532 | } |
533 | |
12381341 |
534 | const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation(); |
535 | anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(), |
536 | (float) anEquation.y(), |
537 | (float) anEquation.z(), |
538 | (float) anEquation.w()); |
539 | aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane); |
540 | ++aPlaneId; |
30f0ad28 |
541 | } |
4fe9ad57 |
542 | theProgram->SetUniform (myContext, aLocEquations, aPlanesNb, anEquations[0].GetData()); |
543 | theProgram->SetUniform (myContext, aLocSpaces, aPlanesNb, aSpaces); |
544 | |
12381341 |
545 | delete[] anEquations; |
546 | delete[] aSpaces; |
30f0ad28 |
547 | } |
548 | |
549 | // ======================================================================= |
550 | // function : UpdateMaterialStateTo |
551 | // purpose : Updates state of OCCT material for specified program |
552 | // ======================================================================= |
553 | void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram, |
554 | const OpenGl_Element* theAspect) |
555 | { |
556 | if (myMaterialStates.IsBound (theProgram)) |
557 | { |
558 | myMaterialStates.ChangeFind (theProgram).Set (theAspect); |
559 | } |
560 | else |
561 | { |
562 | myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect)); |
563 | } |
564 | |
565 | myMaterialStates.ChangeFind (theProgram).Update(); |
566 | } |
567 | |
568 | // ======================================================================= |
569 | // function : ResetMaterialStates |
570 | // purpose : Resets state of OCCT material for all programs |
571 | // ======================================================================= |
572 | void OpenGl_ShaderManager::ResetMaterialStates() |
573 | { |
574 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
575 | { |
576 | anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0); |
577 | } |
578 | } |
579 | |
580 | // ======================================================================= |
581 | // function : MaterialState |
582 | // purpose : Returns state of OCCT material for specified program |
583 | // ======================================================================= |
584 | const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
585 | { |
586 | if (!myMaterialStates.IsBound (theProgram)) |
587 | return NULL; |
588 | |
589 | return &myMaterialStates.Find (theProgram); |
590 | } |
591 | |
592 | namespace |
593 | { |
594 | |
595 | static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f); |
596 | |
597 | // ======================================================================= |
598 | // function : PushAspectFace |
599 | // purpose : |
600 | // ======================================================================= |
601 | static void PushAspectFace (const Handle(OpenGl_Context)& theCtx, |
602 | const Handle(OpenGl_ShaderProgram)& theProgram, |
603 | const OpenGl_AspectFace* theAspect) |
604 | { |
605 | theProgram->SetUniform (theCtx, |
606 | theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), |
607 | theAspect->DoTextureMap()); |
30f0ad28 |
608 | theProgram->SetUniform (theCtx, |
609 | theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), |
610 | 0 /* GL_TEXTURE0 */); |
30f0ad28 |
611 | theProgram->SetUniform (theCtx, |
612 | theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), |
613 | theAspect->DistinguishingMode()); |
614 | |
64c759f8 |
615 | const float aDefSpecCol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; |
12381341 |
616 | OpenGl_Vec4 aParams[5]; |
617 | for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex) |
30f0ad28 |
618 | { |
12381341 |
619 | const GLint aLoc = theProgram->GetStateLocation (anIndex == 0 |
620 | ? OpenGl_OCCT_FRONT_MATERIAL |
621 | : OpenGl_OCCT_BACK_MATERIAL); |
622 | if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION) |
30f0ad28 |
623 | { |
12381341 |
624 | continue; |
30f0ad28 |
625 | } |
30f0ad28 |
626 | |
12381341 |
627 | const OPENGL_SURF_PROP& aProps = (anIndex == 0) ? theAspect->IntFront() : theAspect->IntBack(); |
64c759f8 |
628 | const float* aSrcEms = aProps.isphysic ? aProps.emscol.rgb : aProps.matcol.rgb; |
629 | const OpenGl_Vec4 anEmission (aSrcEms[0] * aProps.emsv, |
630 | aSrcEms[1] * aProps.emsv, |
631 | aSrcEms[2] * aProps.emsv, |
632 | 1.0f); |
633 | const float* aSrcAmb = aProps.isphysic ? aProps.ambcol.rgb : aProps.matcol.rgb; |
634 | const OpenGl_Vec4 anAmbient (aSrcAmb[0] * aProps.amb, |
635 | aSrcAmb[1] * aProps.amb, |
636 | aSrcAmb[2] * aProps.amb, |
637 | 1.0f); |
638 | const float* aSrcDif = aProps.isphysic ? aProps.difcol.rgb : aProps.matcol.rgb; |
639 | const OpenGl_Vec4 aDiffuse (aSrcDif[0] * aProps.diff, |
640 | aSrcDif[1] * aProps.diff, |
641 | aSrcDif[2] * aProps.diff, |
642 | 1.0f); |
643 | const float* aSrcSpe = aProps.isphysic ? aProps.speccol.rgb : aDefSpecCol; |
644 | const OpenGl_Vec4 aSpecular (aSrcSpe[0] * aProps.spec, |
645 | aSrcSpe[1] * aProps.spec, |
646 | aSrcSpe[2] * aProps.spec, |
647 | 1.0f); |
648 | |
12381341 |
649 | aParams[0] = anEmission; |
650 | aParams[1] = anAmbient; |
651 | aParams[2] = aDiffuse; |
652 | aParams[3] = aSpecular; |
653 | aParams[4].x() = aProps.shine; |
654 | aParams[4].y() = aProps.trans; |
4fe9ad57 |
655 | theProgram->SetUniform (theCtx, aLoc, 5, aParams); |
30f0ad28 |
656 | } |
657 | } |
658 | |
659 | // ======================================================================= |
660 | // function : PushAspectLine |
661 | // purpose : |
662 | // ======================================================================= |
663 | static void PushAspectLine (const Handle(OpenGl_Context)& theCtx, |
664 | const Handle(OpenGl_ShaderProgram)& theProgram, |
665 | const OpenGl_AspectLine* theAspect) |
666 | { |
667 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff); |
668 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
669 | |
670 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
671 | theAspect->Color().rgb[1], |
672 | theAspect->Color().rgb[2], |
673 | theAspect->Color().rgb[3]); |
12381341 |
674 | OpenGl_Vec4 aParams[5]; |
675 | aParams[0] = THE_COLOR_BLACK_VEC4; |
676 | aParams[1] = THE_COLOR_BLACK_VEC4; |
677 | aParams[2] = aDiffuse; |
678 | aParams[3] = THE_COLOR_BLACK_VEC4; |
679 | aParams[4].x() = 0.0f; // shininess |
680 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
681 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
682 | 5, aParams); |
30f0ad28 |
683 | } |
684 | |
685 | // ======================================================================= |
686 | // function : PushAspectText |
687 | // purpose : |
688 | // ======================================================================= |
689 | static void PushAspectText (const Handle(OpenGl_Context)& theCtx, |
690 | const Handle(OpenGl_ShaderProgram)& theProgram, |
691 | const OpenGl_AspectText* theAspect) |
692 | { |
693 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
694 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
695 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
696 | |
697 | OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
698 | theAspect->Color().rgb[1], |
699 | theAspect->Color().rgb[2], |
700 | theAspect->Color().rgb[3]); |
701 | if (theAspect->DisplayType() == Aspect_TODT_DEKALE |
702 | || theAspect->DisplayType() == Aspect_TODT_SUBTITLE) |
703 | { |
704 | aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0], |
705 | theAspect->SubtitleColor().rgb[1], |
706 | theAspect->SubtitleColor().rgb[2], |
707 | theAspect->SubtitleColor().rgb[3]); |
708 | } |
709 | |
12381341 |
710 | OpenGl_Vec4 aParams[5]; |
711 | aParams[0] = THE_COLOR_BLACK_VEC4; |
712 | aParams[1] = THE_COLOR_BLACK_VEC4; |
713 | aParams[2] = aDiffuse; |
714 | aParams[3] = THE_COLOR_BLACK_VEC4; |
715 | aParams[4].x() = 0.0f; // shininess |
716 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
717 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
718 | 5, aParams); |
30f0ad28 |
719 | } |
720 | |
721 | // ======================================================================= |
722 | // function : PushAspectMarker |
723 | // purpose : |
724 | // ======================================================================= |
725 | static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx, |
726 | const Handle(OpenGl_ShaderProgram)& theProgram, |
727 | const OpenGl_AspectMarker* theAspect) |
728 | { |
729 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
730 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
731 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
732 | |
733 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
734 | theAspect->Color().rgb[1], |
735 | theAspect->Color().rgb[2], |
736 | theAspect->Color().rgb[3]); |
12381341 |
737 | OpenGl_Vec4 aParams[5]; |
738 | aParams[0] = THE_COLOR_BLACK_VEC4; |
739 | aParams[1] = THE_COLOR_BLACK_VEC4; |
740 | aParams[2] = aDiffuse; |
741 | aParams[3] = THE_COLOR_BLACK_VEC4; |
742 | aParams[4].x() = 0.0f; // shininess |
743 | aParams[4].y() = 0.0f; // transparency |
4fe9ad57 |
744 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), |
745 | 5, aParams); |
30f0ad28 |
746 | } |
747 | |
748 | }; // nameless namespace |
749 | |
750 | // ======================================================================= |
751 | // function : PushMaterialState |
752 | // purpose : Pushes current state of OCCT material to the program |
753 | // ======================================================================= |
754 | void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
755 | { |
756 | if (!myMaterialStates.IsBound (theProgram)) |
757 | { |
758 | return; |
759 | } |
760 | |
761 | const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram); |
762 | if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE)) |
763 | { |
764 | return; |
765 | } |
766 | |
767 | if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace)) |
768 | { |
769 | PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect())); |
770 | } |
771 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine)) |
772 | { |
773 | PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect())); |
774 | } |
775 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText)) |
776 | { |
777 | PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect())); |
778 | } |
779 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker)) |
780 | { |
781 | PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect())); |
782 | } |
783 | |
784 | theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index()); |
785 | } |
786 | |
787 | // ======================================================================= |
788 | // function : PushWorldViewState |
789 | // purpose : Pushes state of OCCT graphics parameters to the program |
790 | // ======================================================================= |
791 | void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
792 | { |
793 | PushClippingState (theProgram); |
794 | PushMaterialState (theProgram); |
795 | PushWorldViewState (theProgram); |
796 | PushModelWorldState (theProgram); |
797 | PushProjectionState (theProgram); |
798 | PushLightSourceState (theProgram); |
12381341 |
799 | } |