]> OCCT Git - occt-copy.git/commitdiff
0031099: Visualization, TKOpenGl - support Point light source with artistic full...
authoriko <iko@opencascade.com>
Tue, 24 Dec 2019 13:05:00 +0000 (16:05 +0300)
committerbugmaster <bugmaster@opencascade.com>
Mon, 13 Jan 2020 13:07:19 +0000 (16:07 +0300)
"Range" parameter of point light sources (positional and spot) concidering in PBR has been added.
Angular attenuation parameter of spot light in PBR has been reimplemented based on existing "concentration" parameter.

12 files changed:
src/Graphic3d/Graphic3d_CLight.cxx
src/Graphic3d/Graphic3d_CLight.hxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx
src/Shaders/Declarations.glsl
src/Shaders/FILES
src/Shaders/PointLightAttenuation.glsl [new file with mode: 0644]
src/Shaders/Shaders_Declarations_glsl.pxx
src/Shaders/Shaders_PointLightAttenuation_glsl.pxx [new file with mode: 0644]
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/glsl/pbr_attenuation [new file with mode: 0644]

index 04437873eec170db77aef8069ed8cc657ba2d5c6..0e8941cd2d019483af3a242ab48d38deabd6ced5 100644 (file)
@@ -233,3 +233,16 @@ void Graphic3d_CLight::SetSmoothAngle (Standard_ShortReal theValue)
   updateRevisionIf (Abs (mySmoothness - theValue) > ShortRealEpsilon());
   mySmoothness = theValue;
 }
+
+// =======================================================================
+// function : SetRange
+// purpose  :
+// =======================================================================
+void Graphic3d_CLight::SetRange (Standard_ShortReal theValue)
+{
+  Standard_ProgramError_Raise_if (myType != Graphic3d_TOLS_POSITIONAL && myType != Graphic3d_TOLS_SPOT,
+                                  "Graphic3d_CLight::SetRange(), incorrect light type");
+  Standard_OutOfRange_Raise_if (theValue < 0.0, "Graphic3d_CLight::SetRange(), Bad value for falloff range");
+  updateRevisionIf (Abs (Range() - theValue) > ShortRealEpsilon());
+  myDirection.w() = theValue;
+};
\ No newline at end of file
index fd8b68c66d368830eebd567727132c39ec8eb586..54276d7cc2eb8d65121192758120f033a9e24182 100644 (file)
@@ -177,6 +177,16 @@ public:
   //! Modifies the smoothing angle (in radians) of directional light source; should be within range [0.0, M_PI/2].
   Standard_EXPORT void SetSmoothAngle (Standard_ShortReal theValue);
 
+  //! Returns maximum distance on which point light source affects to objects and is considered during illumination calculations.
+  //! 0.0 means disabling range considering at all without any distance limits.
+  //! Has sense only for point light sources (positional and spot).  
+  Standard_ShortReal Range() const { return myDirection.w(); }
+
+  //! Modifies maximum distance on which point light source affects to objects and is considered during illumination calculations.
+  //! Positional and spot lights are only point light sources.
+  //! 0.0 means disabling range considering at all without any distance limits.
+  Standard_EXPORT void SetRange (Standard_ShortReal theValue);
+
 //! @name low-level access methods
 public:
 
@@ -189,8 +199,8 @@ public:
   //! Returns the color of the light source with dummy Alpha component, which should be ignored.
   const Graphic3d_Vec4& PackedColor() const { return myColor; }
 
-  //! Returns direction of directional/spot light.
-  const Graphic3d_Vec4& PackedDirection() const { return myDirection; }
+  //! Returns direction of directional/spot light and range for positional/spot light in alpha channel.
+  const Graphic3d_Vec4& PackedDirectionRange() const { return myDirection; }
 
   //! @return modification counter
   Standard_Size Revision() const { return myRevision; }
@@ -204,10 +214,10 @@ private:
   Standard_ShortReal& changeLinearAttenuation() { return myParams.y(); }
 
   //! Access spotlight angle parameter from packed vector.
-  Standard_ShortReal& changeAngle()             { return myParams.z();  }
+  Standard_ShortReal& changeAngle()             { return myParams.z(); }
 
   //! Access spotlight concentration parameter from packed vector.
