1 // Created on: 2013-09-26
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
18 #include <Graphic3d_TextureParams.hxx>
19 #include <OpenGl_AspectFace.hxx>
20 #include <OpenGl_AspectLine.hxx>
21 #include <OpenGl_AspectMarker.hxx>
22 #include <OpenGl_AspectText.hxx>
23 #include <OpenGl_Clipping.hxx>
24 #include <OpenGl_Context.hxx>
25 #include <OpenGl_ShaderManager.hxx>
26 #include <OpenGl_ShaderProgram.hxx>
27 #include <OpenGl_Workspace.hxx>
29 IMPLEMENT_STANDARD_HANDLE (OpenGl_SetOfShaderPrograms, Standard_Transient)
30 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_SetOfShaderPrograms, Standard_Transient)
32 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
33 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
40 //! Definition of VertColor varying.
41 const char THE_VARY_TexCoord_OUT[] =
42 EOL"THE_SHADER_OUT vec2 TexCoord;";
43 const char THE_VARY_TexCoord_IN[] =
44 EOL"THE_SHADER_IN vec2 TexCoord;";
46 //! Auxiliary function to transform normal
47 const char THE_FUNC_transformNormal[] =
48 EOL"vec3 transformNormal (in vec3 theNormal)"
50 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
51 EOL" * occModelWorldMatrixInverseTranspose"
52 EOL" * vec4 (theNormal, 0.0);"
53 EOL" return normalize (aResult.xyz);"
56 //! Global shader variable for color definition with lighting enabled.
57 const char THE_FUNC_lightDef[] =
58 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
59 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
60 EOL"vec3 Specular;"; //!< Specular contribution of light sources
62 //! Function computes contribution of isotropic point light source
63 const char THE_FUNC_pointLight[] =
64 EOL"void pointLight (in int theId,"
65 EOL" in vec3 theNormal,"
66 EOL" in vec3 theView,"
67 EOL" in vec3 thePoint,"
68 EOL" in bool theIsFront)"
70 EOL" vec3 aLight = occLight_Position (theId).xyz;"
71 EOL" if (occLight_IsHeadlight (theId) == 0)"
73 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
75 EOL" aLight -= thePoint;"
77 EOL" float aDist = length (aLight);"
78 EOL" aLight = aLight * (1.0 / aDist);"
80 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
81 EOL" + occLight_LinearAttenuation (theId) * aDist);"
83 EOL" vec3 aHalf = normalize (aLight + theView);"
85 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
86 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
87 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
89 EOL" float aSpecl = 0.0;"
90 EOL" if (aNdotL > 0.0)"
92 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
95 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
96 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
99 //! Function computes contribution of spotlight source
100 const char THE_FUNC_spotLight[] =
101 EOL"void spotLight (in int theId,"
102 EOL" in vec3 theNormal,"
103 EOL" in vec3 theView,"
104 EOL" in vec3 thePoint,"
105 EOL" in bool theIsFront)"
107 EOL" vec3 aLight = occLight_Position (theId).xyz;"
108 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
109 EOL" if (occLight_IsHeadlight (theId) == 0)"
111 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
112 EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
114 EOL" aLight -= thePoint;"
116 EOL" float aDist = length (aLight);"
117 EOL" aLight = aLight * (1.0 / aDist);"
119 EOL" aSpotDir = normalize (aSpotDir);"
121 EOL" float aCosA = dot (aSpotDir, -aLight);"
122 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
127 EOL" float anExponent = occLight_SpotExponent (theId);"
128 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
129 EOL" + occLight_LinearAttenuation (theId) * aDist);"
130 EOL" if (anExponent > 0.0)"
132 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
135 EOL" vec3 aHalf = normalize (aLight + theView);"
137 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
138 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
139 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
141 EOL" float aSpecl = 0.0;"
142 EOL" if (aNdotL > 0.0)"
144 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
147 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
148 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
151 //! Function computes contribution of directional light source
152 const char THE_FUNC_directionalLight[] =
153 EOL"void directionalLight (in int theId,"
154 EOL" in vec3 theNormal,"
155 EOL" in vec3 theView,"
156 EOL" in bool theIsFront)"
158 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
159 EOL" if (occLight_IsHeadlight (theId) == 0)"
161 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
164 EOL" vec3 aHalf = normalize (aLight + theView);"
166 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
167 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
168 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
170 EOL" float aSpecl = 0.0;"
171 EOL" if (aNdotL > 0.0)"
173 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
176 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
177 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
180 //! Process clipping planes in Fragment Shader.
181 //! Should be added at the beginning of the main() function.
182 const char THE_FRAG_CLIP_PLANES[] =
183 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
185 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
186 EOL" int aClipSpace = occClipPlaneSpaces[aPlaneIter];"
187 EOL" if (aClipSpace == OccEquationCoords_World)"
189 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)"
194 EOL" else if (aClipSpace == OccEquationCoords_View)"
196 EOL" if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)"
205 // =======================================================================
206 // function : OpenGl_ShaderManager
207 // purpose : Creates new empty shader manager
208 // =======================================================================
209 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
210 : myShadingModel (Visual3d_TOM_VERTEX),
211 myContext (theContext),
217 // =======================================================================
218 // function : ~OpenGl_ShaderManager
219 // purpose : Releases resources of shader manager
220 // =======================================================================
221 OpenGl_ShaderManager::~OpenGl_ShaderManager()
223 myProgramList.Clear();
226 // =======================================================================
229 // =======================================================================
230 void OpenGl_ShaderManager::clear()
232 myProgramList.Clear();
233 myLightPrograms.Nullify();
234 myFlatPrograms = OpenGl_SetOfShaderPrograms();
235 myMapOfLightPrograms.Clear();
236 myFontProgram.Nullify();
237 myBlitProgram.Nullify();
238 switchLightPrograms();
241 // =======================================================================
243 // purpose : Creates new shader program
244 // =======================================================================
245 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
246 TCollection_AsciiString& theShareKey,
247 Handle(OpenGl_ShaderProgram)& theProgram)
249 theProgram.Nullify();
250 if (theProxy.IsNull())
252 return Standard_False;
255 theShareKey = theProxy->GetId();
256 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
258 if (theProgram->Share())
260 myProgramList.Append (theProgram);
262 return Standard_True;
265 theProgram = new OpenGl_ShaderProgram (theProxy);
266 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
268 theProgram->Release (myContext);
270 theProgram.Nullify();
271 return Standard_False;
274 myProgramList.Append (theProgram);
275 myContext->ShareResource (theShareKey, theProgram);
276 return Standard_True;
279 // =======================================================================
280 // function : Unregister
281 // purpose : Removes specified shader program from the manager
282 // =======================================================================
283 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
284 Handle(OpenGl_ShaderProgram)& theProgram)
286 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
288 if (anIt.Value() == theProgram)
290 if (!theProgram->UnShare())
293 theProgram.Nullify();
297 myProgramList.Remove (anIt);
298 myMaterialStates.UnBind (theProgram);
303 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
306 myContext->DelayedRelease (theProgram);
307 theProgram.Nullify();
311 theProgram.Nullify();
312 myContext->ReleaseResource (anID, Standard_True);
316 // =======================================================================
317 // function : ShaderPrograms
318 // purpose : Returns list of registered shader programs
319 // =======================================================================
320 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
322 return myProgramList;
325 // =======================================================================
327 // purpose : Returns true if no program objects are attached
328 // =======================================================================
329 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
331 return myProgramList.IsEmpty();
334 // =======================================================================
335 // function : switchLightPrograms
337 // =======================================================================
338 void OpenGl_ShaderManager::switchLightPrograms()
340 TCollection_AsciiString aKey (myShadingModel == Visual3d_TOM_FRAGMENT ? "p_" : "g_");
341 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
344 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
346 switch (aLightIter.Value().Type)
348 case Visual3d_TOLS_AMBIENT:
349 break; // skip ambient
350 case Visual3d_TOLS_DIRECTIONAL:
353 case Visual3d_TOLS_POSITIONAL:
356 case Visual3d_TOLS_SPOT:
363 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
365 myLightPrograms = new OpenGl_SetOfShaderPrograms();
366 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
370 // =======================================================================
371 // function : UpdateLightSourceStateTo
372 // purpose : Updates state of OCCT light sources
373 // =======================================================================
374 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
376 myLightSourceState.Set (theLights);
377 myLightSourceState.Update();
378 switchLightPrograms();
381 // =======================================================================
382 // function : SetShadingModel
384 // =======================================================================
385 void OpenGl_ShaderManager::SetShadingModel (const Visual3d_TypeOfModel theModel)
387 myShadingModel = theModel;
388 switchLightPrograms();
391 // =======================================================================
392 // function : SetProjectionState
393 // purpose : Sets new state of OCCT projection transform
394 // =======================================================================
395 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
397 myProjectionState.Set (theProjectionMatrix);
398 myProjectionState.Update();
401 // =======================================================================
402 // function : SetModelWorldState
403 // purpose : Sets new state of OCCT model-world transform
404 // =======================================================================
405 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
407 myModelWorldState.Set (theModelWorldMatrix);
408 myModelWorldState.Update();
411 // =======================================================================
412 // function : SetWorldViewState
413 // purpose : Sets new state of OCCT world-view transform
414 // =======================================================================
415 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
417 myWorldViewState.Set (theWorldViewMatrix);
418 myWorldViewState.Update();
421 // =======================================================================
422 // function : LightSourceState
423 // purpose : Returns current state of OCCT light sources
424 // =======================================================================
425 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
427 return myLightSourceState;
430 // =======================================================================
431 // function : ProjectionState
432 // purpose : Returns current state of OCCT projection transform
433 // =======================================================================
434 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
436 return myProjectionState;
439 // =======================================================================
440 // function : ModelWorldState
441 // purpose : Returns current state of OCCT model-world transform
442 // =======================================================================
443 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
445 return myModelWorldState;
448 // =======================================================================
449 // function : WorldViewState
450 // purpose : Returns current state of OCCT world-view transform
451 // =======================================================================
452 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
454 return myWorldViewState;
457 //! Packed properties of light source
458 class OpenGl_ShaderLightParameters
463 OpenGl_Vec4 Position;
464 OpenGl_Vec4 Direction;
465 OpenGl_Vec4 Parameters;
467 //! Returns packed (serialized) representation of light source properties
468 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
469 static Standard_Integer NbOfVec4() { return 4; }
473 //! Packed light source type information
474 class OpenGl_ShaderLightType
478 Standard_Integer Type;
479 Standard_Integer IsHeadlight;
481 //! Returns packed (serialized) representation of light source type
482 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
483 static Standard_Integer NbOfVec2i() { return 1; }
487 // =======================================================================
488 // function : PushLightSourceState
489 // purpose : Pushes state of OCCT light sources to the program
490 // =======================================================================
491 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
493 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
494 || !theProgram->IsValid())
499 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
500 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
502 aLightTypeArray[aLightIt].Type = -1;
505 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
506 if (aLightsDefNb < 1)
508 theProgram->SetUniform (myContext,
509 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
511 theProgram->SetUniform (myContext,
512 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
513 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
514 theProgram->SetUniform (myContext,
515 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
516 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
517 aLightTypeArray[0].Packed());
518 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
519 delete[] aLightTypeArray;
523 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
525 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
526 Standard_Integer aLightsNb = 0;
527 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
529 const OpenGl_Light& aLight = anIter.Value();
530 if (aLight.Type == Visual3d_TOLS_AMBIENT)
532 anAmbient += aLight.Color;
535 else if (aLightsNb >= OpenGLMaxLights)
540 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
541 aLightType.Type = aLight.Type;
542 aLightType.IsHeadlight = aLight.IsHeadlight;
544 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
545 aLightParams.Color = aLight.Color;
546 aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
549 if (aLight.Type == Visual3d_TOLS_SPOT)
551 aLightParams.Direction = aLight.Direction;
553 aLightParams.Parameters = aLight.Params;
557 theProgram->SetUniform (myContext,
558 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
560 theProgram->SetUniform (myContext,
561 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
563 theProgram->SetUniform (myContext,
564 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
565 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
566 aLightTypeArray[0].Packed());
569 theProgram->SetUniform (myContext,
570 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
571 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
572 aLightParamsArray[0].Packed());
574 delete[] aLightParamsArray;
575 delete[] aLightTypeArray;
577 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
580 // =======================================================================
581 // function : PushProjectionState
582 // purpose : Pushes state of OCCT projection transform to the program
583 // =======================================================================
584 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
586 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
591 theProgram->SetUniform (myContext,
592 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
593 myProjectionState.ProjectionMatrix());
595 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
596 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
598 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
601 theProgram->SetUniform (myContext,
602 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
603 myProjectionState.ProjectionMatrix(), true);
605 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
606 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
608 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
611 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
614 // =======================================================================
615 // function : PushModelWorldState
616 // purpose : Pushes state of OCCT model-world transform to the program
617 // =======================================================================
618 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
620 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
625 theProgram->SetUniform (myContext,
626 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
627 myModelWorldState.ModelWorldMatrix());
629 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
630 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
632 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
635 theProgram->SetUniform (myContext,
636 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
637 myModelWorldState.ModelWorldMatrix(), true);
639 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
640 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
642 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
645 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
648 // =======================================================================
649 // function : PushWorldViewState
650 // purpose : Pushes state of OCCT world-view transform to the program
651 // =======================================================================
652 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
654 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
659 theProgram->SetUniform (myContext,
660 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
661 myWorldViewState.WorldViewMatrix());
663 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
664 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
666 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
669 theProgram->SetUniform (myContext,
670 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
671 myWorldViewState.WorldViewMatrix(), true);
673 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
674 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
676 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
679 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
682 // =======================================================================
683 // function : UpdateClippingState
684 // purpose : Updates state of OCCT clipping planes
685 // =======================================================================
686 void OpenGl_ShaderManager::UpdateClippingState()
688 myClippingState.Update();
691 // =======================================================================
692 // function : RevertClippingState
693 // purpose : Reverts state of OCCT clipping planes
694 // =======================================================================
695 void OpenGl_ShaderManager::RevertClippingState()
697 myClippingState.Revert();
700 // =======================================================================
701 // function : PushClippingState
702 // purpose : Pushes state of OCCT clipping planes to the program
703 // =======================================================================
704 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
706 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
711 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
712 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
713 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
714 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
715 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
721 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
722 anIter.More(); anIter.Next())
724 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
725 if (!myContext->Clipping().IsEnabled (aPlane))
737 const Standard_Size MAX_CLIP_PLANES = 8;
738 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
739 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
741 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
742 anIter.More(); anIter.Next())
744 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
745 if (!myContext->Clipping().IsEnabled (aPlane))
750 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
751 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
752 (float) anEquation.y(),
753 (float) anEquation.z(),
754 (float) anEquation.w());
755 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
759 theProgram->SetUniform (myContext,
760 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
762 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
763 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
765 delete[] anEquations;
769 // =======================================================================
770 // function : UpdateMaterialStateTo
771 // purpose : Updates state of OCCT material for specified program
772 // =======================================================================
773 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
774 const OpenGl_Element* theAspect)
776 if (myMaterialStates.IsBound (theProgram))
778 OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
779 aState.Set (theAspect);
784 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
785 myMaterialStates.ChangeFind (theProgram).Update();
789 // =======================================================================
790 // function : ResetMaterialStates
791 // purpose : Resets state of OCCT material for all programs
792 // =======================================================================
793 void OpenGl_ShaderManager::ResetMaterialStates()
795 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
797 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
801 // =======================================================================
802 // function : MaterialState
803 // purpose : Returns state of OCCT material for specified program
804 // =======================================================================
805 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
807 if (!myMaterialStates.IsBound (theProgram))
810 return &myMaterialStates.Find (theProgram);
813 // =======================================================================
814 // function : SurfaceDetailState
815 // purpose : Returns current state of OCCT surface detail
816 // =======================================================================
817 const OpenGl_SurfaceDetailState& OpenGl_ShaderManager::SurfaceDetailState() const
819 return mySurfaceDetailState;
822 // =======================================================================
823 // function : UpdateSurfaceDetailStateTo
824 // purpose : Updates state of OCCT surface detail
825 // =======================================================================
826 void OpenGl_ShaderManager::UpdateSurfaceDetailStateTo (const Visual3d_TypeOfSurfaceDetail theDetail)
828 mySurfaceDetailState.Set (theDetail);
829 mySurfaceDetailState.Update();
835 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
837 // =======================================================================
838 // function : PushAspectFace
840 // =======================================================================
841 static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
842 const Handle(OpenGl_ShaderProgram)& theProgram,
843 const OpenGl_AspectFace* theAspect)
845 theProgram->SetUniform (theCtx,
846 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
847 theAspect->DoTextureMap());
848 theProgram->SetUniform (theCtx,
849 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
850 0 /* GL_TEXTURE0 */);
851 theProgram->SetUniform (theCtx,
852 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
853 theAspect->DistinguishingMode());
855 OpenGl_Material aParams;
856 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
858 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
859 ? OpenGl_OCCT_FRONT_MATERIAL
860 : OpenGl_OCCT_BACK_MATERIAL);
861 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
866 aParams.Init (anIndex == 0 || theAspect->DistinguishingMode() != TOn
867 ? theAspect->IntFront()
868 : theAspect->IntBack());
869 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
874 // =======================================================================
875 // function : PushAspectLine
877 // =======================================================================
878 static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
879 const Handle(OpenGl_ShaderProgram)& theProgram,
880 const OpenGl_AspectLine* theAspect)
882 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
883 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
885 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
886 theAspect->Color().rgb[1],
887 theAspect->Color().rgb[2],
888 theAspect->Color().rgb[3]);
889 OpenGl_Vec4 aParams[5];
890 aParams[0] = THE_COLOR_BLACK_VEC4;
891 aParams[1] = THE_COLOR_BLACK_VEC4;
892 aParams[2] = aDiffuse;
893 aParams[3] = THE_COLOR_BLACK_VEC4;
894 aParams[4].x() = 0.0f; // shininess
895 aParams[4].y() = 0.0f; // transparency
896 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
900 // =======================================================================
901 // function : PushAspectText
903 // =======================================================================
904 static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
905 const Handle(OpenGl_ShaderProgram)& theProgram,
906 const OpenGl_AspectText* theAspect)
908 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
909 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
910 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
912 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
913 theAspect->Color().rgb[1],
914 theAspect->Color().rgb[2],
915 theAspect->Color().rgb[3]);
916 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
917 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
919 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
920 theAspect->SubtitleColor().rgb[1],
921 theAspect->SubtitleColor().rgb[2],
922 theAspect->SubtitleColor().rgb[3]);
925 OpenGl_Vec4 aParams[5];
926 aParams[0] = THE_COLOR_BLACK_VEC4;
927 aParams[1] = THE_COLOR_BLACK_VEC4;
928 aParams[2] = aDiffuse;
929 aParams[3] = THE_COLOR_BLACK_VEC4;
930 aParams[4].x() = 0.0f; // shininess
931 aParams[4].y() = 0.0f; // transparency
932 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
936 // =======================================================================
937 // function : PushAspectMarker
939 // =======================================================================
940 static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
941 const Handle(OpenGl_ShaderProgram)& theProgram,
942 const OpenGl_AspectMarker* theAspect)
944 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
945 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
946 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
948 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
949 theAspect->Color().rgb[1],
950 theAspect->Color().rgb[2],
951 theAspect->Color().rgb[3]);
952 OpenGl_Vec4 aParams[5];
953 aParams[0] = THE_COLOR_BLACK_VEC4;
954 aParams[1] = THE_COLOR_BLACK_VEC4;
955 aParams[2] = aDiffuse;
956 aParams[3] = THE_COLOR_BLACK_VEC4;
957 aParams[4].x() = 0.0f; // shininess
958 aParams[4].y() = 0.0f; // transparency
959 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
963 }; // nameless namespace
965 // =======================================================================
966 // function : PushMaterialState
967 // purpose : Pushes current state of OCCT material to the program
968 // =======================================================================
969 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
971 if (!myMaterialStates.IsBound (theProgram))
976 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
977 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
982 if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
984 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
986 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
988 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
990 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
992 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
994 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
996 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
999 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
1002 // =======================================================================
1003 // function : PushState
1004 // purpose : Pushes state of OCCT graphics parameters to the program
1005 // =======================================================================
1006 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1008 PushClippingState (theProgram);
1009 PushMaterialState (theProgram);
1010 PushWorldViewState (theProgram);
1011 PushModelWorldState (theProgram);
1012 PushProjectionState (theProgram);
1013 PushLightSourceState (theProgram);
1016 // =======================================================================
1017 // function : prepareStdProgramFont
1019 // =======================================================================
1020 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1022 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1023 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1024 + THE_VARY_TexCoord_OUT
1027 EOL" TexCoord = occTexCoord.st;"
1028 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1031 TCollection_AsciiString
1032 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
1033 #if !defined(GL_ES_VERSION_2_0)
1034 if (myContext->core11 == NULL)
1036 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
1040 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
1041 + THE_VARY_TexCoord_IN
1045 EOL" vec4 aColor = occColor;"
1046 EOL" aColor.a *= getAlpha();"
1047 EOL" if (aColor.a <= 0.285) discard;"
1048 EOL" occFragColor = aColor;"
1051 #if !defined(GL_ES_VERSION_2_0)
1052 if (myContext->core32 != NULL)
1054 aProgramSrc->SetHeader ("#version 150");
1057 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1058 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1059 TCollection_AsciiString aKey;
1060 if (!Create (aProgramSrc, aKey, myFontProgram))
1062 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1063 return Standard_False;
1065 return Standard_True;
1068 // =======================================================================
1069 // function : prepareStdProgramFboBlit
1071 // =======================================================================
1072 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1074 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1075 TCollection_AsciiString aSrcVert =
1076 EOL"THE_SHADER_OUT vec2 TexCoord;"
1079 EOL" TexCoord = occVertex.zw;"
1080 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1083 TCollection_AsciiString aSrcFrag =
1084 EOL"uniform sampler2D uColorSampler;"
1085 EOL"uniform sampler2D uDepthSampler;"
1087 EOL"THE_SHADER_IN vec2 TexCoord;"
1091 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1092 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1095 #if defined(GL_ES_VERSION_2_0)
1096 if (myContext->IsGlGreaterEqual (3, 0))
1098 aProgramSrc->SetHeader ("#version 300 es");
1102 // there is no way to draw into depth buffer
1104 EOL"uniform sampler2D uColorSampler;"
1106 EOL"THE_SHADER_IN vec2 TexCoord;"
1110 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1114 if (myContext->core32 != NULL)
1116 aProgramSrc->SetHeader ("#version 150");
1119 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1120 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1121 TCollection_AsciiString aKey;
1122 if (!Create (aProgramSrc, aKey, myBlitProgram))
1124 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1125 return Standard_False;
1128 myContext->BindProgram (myBlitProgram);
1129 myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
1130 myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
1131 myContext->BindProgram (NULL);
1132 return Standard_True;
1135 // =======================================================================
1136 // function : prepareStdProgramFlat
1138 // =======================================================================
1139 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1140 const Standard_Integer theBits)
1142 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1143 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1144 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1145 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
1146 if ((theBits & OpenGl_PO_Point) != 0)
1148 #if defined(GL_ES_VERSION_2_0)
1149 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1151 if ((theBits & OpenGl_PO_TextureA) != 0)
1153 TCollection_AsciiString
1154 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).a; }";
1155 #if !defined(GL_ES_VERSION_2_0)
1156 if (myContext->core11 == NULL)
1158 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).r; }";
1162 aSrcFragGetColor = aSrcGetAlpha
1163 + EOL"vec4 getColor(void)"
1165 EOL" vec4 aColor = occColor;"
1166 EOL" aColor.a *= getAlpha();"
1167 EOL" return aColor;"
1170 aSrcFragMainGetColor =
1171 EOL" vec4 aColor = getColor();"
1172 EOL" if (aColor.a <= 0.1) discard;"
1173 EOL" occFragColor = aColor;";
1175 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1178 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, gl_PointCoord); }";
1179 aSrcFragMainGetColor =
1180 EOL" vec4 aColor = getColor();"
1181 EOL" if (aColor.a <= 0.1) discard;"
1182 EOL" occFragColor = aColor;";
1187 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1189 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1190 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1191 aSrcVertExtraMain +=
1192 EOL" TexCoord = occTexCoord.st;";
1195 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st); }";
1197 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1199 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1200 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1202 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1204 aSrcVertExtraMain +=
1205 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1206 EOL" vec3 aNormal = transformNormal (occNormal);"
1207 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1208 EOL" aReflect.z += 1.0;"
1209 EOL" TexCoord = aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5);";
1212 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1215 if ((theBits & OpenGl_PO_VertColor) != 0)
1217 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1218 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1219 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
1220 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1222 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1225 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1226 EOL"THE_SHADER_OUT vec4 Position;";
1228 EOL"THE_SHADER_IN vec4 PositionWorld;"
1229 EOL"THE_SHADER_IN vec4 Position;";
1230 aSrcVertExtraMain +=
1231 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1232 EOL" Position = occWorldViewMatrix * PositionWorld;";
1233 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1242 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1251 + aSrcFragMainGetColor
1254 #if !defined(GL_ES_VERSION_2_0)
1255 if (myContext->core32 != NULL)
1257 aProgramSrc->SetHeader ("#version 150");
1260 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1261 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1263 TCollection_AsciiString aKey;
1264 if (!Create (aProgramSrc, aKey, theProgram))
1266 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1267 return Standard_False;
1269 return Standard_True;
1272 // =======================================================================
1273 // function : stdComputeLighting
1275 // =======================================================================
1276 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
1278 bool aLightsMap[Visual3d_TOLS_SPOT + 1] = { false, false, false, false };
1279 TCollection_AsciiString aLightsFunc, aLightsLoop;
1280 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1281 if (aLights != NULL)
1283 Standard_Integer anIndex = 0;
1284 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1286 switch (aLightIter.Value().Type)
1288 case Visual3d_TOLS_AMBIENT:
1290 break; // skip ambient
1291 case Visual3d_TOLS_DIRECTIONAL:
1292 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1294 case Visual3d_TOLS_POSITIONAL:
1295 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1297 case Visual3d_TOLS_SPOT:
1298 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1302 bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
1309 switch (aLightIter.Value().Type)
1311 case Visual3d_TOLS_AMBIENT: break;
1312 case Visual3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
1313 case Visual3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break;
1314 case Visual3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break;
1319 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1320 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1321 if (theHasVertColor)
1323 aGetMatAmbient = "getVertColor();";
1324 aGetMatDiffuse = "getVertColor();";
1327 return TCollection_AsciiString()
1331 EOL"vec4 computeLighting (in vec3 theNormal,"
1332 EOL" in vec3 theView,"
1333 EOL" in vec4 thePoint,"
1334 EOL" in bool theIsFront)"
1336 EOL" Ambient = occLightAmbient.rgb;"
1337 EOL" Diffuse = vec3 (0.0);"
1338 EOL" Specular = vec3 (0.0);"
1339 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1341 + EOL" vec4 aMaterialAmbient = " + aGetMatAmbient
1342 + EOL" vec4 aMaterialDiffuse = " + aGetMatDiffuse
1343 + EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1344 EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1345 EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
1346 EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
1347 EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
1348 EOL" + aMaterialEmission;"
1352 // =======================================================================
1353 // function : prepareStdProgramGouraud
1355 // =======================================================================
1356 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1357 const Standard_Integer theBits)
1359 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1360 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1361 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
1362 if ((theBits & OpenGl_PO_Point) != 0)
1364 #if defined(GL_ES_VERSION_2_0)
1365 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1368 if ((theBits & OpenGl_PO_VertColor) != 0)
1370 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1372 if ((theBits & OpenGl_PO_Point) != 0)
1374 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1377 EOL"vec4 getColor(void)"
1379 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1380 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1386 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1388 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1389 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1390 aSrcVertExtraMain +=
1391 EOL" TexCoord = occTexCoord.st;";
1394 EOL"vec4 getColor(void)"
1396 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1397 EOL" return occTexture2D(occActiveSampler, TexCoord.st) * aColor;"
1401 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1404 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1405 EOL"THE_SHADER_OUT vec4 Position;";
1407 EOL"THE_SHADER_IN vec4 PositionWorld;"
1408 EOL"THE_SHADER_IN vec4 Position;";
1409 aSrcVertExtraMain +=
1410 EOL" PositionWorld = aPositionWorld;"
1411 EOL" Position = aPosition;";
1412 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1415 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1416 aSrcVert = TCollection_AsciiString()
1417 + THE_FUNC_transformNormal
1422 EOL"THE_SHADER_OUT vec4 FrontColor;"
1423 EOL"THE_SHADER_OUT vec4 BackColor;"
1428 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1429 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1430 EOL" vec3 aNormal = transformNormal (occNormal);"
1431 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1432 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1433 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1435 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1438 aSrcFrag = TCollection_AsciiString()
1439 + EOL"THE_SHADER_IN vec4 FrontColor;"
1440 EOL"THE_SHADER_IN vec4 BackColor;"
1446 + EOL" occFragColor = getColor();"
1449 #if !defined(GL_ES_VERSION_2_0)
1450 if (myContext->core32 != NULL)
1452 aProgramSrc->SetHeader ("#version 150");
1455 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1456 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1457 TCollection_AsciiString aKey;
1458 if (!Create (aProgramSrc, aKey, theProgram))
1460 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1461 return Standard_False;
1463 return Standard_True;
1466 // =======================================================================
1467 // function : prepareStdProgramPhong
1469 // =======================================================================
1470 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1471 const Standard_Integer theBits)
1473 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1475 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1476 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1477 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
1478 if ((theBits & OpenGl_PO_Point) != 0)
1480 #if defined(GL_ES_VERSION_2_0)
1481 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1484 if ((theBits & OpenGl_PO_VertColor) != 0)
1486 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1487 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1488 aSrcFragGetColor = EOL"THE_SHADER_IN vec4 VertColor;"
1489 EOL"vec4 getVertColor(void) { return VertColor; }";
1492 if ((theBits & OpenGl_PO_Point) != 0)
1494 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1497 EOL"vec4 getColor(void)"
1499 EOL" vec4 aColor = " thePhongCompLight ";"
1500 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1506 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1508 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1509 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1510 aSrcVertExtraMain +=
1511 EOL" TexCoord = occTexCoord.st;";
1514 EOL"vec4 getColor(void)"
1516 EOL" vec4 aColor = " thePhongCompLight ";"
1517 EOL" return occTexture2D(occActiveSampler, TexCoord.st) * aColor;"
1522 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1524 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1527 aSrcVert = TCollection_AsciiString()
1528 + THE_FUNC_transformNormal
1530 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1531 EOL"THE_SHADER_OUT vec4 Position;"
1532 EOL"THE_SHADER_OUT vec3 Normal;"
1533 EOL"THE_SHADER_OUT vec3 View;"
1538 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1539 EOL" Position = occWorldViewMatrix * PositionWorld;"
1540 EOL" Normal = transformNormal (occNormal);"
1541 EOL" View = vec3 (0.0, 0.0, 1.0);"
1543 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1546 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1547 aSrcFrag = TCollection_AsciiString()
1548 + EOL"THE_SHADER_IN vec4 PositionWorld;"
1549 EOL"THE_SHADER_IN vec4 Position;"
1550 EOL"THE_SHADER_IN vec3 Normal;"
1551 EOL"THE_SHADER_IN vec3 View;"
1554 + aSrcFragGetVertColor
1561 + EOL" occFragColor = getColor();"
1564 #if !defined(GL_ES_VERSION_2_0)
1565 if (myContext->core32 != NULL)
1567 aProgramSrc->SetHeader ("#version 150");
1570 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1571 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1572 TCollection_AsciiString aKey;
1573 if (!Create (aProgramSrc, aKey, theProgram))
1575 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1576 return Standard_False;
1578 return Standard_True;
1581 // =======================================================================
1582 // function : bindProgramWithState
1584 // =======================================================================
1585 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1586 const OpenGl_Element* theAspect)
1588 if (!myContext->BindProgram (theProgram))
1590 return Standard_False;
1592 theProgram->ApplyVariables (myContext);
1594 const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1595 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1597 UpdateMaterialStateTo (theProgram, theAspect);
1600 PushState (theProgram);
1601 return Standard_True;