0024322: TKOpenGl - light sources management inconsistency
authorduv <duv@opencascade.com>
Wed, 13 Nov 2013 17:07:32 +0000 (21:07 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 14 Nov 2013 08:53:09 +0000 (12:53 +0400)
Fixed pipeline - accumulate all ambient light sources.

Fix clearing of all light sources.

src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_View_2.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
src/Visual3d/Visual3d_Light.cdl
src/Visual3d/Visual3d_Light.cxx
src/Visual3d/Visual3d_View.cxx
tests/v3d/glsl/light_off [new file with mode: 0644]

index 95491ad..4092769 100644 (file)
@@ -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<OpenGl_Vec4*> (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<OpenGl_Vec2i*> (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
index 34f72b4..78d0c70 100644 (file)
@@ -932,6 +932,150 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
 }
 
 // =======================================================================
+// 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
 // =======================================================================
index 0efb326..14ef6dc 100644 (file)
@@ -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.
index 3632e78..84e7494 100644 (file)
@@ -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);
index 421bfde..519f343 100755 (executable)
@@ -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]"
index 72d875d..e5de3f1 100755 (executable)
@@ -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
index 4687a9e..b2a0e93 100755 (executable)
@@ -355,25 +355,6 @@ void Visual3d_Light::SetPosition (const Graphic3d_Vertex& thePos)
 }
 
 // =======================================================================
-// 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  :
 // =======================================================================
index ecdce08..cdf2c5a 100755 (executable)
@@ -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 (file)
index 0000000..8a9c9f7
--- /dev/null
@@ -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!"}