-  Standard_ShortReal& changeConcentration()     { return myParams.w();  }
+  Standard_ShortReal& changeConcentration()     { return myParams.w(); }
 
 private:
 
index a1dfa2bf5f967335664a879b27a744555966de0e..bb3c407c51a3b1ec9c6c3ac64ee67bcc78a9cca9 100644 (file)
@@ -34,6 +34,7 @@
 #include "../Shaders/Shaders_PBRIllumination_glsl.pxx"
 #include "../Shaders/Shaders_PBREnvBaking_fs.pxx"
 #include "../Shaders/Shaders_PBREnvBaking_vs.pxx"
+#include "../Shaders/Shaders_PointLightAttenuation_glsl.pxx"
 
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
 
@@ -117,9 +118,10 @@ const char THE_FUNC_pointLight[] =
   EOL"  aLight -= thePoint;"
   EOL
   EOL"  float aDist = length (aLight);"
-  EOL"  aLight = aLight * (1.0 / aDist);"
-  EOL
-  EOL"  float anAtten = 1.0 / (occLight_ConstAttenuation (theId) + occLight_LinearAttenuation (theId) * aDist);"
+  EOL"  float aRange = occLight_Range (theId);"
+  EOL"  float anAtten = occPointLightAttenuation (aDist, aRange, occLight_LinearAttenuation (theId), occLight_ConstAttenuation (theId));"
+  EOL"  if (anAtten <= 0.0) return;"
+  EOL"  aLight /= aDist;"
   EOL
   EOL"  vec3 aHalf = normalize (aLight + theView);"
   EOL
@@ -153,10 +155,11 @@ const char THE_FUNC_PBR_pointLight[] =
   EOL"  aLight -= thePoint;"
   EOL
   EOL"  float aDist = length (aLight);"
+  EOL"  float aRange = occLight_Range (theId);"
+  EOL"  float anAtten = occPointLightAttenuation (aDist, aRange);"
+  EOL"  if (anAtten <= 0.0) return;"
   EOL"  aLight /= aDist;"
   EOL
-  EOL"  float anAtten = 1.0 / max (aDist * aDist, 0.01);"
-  EOL
   EOL"  theNormal = theIsFront ? theNormal : -theNormal;"
   EOL"  DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
   EOL"                                        BaseColor, Metallic, Roughness, IOR,"
@@ -182,7 +185,10 @@ const char THE_FUNC_spotLight[] =
   EOL"  aLight -= thePoint;"
   EOL
   EOL"  float aDist = length (aLight);"
-  EOL"  aLight = aLight * (1.0 / aDist);"
+  EOL"  float aRange = occLight_Range (theId);"
+  EOL"  float anAtten = occPointLightAttenuation (aDist, aRange, occLight_LinearAttenuation (theId), occLight_ConstAttenuation (theId));"
+  EOL"  if (anAtten <= 0.0) return;"
+  EOL"  aLight /= aDist;"
   EOL
   EOL"  aSpotDir = normalize (aSpotDir);"
   // light cone
@@ -193,8 +199,6 @@ const char THE_FUNC_spotLight[] =
   EOL"  }"
   EOL
   EOL"  float anExponent = occLight_SpotExponent (theId);"
-  EOL"  float anAtten    = 1.0 / (occLight_ConstAttenuation  (theId)"
-  EOL"                          + occLight_LinearAttenuation (theId) * aDist);"
   EOL"  if (anExponent > 0.0)"
   EOL"  {"
   EOL"    anAtten *= pow (aCosA, anExponent * 128.0);"
@@ -234,25 +238,30 @@ const char THE_FUNC_spotLight[] =
   EOL"  aLight -= thePoint;"
   EOL
   EOL"  float aDist = length (aLight);"
+  EOL"  float aRange = occLight_Range (theId);"
+  EOL"  float anAtten = occPointLightAttenuation (aDist, aRange);"
+  EOL"  if (anAtten <= 0.0) return;"
   EOL"  aLight /= aDist;"
   EOL
   EOL"  aSpotDir = normalize (aSpotDir);"
   // light cone
   EOL"  float aCosA = dot (aSpotDir, -aLight);"
