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 | { |
71 | theProgram->Share(); |
72 | return; |
73 | } |
74 | |
75 | theProgram = new OpenGl_ShaderProgram (theProxy); |
76 | if (!theProgram->Initialize (myContext, theProxy->ShaderObjects())) |
30f0ad28 |
77 | { |
392ac980 |
78 | theProgram->Release (myContext); |
79 | theShareKey.Clear(); |
80 | theProgram.Nullify(); |
81 | return; |
30f0ad28 |
82 | } |
30f0ad28 |
83 | |
392ac980 |
84 | myProgramList.Append (theProgram); |
85 | myContext->ShareResource (theShareKey, theProgram); |
30f0ad28 |
86 | } |
87 | |
88 | // ======================================================================= |
89 | // function : Unregister |
90 | // purpose : Removes specified shader program from the manager |
91 | // ======================================================================= |
392ac980 |
92 | void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey, |
93 | Handle(OpenGl_ShaderProgram)& theProgram) |
30f0ad28 |
94 | { |
95 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
96 | { |
97 | if (anIt.Value() == theProgram) |
98 | { |
392ac980 |
99 | if (!theProgram->UnShare()) |
100 | { |
101 | theShareKey.Clear(); |
102 | theProgram.Nullify(); |
103 | return; |
104 | } |
105 | |
30f0ad28 |
106 | myProgramList.Remove (anIt); |
392ac980 |
107 | myMaterialStates.UnBind (theProgram); |
30f0ad28 |
108 | break; |
109 | } |
110 | } |
111 | |
112 | const TCollection_AsciiString anID = theProgram->myProxy->GetId(); |
113 | if (anID.IsEmpty()) |
114 | { |
115 | myContext->DelayedRelease (theProgram); |
116 | theProgram.Nullify(); |
117 | } |
118 | else |
119 | { |
120 | theProgram.Nullify(); |
121 | myContext->ReleaseResource (anID); |
122 | } |
123 | } |
124 | |
125 | // ======================================================================= |
126 | // function : ShaderPrograms |
127 | // purpose : Returns list of registered shader programs |
128 | // ======================================================================= |
129 | const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const |
130 | { |
131 | return myProgramList; |
132 | } |
133 | |
134 | // ======================================================================= |
135 | // function : Empty |
136 | // purpose : Returns true if no program objects are attached |
137 | // ======================================================================= |
138 | Standard_Boolean OpenGl_ShaderManager::IsEmpty() const |
139 | { |
140 | return myProgramList.IsEmpty(); |
141 | } |
142 | |
143 | // ======================================================================= |
144 | // function : UpdateLightSourceStateTo |
145 | // purpose : Updates state of OCCT light sources |
146 | // ======================================================================= |
147 | void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights) |
148 | { |
149 | myLightSourceState.Set (theLights); |
150 | myLightSourceState.Update(); |
151 | } |
152 | |
153 | // ======================================================================= |
154 | // function : SetProjectionState |
155 | // purpose : Sets new state of OCCT projection transform |
156 | // ======================================================================= |
157 | void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3& theProjectionMatrix) |
158 | { |
159 | myProjectionState.Set (theProjectionMatrix); |
160 | myProjectionState.Update(); |
161 | } |
162 | |
163 | // ======================================================================= |
164 | // function : SetModelWorldState |
165 | // purpose : Sets new state of OCCT model-world transform |
166 | // ======================================================================= |
167 | void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3& theModelWorldMatrix) |
168 | { |
169 | myModelWorldState.Set (theModelWorldMatrix); |
170 | myModelWorldState.Update(); |
171 | } |
172 | |
173 | // ======================================================================= |
174 | // function : SetWorldViewState |
175 | // purpose : Sets new state of OCCT world-view transform |
176 | // ======================================================================= |
177 | void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3& theWorldViewMatrix) |
178 | { |
179 | myWorldViewState.Set (theWorldViewMatrix); |
180 | myWorldViewState.Update(); |
181 | } |
182 | |
183 | // ======================================================================= |
184 | // function : RevertProjectionStateTo |
185 | // purpose : Reverts state of OCCT projection transform |
186 | // ======================================================================= |
187 | void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3& theProjectionMatrix) |
188 | { |
189 | myProjectionState.Set (theProjectionMatrix); |
190 | myProjectionState.Revert(); |
191 | } |
192 | |
193 | // ======================================================================= |
194 | // function : RevertModelWorldStateTo |
195 | // purpose : Reverts state of OCCT model-world transform |
196 | // ======================================================================= |
197 | void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3& theModelWorldMatrix) |
198 | { |
199 | myModelWorldState.Set (theModelWorldMatrix); |
200 | myModelWorldState.Revert(); |
201 | } |
202 | |
203 | // ======================================================================= |
204 | // function : RevertWorldViewStateTo |
205 | // purpose : Reverts state of OCCT world-view transform |
206 | // ======================================================================= |
207 | void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3& theWorldViewMatrix) |
208 | { |
209 | myWorldViewState.Set (theWorldViewMatrix); |
210 | myWorldViewState.Revert(); |
211 | } |
212 | |
213 | // ======================================================================= |
214 | // function : LightSourceState |
215 | // purpose : Returns current state of OCCT light sources |
216 | // ======================================================================= |
217 | const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const |
218 | { |
219 | return myLightSourceState; |
220 | } |
221 | |
222 | // ======================================================================= |
223 | // function : ProjectionState |
224 | // purpose : Returns current state of OCCT projection transform |
225 | // ======================================================================= |
226 | const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const |
227 | { |
228 | return myProjectionState; |
229 | } |
230 | |
231 | // ======================================================================= |
232 | // function : ModelWorldState |
233 | // purpose : Returns current state of OCCT model-world transform |
234 | // ======================================================================= |
235 | const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const |
236 | { |
237 | return myModelWorldState; |
238 | } |
239 | |
240 | // ======================================================================= |
241 | // function : WorldViewState |
242 | // purpose : Returns current state of OCCT world-view transform |
243 | // ======================================================================= |
244 | const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const |
245 | { |
246 | return myWorldViewState; |
247 | } |
248 | |
249 | // ======================================================================= |
250 | // function : PushLightSourceState |
251 | // purpose : Pushes state of OCCT light sources to the program |
252 | // ======================================================================= |
253 | void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
254 | { |
255 | if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)) |
256 | { |
257 | return; |
258 | } |
259 | |
260 | theProgram->SetUniform (myContext, theProgram->GetStateLocation ( |
261 | OpenGl_OCC_LIGHT_SOURCE_COUNT), myLightSourceState.LightSources()->Size()); |
262 | |
263 | OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); |
264 | for (unsigned int anIndex = 0; anIter.More(); anIter.Next()) |
265 | { |
266 | if (anIndex >= OpenGLMaxLights) |
267 | { |
268 | break; |
269 | } |
270 | |
271 | const OpenGl_Light& aLight = anIter.Value(); |
272 | if (aLight.type == TLightAmbient) |
273 | { |
274 | OpenGl_Vec3 anAmbient (aLight.col.rgb[0], |
275 | aLight.col.rgb[1], |
276 | aLight.col.rgb[2]); |
277 | |
278 | theProgram->SetUniform (myContext, |
279 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT + anIndex), anAmbient); |
280 | |
281 | anIter.Next(); |
282 | if (!anIter.More()) |
283 | { |
284 | theProgram->SetUniform (myContext, |
285 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type)); |
286 | break; |
287 | } |
288 | } |
289 | |
290 | OpenGl_Vec3 aDiffuse (aLight.col.rgb[0], |
291 | aLight.col.rgb[1], |
292 | aLight.col.rgb[2]); |
293 | |
294 | OpenGl_Vec3 aPosition (aLight.type == TLightDirectional ? -aLight.dir[0] : aLight.pos[0], |
295 | aLight.type == TLightDirectional ? -aLight.dir[1] : aLight.pos[1], |
296 | aLight.type == TLightDirectional ? -aLight.dir[2] : aLight.pos[2]); |
297 | |
298 | theProgram->SetUniform (myContext, |
299 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type)); |
300 | |
301 | theProgram->SetUniform (myContext, |
302 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_HEAD + anIndex), aLight.HeadLight); |
303 | |
304 | theProgram->SetUniform (myContext, |
305 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE + anIndex), aDiffuse); |
306 | |
307 | theProgram->SetUniform (myContext, |
308 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR + anIndex), aDiffuse); |
309 | |
310 | theProgram->SetUniform (myContext, |
311 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_POSITION + anIndex), aPosition); |
312 | |
313 | theProgram->SetUniform (myContext, |
314 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION + anIndex), aLight.atten[0]); |
315 | |
316 | theProgram->SetUniform (myContext, |
317 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION + anIndex), aLight.atten[1]); |
318 | |
319 | if (aLight.type == TLightSpot) |
320 | { |
321 | OpenGl_Vec3 aDirection (aLight.dir[0], |
322 | aLight.dir[1], |
323 | aLight.dir[2]); |
324 | |
325 | theProgram->SetUniform (myContext, |
326 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF + anIndex), aLight.angle); |
327 | |
328 | theProgram->SetUniform (myContext, |
329 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT + anIndex), aLight.shine); |
330 | |
331 | theProgram->SetUniform (myContext, |
332 | theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION + anIndex), aDirection); |
333 | } |
334 | |
335 | ++anIndex; |
336 | } |
337 | |
338 | theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); |
339 | } |
340 | |
341 | // ======================================================================= |
342 | // function : PushProjectionState |
343 | // purpose : Pushes state of OCCT projection transform to the program |
344 | // ======================================================================= |
345 | void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
346 | { |
347 | if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE)) |
348 | { |
349 | return; |
350 | } |
351 | |
352 | theProgram->SetUniform (myContext, |
353 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX), |
354 | myProjectionState.ProjectionMatrix()); |
355 | |
356 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE); |
357 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
358 | { |
359 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse()); |
360 | } |
361 | |
362 | theProgram->SetUniform (myContext, |
363 | theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE), |
364 | myProjectionState.ProjectionMatrix(), true); |
365 | |
366 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE); |
367 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
368 | { |
369 | theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true); |
370 | } |
371 | |
372 | theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index()); |
373 | } |
374 | |
375 | // ======================================================================= |
376 | // function : PushModelWorldState |
377 | // purpose : Pushes state of OCCT model-world transform to the program |
378 | // ======================================================================= |
379 | void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
380 | { |
381 | if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE)) |
382 | { |
383 | return; |
384 | } |
385 | |
386 | theProgram->SetUniform (myContext, |
387 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX), |
388 | myModelWorldState.ModelWorldMatrix()); |
389 | |
390 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE); |
391 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
392 | { |
393 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse()); |
394 | } |
395 | |
396 | theProgram->SetUniform (myContext, |
397 | theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE), |
398 | myModelWorldState.ModelWorldMatrix(), true); |
399 | |
400 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE); |
401 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
402 | { |
403 | theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true); |
404 | } |
405 | |
406 | theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index()); |
407 | } |
408 | |
409 | // ======================================================================= |
410 | // function : PushWorldViewState |
411 | // purpose : Pushes state of OCCT world-view transform to the program |
412 | // ======================================================================= |
413 | void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
414 | { |
415 | if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE)) |
416 | { |
417 | return; |
418 | } |
419 | |
420 | theProgram->SetUniform (myContext, |
421 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX), |
422 | myWorldViewState.WorldViewMatrix()); |
423 | |
424 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE); |
425 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
426 | { |
427 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse()); |
428 | } |
429 | |
430 | theProgram->SetUniform (myContext, |
431 | theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE), |
432 | myWorldViewState.WorldViewMatrix(), true); |
433 | |
434 | aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE); |
435 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
436 | { |
437 | theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true); |
438 | } |
439 | |
440 | theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index()); |
441 | } |
442 | |
443 | // ======================================================================= |
444 | // function : UpdateClippingState |
445 | // purpose : Updates state of OCCT clipping planes |
446 | // ======================================================================= |
447 | void OpenGl_ShaderManager::UpdateClippingState() |
448 | { |
449 | myClippingState.Update(); |
450 | } |
451 | |
452 | // ======================================================================= |
453 | // function : RevertClippingState |
454 | // purpose : Reverts state of OCCT clipping planes |
455 | // ======================================================================= |
456 | void OpenGl_ShaderManager::RevertClippingState() |
457 | { |
458 | myClippingState.Revert(); |
459 | } |
460 | |
461 | // ======================================================================= |
462 | // function : PushClippingState |
463 | // purpose : Pushes state of OCCT clipping planes to the program |
464 | // ======================================================================= |
465 | void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
466 | { |
467 | if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE)) |
468 | { |
469 | return; |
470 | } |
471 | |
472 | Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes()); |
473 | for (GLuint anIndex = 0; anIter.More(); anIter.Next()) |
474 | { |
475 | const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value(); |
476 | if (!myContext->Clipping().IsEnabled (aPlane)) |
477 | { |
478 | continue; |
479 | } |
480 | |
481 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_EQUATION + anIndex); |
482 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
483 | { |
484 | const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation(); |
485 | theProgram->SetUniform (myContext, aLocation, OpenGl_Vec4 ((float) anEquation.x(), |
486 | (float) anEquation.y(), |
487 | (float) anEquation.z(), |
488 | (float) anEquation.w())); |
489 | } |
490 | |
491 | theProgram->SetUniform (myContext, |
492 | theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_SPACE + anIndex), |
493 | myContext->Clipping().GetEquationSpace (aPlane)); |
494 | ++anIndex; |
495 | } |
496 | |
497 | theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index()); |
498 | } |
499 | |
500 | // ======================================================================= |
501 | // function : UpdateMaterialStateTo |
502 | // purpose : Updates state of OCCT material for specified program |
503 | // ======================================================================= |
504 | void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram, |
505 | const OpenGl_Element* theAspect) |
506 | { |
507 | if (myMaterialStates.IsBound (theProgram)) |
508 | { |
509 | myMaterialStates.ChangeFind (theProgram).Set (theAspect); |
510 | } |
511 | else |
512 | { |
513 | myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect)); |
514 | } |
515 | |
516 | myMaterialStates.ChangeFind (theProgram).Update(); |
517 | } |
518 | |
519 | // ======================================================================= |
520 | // function : ResetMaterialStates |
521 | // purpose : Resets state of OCCT material for all programs |
522 | // ======================================================================= |
523 | void OpenGl_ShaderManager::ResetMaterialStates() |
524 | { |
525 | for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next()) |
526 | { |
527 | anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0); |
528 | } |
529 | } |
530 | |
531 | // ======================================================================= |
532 | // function : MaterialState |
533 | // purpose : Returns state of OCCT material for specified program |
534 | // ======================================================================= |
535 | const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
536 | { |
537 | if (!myMaterialStates.IsBound (theProgram)) |
538 | return NULL; |
539 | |
540 | return &myMaterialStates.Find (theProgram); |
541 | } |
542 | |
543 | namespace |
544 | { |
545 | |
546 | static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f); |
547 | |
548 | // ======================================================================= |
549 | // function : PushAspectFace |
550 | // purpose : |
551 | // ======================================================================= |
552 | static void PushAspectFace (const Handle(OpenGl_Context)& theCtx, |
553 | const Handle(OpenGl_ShaderProgram)& theProgram, |
554 | const OpenGl_AspectFace* theAspect) |
555 | { |
556 | theProgram->SetUniform (theCtx, |
557 | theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), |
558 | theAspect->DoTextureMap()); |
559 | |
560 | theProgram->SetUniform (theCtx, |
561 | theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), |
562 | 0 /* GL_TEXTURE0 */); |
563 | |
564 | theProgram->SetUniform (theCtx, |
565 | theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), |
566 | theAspect->DistinguishingMode()); |
567 | |
568 | for (int anIndex = 0; anIndex < 2; ++anIndex) |
569 | { |
570 | const OPENGL_SURF_PROP& aProperties = (anIndex == 0) ? theAspect->IntFront() : theAspect->IntBack(); |
571 | GLint aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT + anIndex); |
572 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
573 | { |
574 | OpenGl_Vec4 anAmbient (aProperties.ambcol.rgb[0] * aProperties.amb, |
575 | aProperties.ambcol.rgb[1] * aProperties.amb, |
576 | aProperties.ambcol.rgb[2] * aProperties.amb, |
577 | aProperties.ambcol.rgb[3] * aProperties.amb); |
578 | theProgram->SetUniform (theCtx, aLocation, anAmbient); |
579 | } |
580 | |
581 | aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE + anIndex); |
582 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
583 | { |
584 | OpenGl_Vec4 aDiffuse (aProperties.difcol.rgb[0] * aProperties.diff, |
585 | aProperties.difcol.rgb[1] * aProperties.diff, |
586 | aProperties.difcol.rgb[2] * aProperties.diff, |
587 | aProperties.difcol.rgb[3] * aProperties.diff); |
588 | theProgram->SetUniform (theCtx, aLocation, aDiffuse); |
589 | } |
590 | |
591 | aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR + anIndex); |
592 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
593 | { |
594 | OpenGl_Vec4 aSpecular (aProperties.speccol.rgb[0] * aProperties.spec, |
595 | aProperties.speccol.rgb[1] * aProperties.spec, |
596 | aProperties.speccol.rgb[2] * aProperties.spec, |
597 | aProperties.speccol.rgb[3] * aProperties.spec); |
598 | theProgram->SetUniform (theCtx, aLocation, aSpecular); |
599 | } |
600 | |
601 | aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION + anIndex); |
602 | if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION) |
603 | { |
604 | OpenGl_Vec4 anEmission (aProperties.emscol.rgb[0] * aProperties.emsv, |
605 | aProperties.emscol.rgb[1] * aProperties.emsv, |
606 | aProperties.emscol.rgb[2] * aProperties.emsv, |
607 | aProperties.emscol.rgb[3] * aProperties.emsv); |
608 | theProgram->SetUniform (theCtx, aLocation, anEmission); |
609 | } |
610 | |
611 | theProgram->SetUniform (theCtx, |
612 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SHININESS + anIndex), |
613 | aProperties.shine); |
614 | |
615 | theProgram->SetUniform (theCtx, |
616 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY + anIndex), |
617 | aProperties.trans); |
618 | } |
619 | } |
620 | |
621 | // ======================================================================= |
622 | // function : PushAspectLine |
623 | // purpose : |
624 | // ======================================================================= |
625 | static void PushAspectLine (const Handle(OpenGl_Context)& theCtx, |
626 | const Handle(OpenGl_ShaderProgram)& theProgram, |
627 | const OpenGl_AspectLine* theAspect) |
628 | { |
629 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff); |
630 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
631 | |
632 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
633 | theAspect->Color().rgb[1], |
634 | theAspect->Color().rgb[2], |
635 | theAspect->Color().rgb[3]); |
636 | theProgram->SetUniform (theCtx, |
637 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT), |
638 | THE_COLOR_BLACK_VEC4); |
639 | theProgram->SetUniform (theCtx, |
640 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE), |
641 | aDiffuse); |
642 | theProgram->SetUniform (theCtx, |
643 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR), |
644 | THE_COLOR_BLACK_VEC4); |
645 | theProgram->SetUniform (theCtx, |
646 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION), |
647 | THE_COLOR_BLACK_VEC4); |
648 | theProgram->SetUniform (theCtx, |
649 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY), |
650 | 0.0f); |
651 | } |
652 | |
653 | // ======================================================================= |
654 | // function : PushAspectText |
655 | // purpose : |
656 | // ======================================================================= |
657 | static void PushAspectText (const Handle(OpenGl_Context)& theCtx, |
658 | const Handle(OpenGl_ShaderProgram)& theProgram, |
659 | const OpenGl_AspectText* theAspect) |
660 | { |
661 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
662 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
663 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
664 | |
665 | OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
666 | theAspect->Color().rgb[1], |
667 | theAspect->Color().rgb[2], |
668 | theAspect->Color().rgb[3]); |
669 | if (theAspect->DisplayType() == Aspect_TODT_DEKALE |
670 | || theAspect->DisplayType() == Aspect_TODT_SUBTITLE) |
671 | { |
672 | aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0], |
673 | theAspect->SubtitleColor().rgb[1], |
674 | theAspect->SubtitleColor().rgb[2], |
675 | theAspect->SubtitleColor().rgb[3]); |
676 | } |
677 | |
678 | theProgram->SetUniform (theCtx, |
679 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT), |
680 | THE_COLOR_BLACK_VEC4); |
681 | theProgram->SetUniform (theCtx, |
682 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE), |
683 | aDiffuse); |
684 | theProgram->SetUniform (theCtx, |
685 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR), |
686 | THE_COLOR_BLACK_VEC4); |
687 | theProgram->SetUniform (theCtx, |
688 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION), |
689 | THE_COLOR_BLACK_VEC4); |
690 | theProgram->SetUniform (theCtx, |
691 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY), |
692 | 0.0f); |
693 | } |
694 | |
695 | // ======================================================================= |
696 | // function : PushAspectMarker |
697 | // purpose : |
698 | // ======================================================================= |
699 | static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx, |
700 | const Handle(OpenGl_ShaderProgram)& theProgram, |
701 | const OpenGl_AspectMarker* theAspect) |
702 | { |
703 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn); |
704 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff); |
705 | theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */); |
706 | |
707 | const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0], |
708 | theAspect->Color().rgb[1], |
709 | theAspect->Color().rgb[2], |
710 | theAspect->Color().rgb[3]); |
711 | |
712 | theProgram->SetUniform (theCtx, |
713 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT), |
714 | THE_COLOR_BLACK_VEC4); |
715 | theProgram->SetUniform (theCtx, |
716 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE), |
717 | aDiffuse); |
718 | theProgram->SetUniform (theCtx, |
719 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR), |
720 | THE_COLOR_BLACK_VEC4); |
721 | theProgram->SetUniform (theCtx, |
722 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION), |
723 | THE_COLOR_BLACK_VEC4); |
724 | theProgram->SetUniform (theCtx, |
725 | theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY), |
726 | 0.0f); |
727 | } |
728 | |
729 | }; // nameless namespace |
730 | |
731 | // ======================================================================= |
732 | // function : PushMaterialState |
733 | // purpose : Pushes current state of OCCT material to the program |
734 | // ======================================================================= |
735 | void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
736 | { |
737 | if (!myMaterialStates.IsBound (theProgram)) |
738 | { |
739 | return; |
740 | } |
741 | |
742 | const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram); |
743 | if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE)) |
744 | { |
745 | return; |
746 | } |
747 | |
748 | if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace)) |
749 | { |
750 | PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect())); |
751 | } |
752 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine)) |
753 | { |
754 | PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect())); |
755 | } |
756 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText)) |
757 | { |
758 | PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect())); |
759 | } |
760 | else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker)) |
761 | { |
762 | PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect())); |
763 | } |
764 | |
765 | theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index()); |
766 | } |
767 | |
768 | // ======================================================================= |
769 | // function : PushWorldViewState |
770 | // purpose : Pushes state of OCCT graphics parameters to the program |
771 | // ======================================================================= |
772 | void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const |
773 | { |
774 | PushClippingState (theProgram); |
775 | PushMaterialState (theProgram); |
776 | PushWorldViewState (theProgram); |
777 | PushModelWorldState (theProgram); |
778 | PushProjectionState (theProgram); |
779 | PushLightSourceState (theProgram); |
780 | } |