From: duv Date: Wed, 13 Nov 2013 17:07:32 +0000 (+0400) Subject: 0024322: TKOpenGl - light sources management inconsistency X-Git-Tag: V6_7_0~81 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=4fe9ad57df8922e43e7a3efa3f3fd6111d7a639d 0024322: TKOpenGl - light sources management inconsistency Fixed pipeline - accumulate all ambient light sources. Fix clearing of all light sources. --- diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 95491ade66..4092769818 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -249,6 +249,36 @@ const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const return myWorldViewState; } +//! Packed properties of light source +class OpenGl_ShaderLightParameters +{ +public: + + OpenGl_Vec4 Color; + OpenGl_Vec4 Position; + OpenGl_Vec4 Direction; + OpenGl_Vec4 Parameters; + + //! Returns packed (serialized) representation of light source properties + const OpenGl_Vec4* Packed() { return reinterpret_cast (this); } + static Standard_Size NbOfVec4() { return 4; } + +}; + +//! Packed light source type information +class OpenGl_ShaderLightType +{ +public: + + Standard_Integer Type; + Standard_Integer IsHeadlight; + + //! Returns packed (serialized) representation of light source type + const OpenGl_Vec2i* Packed() { return reinterpret_cast (this); } + static Standard_Size NbOfVec2i() { return 1; } + +}; + // ======================================================================= // function : PushLightSourceState // purpose : Pushes state of OCCT light sources to the program @@ -261,9 +291,6 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr return; } - const GLint aTypesLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES); - const GLint aParamsLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS); - const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights); if (aLightsDefNb < 1) { @@ -277,8 +304,8 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr return; } - OpenGl_Vec2i* aTypesArray = new OpenGl_Vec2i[aLightsDefNb]; - OpenGl_Vec4* aParamsArray = new OpenGl_Vec4 [aLightsDefNb * 4]; + OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb]; + OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[aLightsDefNb]; OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f); Standard_Integer aLightsNb = 0; @@ -295,18 +322,20 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr continue; } - aTypesArray[aLightsNb].x() = aLight.Type; - aTypesArray[aLightsNb].y() = aLight.IsHeadlight; + OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb]; + aLightType.Type = aLight.Type; + aLightType.IsHeadlight = aLight.IsHeadlight; - aParamsArray[aLightsNb * 4 + 0] = aLight.Color; - aParamsArray[aLightsNb * 4 + 1] = aLight.Type == Visual3d_TOLS_DIRECTIONAL - ? -aLight.Direction - : aLight.Position; + OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb]; + aLightParams.Color = aLight.Color; + aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL + ? -aLight.Direction + : aLight.Position; if (aLight.Type == Visual3d_TOLS_SPOT) { - aParamsArray[aLightsNb * 4 + 2] = aLight.Direction; + aLightParams.Direction = aLight.Direction; } - aParamsArray[aLightsNb * 4 + 3] = aLight.Params; + aLightParams.Parameters = aLight.Params; ++aLightsNb; } @@ -318,11 +347,17 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr anAmbient); if (aLightsNb > 0) { - myContext->core20->glUniform2iv (aTypesLoc, aLightsNb, aTypesArray [0].GetData()); - myContext->core20->glUniform4fv (aParamsLoc, aLightsNb * 4, aParamsArray[0].GetData()); + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES), + aLightsNb * OpenGl_ShaderLightType::NbOfVec2i(), + aLightTypeArray[0].Packed()); + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS), + aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(), + aLightParamsArray[0].Packed()); } - delete[] aTypesArray; - delete[] aParamsArray; + delete[] aLightParamsArray; + delete[] aLightTypeArray; theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index()); } @@ -504,8 +539,9 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram) aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane); ++aPlaneId; } - myContext->core20->glUniform4fv (aLocEquations, aPlanesNb, anEquations[0].GetData()); - myContext->core20->glUniform1iv (aLocSpaces, aPlanesNb, aSpaces); + theProgram->SetUniform (myContext, aLocEquations, aPlanesNb, anEquations[0].GetData()); + theProgram->SetUniform (myContext, aLocSpaces, aPlanesNb, aSpaces); + delete[] anEquations; delete[] aSpaces; } @@ -610,7 +646,7 @@ static void PushAspectFace (const Handle(OpenGl_Context)& theCtx, aParams[3] = aSpecular; aParams[4].x() = aProps.shine; aParams[4].y() = aProps.trans; - theCtx->core20->glUniform4fv (aLoc, 5, aParams[0].GetData()); + theProgram->SetUniform (theCtx, aLoc, 5, aParams); } } @@ -636,8 +672,8 @@ static void PushAspectLine (const Handle(OpenGl_Context)& theCtx, aParams[3] = THE_COLOR_BLACK_VEC4; aParams[4].x() = 0.0f; // shininess aParams[4].y() = 0.0f; // transparency - theCtx->core20->glUniform4fv (theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), - 5, aParams[0].GetData()); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), + 5, aParams); } // ======================================================================= @@ -672,8 +708,8 @@ static void PushAspectText (const Handle(OpenGl_Context)& theCtx, aParams[3] = THE_COLOR_BLACK_VEC4; aParams[4].x() = 0.0f; // shininess aParams[4].y() = 0.0f; // transparency - theCtx->core20->glUniform4fv (theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), - 5, aParams[0].GetData()); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), + 5, aParams); } // ======================================================================= @@ -699,8 +735,8 @@ static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx, aParams[3] = THE_COLOR_BLACK_VEC4; aParams[4].x() = 0.0f; // shininess aParams[4].y() = 0.0f; // transparency - theCtx->core20->glUniform4fv (theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), - 5, aParams[0].GetData()); + theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL), + 5, aParams); } }; // nameless namespace diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 34f72b4b6e..78d0c70a74 100644 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -931,6 +931,150 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& return Standard_True; } +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the float uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const Standard_ShortReal* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform1fv (theLocation, theCount, theData); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the float2 uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec2* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform2fv (theLocation, theCount, theData[0].GetData()); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the float3 uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec3* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform3fv (theLocation, theCount, theData[0].GetData()); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the float4 uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec4* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform4fv (theLocation, theCount, theData[0].GetData()); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the integer uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const Standard_Integer* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform1iv (theLocation, theCount, theData); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the int2 uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec2i* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform2iv (theLocation, theCount, theData[0].GetData()); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the int3 uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec3i* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform3iv (theLocation, theCount, theData[0].GetData()); + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the int4 uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec4i* theData) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniform4iv (theLocation, theCount, theData[0].GetData()); + return Standard_True; +} + // ======================================================================= // function : SetSampler // purpose : Specifies the value of the sampler uniform variable diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 0efb326fd3..14ef6dc24d 100644 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -373,6 +373,54 @@ public: const Tmatrix3& theValue, GLboolean theTranspose = GL_FALSE); + //! Specifies the value of the float uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const Standard_ShortReal* theData); + + //! Specifies the value of the float2 uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec2* theData); + + //! Specifies the value of the float3 uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec3* theData); + + //! Specifies the value of the float4 uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec4* theData); + + //! Specifies the value of the integer uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const Standard_Integer* theData); + + //! Specifies the value of the int2 uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec2i* theData); + + //! Specifies the value of the int3 uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec3i* theData); + + //! Specifies the value of the int4 uniform array + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint theCount, + const OpenGl_Vec4i* theData); + public: //! Specifies the value of the sampler uniform variable. diff --git a/src/OpenGl/OpenGl_View_2.cxx b/src/OpenGl/OpenGl_View_2.cxx index 3632e78dd7..84e7494024 100644 --- a/src/OpenGl/OpenGl_View_2.cxx +++ b/src/OpenGl/OpenGl_View_2.cxx @@ -74,7 +74,8 @@ struct OPENGL_CLIP_PLANE * Set des lumieres */ static void bind_light (const OpenGl_Light& theLight, - GLenum& theLightGlId) + GLenum& theLightGlId, + Graphic3d_Vec4& theAmbientColor) { // Only 8 lights in OpenGL... if (theLightGlId > GL_LIGHT7) @@ -84,8 +85,8 @@ static void bind_light (const OpenGl_Light& theLight, if (theLight.Type == Visual3d_TOLS_AMBIENT) { - // setup RGBA intensity of the ambient light - glLightModelfv (GL_LIGHT_MODEL_AMBIENT, theLight.Color.GetData()); + // add RGBA intensity of the ambient light + theAmbientColor += theLight.Color; return; } @@ -933,13 +934,21 @@ D = -[Px,Py,Pz] dot |Nx| // Apply Lights { // setup lights - glLightModelfv (GL_LIGHT_MODEL_AMBIENT, THE_DEFAULT_AMBIENT); + Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0], + THE_DEFAULT_AMBIENT[1], + THE_DEFAULT_AMBIENT[2], + THE_DEFAULT_AMBIENT[3]); GLenum aLightGlId = GL_LIGHT0; for (OpenGl_ListOfLight::Iterator aLightIt (myLights); aLightIt.More(); aLightIt.Next()) { - bind_light (aLightIt.Value(), aLightGlId); + bind_light (aLightIt.Value(), aLightGlId, anAmbientColor); } + + // apply accumulated ambient color + anAmbientColor.a() = 1.0f; + glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData()); + if (aLightGlId != GL_LIGHT0) { glEnable (GL_LIGHTING); diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 421bfde0b7..519f3436d8 100755 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -5533,6 +5533,23 @@ static int VLight (Draw_Interpretor& theDi, { isGlobal = Standard_False; } + else if (anArgCase.IsEqual ("DEF") + || anArgCase.IsEqual ("DEFAULTS")) + { + toCreate = Standard_False; + aViewer->SetDefaultLights(); + } + else if (anArgCase.IsEqual ("CLR") + || anArgCase.IsEqual ("CLEAR")) + { + toCreate = Standard_False; + aView->InitActiveLights(); + while (aView->MoreActiveLights()) + { + aViewer->DelLight (aView->ActiveLight()); + aView->InitActiveLights(); + } + } else if (anArgCase.IsEqual ("AMB") || anArgCase.IsEqual ("AMBIENT") || anArgCase.IsEqual ("AMBLIGHT")) @@ -5708,6 +5725,22 @@ static int VLight (Draw_Interpretor& theDi, return 1; } } + else if (anArgCase.IsEqual ("ANG") + || anArgCase.IsEqual ("ANGLE")) + { + if (++anArgIt >= theArgsNb) + { + std::cerr << "Wrong syntax at argument '" << anArg << "'!\n"; + return 1; + } + + Standard_Real anAngle = Atof (theArgVec[anArgIt]); + + if (!aLightSpot.IsNull()) + { + aLightSpot->SetAngle (anAngle / 180.0 * M_PI); + } + } else if (anArgCase.IsEqual ("CONSTATTEN") || anArgCase.IsEqual ("CONSTATTENUATION")) { @@ -6217,6 +6250,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) __FILE__, VDefaults, group); theCommands.Add("vlight", "vlight [add|new {amb}ient|directional|{spot}light|positional]" + "\n\t\t: [{def}aults] [clear]" "\n\t\t: [{del}ete|change lightId] [local|global]" "\n\t\t: [{pos}ition X Y Z] [color colorName] [{head}light 0|1]" "\n\t\t: [{constAtten}uation value] [{linearAtten}uation value]" diff --git a/src/Visual3d/Visual3d_Light.cdl b/src/Visual3d/Visual3d_Light.cdl index 72d875d096..e5de3f199d 100755 --- a/src/Visual3d/Visual3d_Light.cdl +++ b/src/Visual3d/Visual3d_Light.cdl @@ -292,23 +292,6 @@ is -- Category: Class methods -------------------------- - Limit ( myclass ) - returns Integer from Standard; - ---Level: Internal - ---Purpose: Maximum number of activatable light sources. - ---Category: Class methods - - ---------------------------- - -- Category: Private methods - ---------------------------- - - Identification ( me ) - returns Integer from Standard - is static private; - ---Level: Internal - ---Purpose: Returns the light identification. - ---Category: Private methods - IsValid ( myclass; AAngle : Real from Standard ) returns Boolean from Standard diff --git a/src/Visual3d/Visual3d_Light.cxx b/src/Visual3d/Visual3d_Light.cxx index 4687a9ee99..b2a0e93888 100755 --- a/src/Visual3d/Visual3d_Light.cxx +++ b/src/Visual3d/Visual3d_Light.cxx @@ -354,25 +354,6 @@ void Visual3d_Light::SetPosition (const Graphic3d_Vertex& thePos) myCLight.Position.z() = float (thePos.Z()); } -// ======================================================================= -// function : Limit -// purpose : -// ======================================================================= -Standard_Integer Visual3d_Light::Limit() -{ - // Old method, replaced by GraphicDriver::InquireLightLimit() - return 0; -} - -// ======================================================================= -// function : Identification -// purpose : -// ======================================================================= -Standard_Integer Visual3d_Light::Identification() const -{ - return 0; -} - // ======================================================================= // function : IsValid // purpose : diff --git a/src/Visual3d/Visual3d_View.cxx b/src/Visual3d/Visual3d_View.cxx index ecdce08f66..cdf2c5ad5f 100755 --- a/src/Visual3d/Visual3d_View.cxx +++ b/src/Visual3d/Visual3d_View.cxx @@ -730,6 +730,7 @@ void Visual3d_View::UpdateLights() MyGraphicDriver->InquireLightLimit()); if (MyCView.Context.NbActiveLight < 1) { + MyGraphicDriver->SetLight (MyCView); return; } diff --git a/tests/v3d/glsl/light_off b/tests/v3d/glsl/light_off new file mode 100644 index 0000000000..8a9c9f771f --- /dev/null +++ b/tests/v3d/glsl/light_off @@ -0,0 +1,19 @@ +puts "========" +puts "Test to verify the lights are turned off after 'vlight clear' (and scene is black)" +puts "========" + +# create box +box b 1 2 3 + +# draw box +vinit View1 +vclear +vsetdispmode 1 +vdisplay b +vfit + +vlight clear + +set color [vreadpixel 100 100 rgb] +set black "0 0 0\n" +if {[string equal $color $black] != 1} {error "Lights do not seems to be cleared!"}