-  EOL"  if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
+  EOL"  float aRelativeAngle = 2.0 * acos(aCosA) / occLight_SpotCutOff(theId);"
+  EOL"  if (aCosA >= 1.0 || aRelativeAngle > 1.0)"
   EOL"  {"
   EOL"    return;"
   EOL"  }"
-  EOL
   EOL"  float anExponent = occLight_SpotExponent (theId);"
-  EOL"  float anAtten    = 1.0 / max (aDist * aDist, 0.01);"
-  EOL"  if (anExponent > 0.0)"
+  EOL"  if ((1.0 - aRelativeAngle) <= anExponent)"
   EOL"  {"
-  EOL"    anAtten *= pow (aCosA, anExponent * 128.0);"
+  EOL"    float anAngularAttenuationOffset = cos(0.5 * occLight_SpotCutOff(theId));"
+  EOL"    float anAngularAttenuationScale = 1.0 / max(0.001, cos(0.5 * occLight_SpotCutOff(theId) * (1.0 - anExponent)) - anAngularAttenuationOffset);"
+  EOL"    anAngularAttenuationOffset *= -anAngularAttenuationScale;"
+  EOL"    float anAngularAttenuantion = clamp(aCosA * anAngularAttenuationScale + anAngularAttenuationOffset, 0.0, 1.0);"
+  EOL"    anAtten *= anAngularAttenuantion * anAngularAttenuantion;"
   EOL"  }"
-  EOL
   EOL"  theNormal = theIsFront ? theNormal : -theNormal;"
-  EOL"  DirectLighting += occPBRIllumination (theView aLight, theNormal,"
+  EOL"  DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
   EOL"                                        BaseColor, Metallic, Roughness, IOR,"
   EOL"                                        occLight_Specular(theId),"
   EOL"                                        occLight_Intensity(theId) * anAtten);"
@@ -459,7 +468,7 @@ EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatr
       case Graphic3d_TOLS_DIRECTIONAL:
       {
         // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
-        const OpenGl_Vec4 anInfDir = -theLight.PackedDirection();
+        const OpenGl_Vec4 anInfDir = -theLight.PackedDirectionRange();
 
         // to create a realistic effect,  set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
         theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
@@ -494,7 +503,7 @@ EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatr
         theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE,               aLightColor.GetData());
         theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR,              aLightColor.GetData());
         theCtx->core11->glLightfv (theLightGlId, GL_POSITION,              aPosition.GetData());
-        theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION,        theLight.PackedDirection().GetData());
+        theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION,        theLight.PackedDirectionRange().GetData());
         theCtx->core11->glLightf  (theLightGlId, GL_SPOT_EXPONENT,         theLight.Concentration() * 128.0f);
         theCtx->core11->glLightf  (theLightGlId, GL_SPOT_CUTOFF,          (theLight.Angle() * 180.0f) / GLfloat(M_PI));
         theCtx->core11->glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
