From 88b312d3a4647916bda9a0b72cd168f0b9606265 Mon Sep 17 00:00:00 2001 From: iko Date: Tue, 24 Dec 2019 16:05:00 +0300 Subject: [PATCH] 0031099: Visualization, TKOpenGl - support Point light source with artistic full cut-off distance "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. --- src/Graphic3d/Graphic3d_CLight.cxx | 13 ++++ src/Graphic3d/Graphic3d_CLight.hxx | 18 +++-- src/OpenGl/OpenGl_ShaderManager.cxx | 53 +++++++++----- src/OpenGl/OpenGl_ShaderManager.hxx | 2 +- src/OpenGl/OpenGl_View_Raytrace.cxx | 6 +- src/Shaders/Declarations.glsl | 3 + src/Shaders/FILES | 2 + src/Shaders/PointLightAttenuation.glsl | 35 ++++++++++ src/Shaders/Shaders_Declarations_glsl.pxx | 3 + .../Shaders_PointLightAttenuation_glsl.pxx | 38 ++++++++++ src/ViewerTest/ViewerTest_ViewerCommands.cxx | 17 +++++ tests/v3d/glsl/pbr_attenuation | 69 +++++++++++++++++++ 12 files changed, 232 insertions(+), 27 deletions(-) create mode 100644 src/Shaders/PointLightAttenuation.glsl create mode 100644 src/Shaders/Shaders_PointLightAttenuation_glsl.pxx create mode 100644 tests/v3d/glsl/pbr_attenuation diff --git a/src/Graphic3d/Graphic3d_CLight.cxx b/src/Graphic3d/Graphic3d_CLight.cxx index 04437873ee..0e8941cd2d 100644 --- a/src/Graphic3d/Graphic3d_CLight.cxx +++ b/src/Graphic3d/Graphic3d_CLight.cxx @@ -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 diff --git a/src/Graphic3d/Graphic3d_CLight.hxx b/src/Graphic3d/Graphic3d_CLight.hxx index fd8b68c66d..54276d7cc2 100644 --- a/src/Graphic3d/Graphic3d_CLight.hxx +++ b/src/Graphic3d/Graphic3d_CLight.hxx @@ -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: diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index a1dfa2bf5f..bb3c407c51 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -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," diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index e11f179f9c..7089b5c280 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -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 diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index 266a82a99a..90377c68fb 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -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) diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index b7dbe78c2e..081fa70e7f 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -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 diff --git a/src/Shaders/FILES b/src/Shaders/FILES index 327206af37..06d166ba2e 100644 --- a/src/Shaders/FILES +++ b/src/Shaders/FILES @@ -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 index 0000000000..cb840393a5 --- /dev/null +++ b/src/Shaders/PointLightAttenuation.glsl @@ -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 diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index 4cd83b435d..cffec84091 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -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 index 0000000000..9e3e35f314 --- /dev/null +++ b/src/Shaders/Shaders_PointLightAttenuation_glsl.pxx @@ -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"; diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index c1e1e059d5..65a1834d49 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -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 index 0000000000..4d0db059f1 --- /dev/null +++ b/tests/v3d/glsl/pbr_attenuation @@ -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