@@ -903,7 +912,7 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr
     aLightParams.Color.a() = aLight.Intensity(); // used by PBR and ignored by old shading model
     if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
     {
-      aLightParams.Position = -aLight.PackedDirection();
+      aLightParams.Position = -aLight.PackedDirectionRange();
     }
     else if (!aLight.IsHeadlight())
     {
@@ -921,7 +930,11 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr
 
     if (aLight.Type() == Graphic3d_TOLS_SPOT)
     {
-      aLightParams.Direction = aLight.PackedDirection();
+      aLightParams.Direction = aLight.PackedDirectionRange();
+    }
+    if (aLight.Type() == Graphic3d_TOLS_POSITIONAL)
+    {
+      aLightParams.Direction.w() = aLight.Range();
     }
     aLightParams.Parameters = aLight.PackedParams();
     ++aLightsNb;
@@ -2325,6 +2338,7 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
   {
     return TCollection_AsciiString()
     + THE_FUNC_lightDef
+    + Shaders_PointLightAttenuation_glsl
     + aLightsFunc
     + EOL
       EOL"vec4 computeLighting (in vec3 theNormal,"
@@ -2352,6 +2366,7 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
   {
     return TCollection_AsciiString()
     + THE_FUNC_PBR_lightDef
+    + Shaders_PointLightAttenuation_glsl
     + aLightsFunc
     + EOL
       EOL"vec4 computeLighting (in vec3 theNormal,"
index e11f179f9c07c53e6a56b7de210732722f07c70d..7089b5c280a915084e3dddb93fc98006abc5732a 100644 (file)
@@ -762,7 +762,7 @@ protected:
   {
     OpenGl_Vec4 Color;      //!< RGB color + Intensity (in .w)
     OpenGl_Vec4 Position;   //!< XYZ Direction or Position + IsHeadlight (in .w)
-    OpenGl_Vec4 Direction;  //!< spot light XYZ direction
+    OpenGl_Vec4 Direction;  //!< spot light XYZ direction + Range (in .w)
     OpenGl_Vec4 Parameters; //!< same as Graphic3d_CLight::PackedParams()
 
     //! Returns packed (serialized) representation of light source properties
index 266a82a99aa2730bed01d0dc7e2199f365d3b157..90377c68fb9c6db5459cd412c75afdbe92943474 100644 (file)
@@ -2440,9 +2440,9 @@ Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& the
                           aLightColor.b() * aLight.Intensity(),
                           1.0f);
 
-    BVH_Vec4f aPosition (-aLight.PackedDirection().x(),
-                         -aLight.PackedDirection().y(),
-                         -aLight.PackedDirection().z(),
+    BVH_Vec4f aPosition (-aLight.PackedDirectionRange().x(),
+                         -aLight.PackedDirectionRange().y(),
+                         -aLight.PackedDirectionRange().z(),
                          0.0f);
 
     if (aLight.Type() != Graphic3d_TOLS_DIRECTIONAL)
index b7dbe78c2ee36268cfa2032d71ecc1afc2ed6f04..081fa70e7f6dc2f27b5f1ff3bb84056f9698d85e 100644 (file)
@@ -156,6 +156,9 @@ uniform THE_PREC_ENUM int  occLightSourcesCount; //!< Total number of light sour
 //! Direction of specified spot light source, vec3.
 #define occLight_SpotDirection(theId)     occLightSources[theId * 4 + 2].xyz
 
+//! Range on which point light source (positional or spot) can affect (>= 0), float.
+#define occLight_Range(theId)             occLightSources[theId * 4 + 2].w
+
 //! Maximum spread angle of the spot light (in radians), float.
 #define occLight_SpotCutOff(theId)        occLightSources[theId * 4 + 3].z
 
index 327206af37749906cdbacde5eb04913fbc41f655..06d166ba2e93efa8d45a7c512dc508338bec16e6 100644 (file)
@@ -9,6 +9,7 @@ srcinc:::PBRGeometry.glsl
 srcinc:::PBRIllumination.glsl
 srcinc:::PhongShading.fs
 srcinc:::PhongShading.vs
+srcinc:::PointLightAttenuation.glsl
 srcinc:::Display.fs
 srcinc:::RaytraceBase.fs
 srcinc:::RaytraceRender.fs
@@ -25,6 +26,7 @@ Shaders_PBREnvBaking_vs.pxx
 Shaders_PBRFresnel_glsl.pxx
 Shaders_PBRGeometry_glsl.pxx
 Shaders_PBRIllumination_glsl.pxx
+Shaders_PointLightAttenuation_glsl.pxx
 Shaders_RaytraceBase_fs.pxx
 Shaders_RaytraceRender_fs.pxx
 Shaders_PathtraceBase_fs.pxx
diff --git a/src/Shaders/PointLightAttenuation.glsl b/src/Shaders/PointLightAttenuation.glsl
new file mode 100644 (file)
index 0000000..cb84039
--- /dev/null
@@ -0,0 +1,35 @@
+//! Returns point light source attenuation factor
+float occRangedPointLightAttenuation (in float theDistance, in float theRange)
+{
+  if (theDistance <= theRange)
+  {
+    float aResult = theDistance / theRange;
+    aResult *= aResult;
+    aResult *= aResult;
+    aResult = 1.0 - aResult;
+    aResult = clamp(aResult, 0.0, 1.0);
+    aResult /= max(0.0001, theDistance * theDistance);
+    return aResult;
+  }
+  return -1.0;
+}
+
+//! Returns point light source attenuation factor with quadratic attenuation in case of zero range.
+float occPointLightAttenuation (in float theDistance, in float theRange)
+{
+  if (theRange == 0.0)
+  {
+    return 1.0 / max(0.0001, theDistance * theDistance);
+  }
+  return occRangedPointLightAttenuation (theDistance, theRange);
+}
+
+//! Returns point light source attenuation factor with linear attenuation in case of zero range.
+float occPointLightAttenuation (in float theDistance, in float theRange, in float theLinearAttenuation, in float theConstAttenuation)
+{
+  if (theRange == 0.0)
+  {
+    return 1.0 / (theConstAttenuation + theLinearAttenuation * theDistance);
+  }
+  return occRangedPointLightAttenuation (theDistance, theRange);
+}
\ No newline at end of file
index 4cd83b435d90a363fcd2f37a7ec86e2033d017ed..cffec840910cd9b2b0f8b2ba8f1eed9778a63b43 100644 (file)
@@ -159,6 +159,9 @@ static const char Shaders_Declarations_glsl[] =
   "//! Direction of specified spot light source, vec3.\n"
   "#define occLight_SpotDirection(theId)     occLightSources[theId * 4 + 2].xyz\n"
   "\n"
+  "//! Range on which point light source (positional or spot) can affect (>= 0), float.\n"
+  "#define occLight_Range(theId)             occLightSources[theId * 4 + 2].w\n"
+  "\n"
   "//! Maximum spread angle of the spot light (in radians), float.\n"
   "#define occLight_SpotCutOff(theId)        occLightSources[theId * 4 + 3].z\n"
   "\n"
diff --git a/src/Shaders/Shaders_PointLightAttenuation_glsl.pxx b/src/Shaders/Shaders_PointLightAttenuation_glsl.pxx
new file mode 100644 (file)
index 0000000..9e3e35f
--- /dev/null
@@ -0,0 +1,38 @@
+// This file has been automatically generated from resource file src/Shaders/PointLightAttenuation.glsl
+
+static const char Shaders_PointLightAttenuation_glsl[] =
+  "//! Returns point light source attenuation factor\n"
+  "float occRangedPointLightAttenuation (in float theDistance, in float theRange)\n"
+  "{\n"
+  "  if (theDistance <= theRange)\n"
+  "  {\n"
+  "    float aResult = theDistance / theRange;\n"
+  "    aResult *= aResult;\n"
+  "    aResult *= aResult;\n"
+  "    aResult = 1.0 - aResult;\n"
+  "    aResult = clamp(aResult, 0.0, 1.0);\n"
+  "    aResult /= max(0.0001, theDistance * theDistance);\n"
+  "    return aResult;\n"
+  "  }\n"
+  "  return -1.0;\n"
+  "}\n"
+  "\n"
+  "//! Returns point light source attenuation factor with quadratic attenuation in case of zero range.\n"
+  "float occPointLightAttenuation (in float theDistance, in float theRange)\n"
+  "{\n"
+  "  if (theRange == 0.0)\n"
+  "  {\n"
+  "    return 1.0 / max(0.0001, theDistance * theDistance);\n"
+  "  }\n"
+  "  return occRangedPointLightAttenuation (theDistance, theRange);\n"
+  "}\n"
+  "\n"
+  "//! Returns point light source attenuation factor with linear attenuation in case of zero range.\n"
+  "float occPointLightAttenuation (in float theDistance, in float theRange, in float theLinearAttenuation, in float theConstAttenuation)\n"
+  "{\n"
+  "  if (theRange == 0.0)\n"
+  "  {\n"
+  "    return 1.0 / (theConstAttenuation + theLinearAttenuation * theDistance);\n"
+  "  }\n"
+  "  return occRangedPointLightAttenuation (theDistance, theRange);\n"
+  "}\n";
index c1e1e059d5c723538aa15ae4c1ba280623b8910c..65a1834d4908a7967a56e9996d983aab5961ad0f 100644 (file)
@@ -10712,6 +10712,7 @@ static int VLight (Draw_Interpretor& theDi,
           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
           aLight->Attenuation (anAtten[0], anAtten[1]);
           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
+          theDi << "  Range:      " << aLight->Range() << "\n";
           break;
         }
         case V3d_SPOT:
@@ -10727,6 +10728,7 @@ static int VLight (Draw_Interpretor& theDi,
           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
+          theDi << "  Range:      " << aLight->Range() << "\n";
           break;
         }
         default:
@@ -11184,6 +11186,20 @@ static int VLight (Draw_Interpretor& theDi,
 
       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
     }
+    else if (anArgCase.IsEqual("RANGE")
+          || anArgCase.IsEqual("-RANGE"))
+    {
+      if (++anArgIt >= theArgsNb
+       || aLightCurr.IsNull()
+       || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT
+       || aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      aLightCurr->SetRange ((Standard_ShortReal)Atof (theArgVec[anArgIt]));
+    }
     else if (anArgCase.IsEqual ("HEAD")
           || anArgCase.IsEqual ("HEADLIGHT")
           || anArgCase.IsEqual ("-HEAD")
@@ -14382,6 +14398,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n        -{linearAtten}uation value"
     "\n        -angle angleDeg"
     "\n        -{spotexp}onent value"
+    "\n        -range value"
     "\n        -local|-global"
     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
diff --git a/tests/v3d/glsl/pbr_attenuation b/tests/v3d/glsl/pbr_attenuation
new file mode 100644 (file)
index 0000000..4d0db05
--- /dev/null
@@ -0,0 +1,69 @@
+puts "========"
+puts "0031099: Visualization, TKOpenGl - support Point light source with artistic full cut-off distance"
+puts "Test of point light's (positional and spot) attenuation and range in PBR"
+puts "========"
+
+pload XDE OCAF VISUALIZATION MODELING
+catch { Close D }
+
+vclear
+vclose ALL
+vinit View1 -w 512 -h 512
+
+vtop
+vrenderparams -shadingmodel pbr
+
+box b -2 -2 -0.00001 4 4 0.00001
+XNewDoc D
+set bs [XAddShape D b 0]
+XAddVisMaterial D m -baseColor WHITE -transparency 0.0 -metallic 0.0 -roughness 1.0
+XSetVisMaterial D $bs m
+XDisplay -dispMode 1 D
+vfit
+
+vlight -clear
+vlight -add positional -pos -1 0 1 -intensity 0.5
+vlight -add spot -pos 1 0 1 -dir 0 0 -1 -intensity 0.5 -angle 100
+
+vdump $::imagedir/${::casename}_norange_high.png
+
+vlight -change 0 -pos -1 0 0.5
+vlight -change 1 -pos 1 0 0.5
+
+vdump $::imagedir/${::casename}_norange_low.png
+
+vlight -change 0 -range 1
+vlight -change 1 -range 1
+
+vdump $::imagedir/${::casename}_range1.png
+
+vlight -change 0 -range 0.5
+vlight -change 1 -range 0.5
+
+vdump $::imagedir/${::casename}_range0_5.png
+
+vlight -change 0 -range 0.6
+vlight -change 1 -range 0.6
+
+vdump $::imagedir/${::casename}_range0_6.png
+
+vlight -change 0 -range 10
+vlight -change 1 -range 10
+
+vdump $::imagedir/${::casename}_range10.png
+
+box b -5.0 -5.0 -0.00001 10 10 0.00001
+XNewDoc D
+set bs [XAddShape D b 0]
+XAddVisMaterial D m -baseColor WHITE -transparency 0.0 -metallic 0.0 -roughness 1.0
+XSetVisMaterial D $bs m
+XDisplay -dispMode 1 D
+vfit
+vlight -clear
+for {set i 0} {$i < 5} {incr i} {
+  for {set j 0} {$j < 5} {incr j} {
+    vlight -add spot -pos [expr -4.0+2.0*$i] [expr -4.0+2.0*$j] 0.5 -dir 0 0 -1 -intensity 0.5 -angle 100 -exp [expr ($i*5+$j) / 24.0]
+  }
+}
+
+vdump $::imagedir/${::casename}_angle_attenuation.png