"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.
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
//! 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:
//! 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; }
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:
#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)
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
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,"
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
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);"
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);"
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);
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());
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())
{
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;
{
return TCollection_AsciiString()
+ THE_FUNC_lightDef
+ + Shaders_PointLightAttenuation_glsl
+ aLightsFunc
+ EOL
EOL"vec4 computeLighting (in vec3 theNormal,"
{
return TCollection_AsciiString()
+ THE_FUNC_PBR_lightDef
+ + Shaders_PointLightAttenuation_glsl
+ aLightsFunc
+ EOL
EOL"vec4 computeLighting (in vec3 theNormal,"
{
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
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)
//! 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
srcinc:::PBRIllumination.glsl
srcinc:::PhongShading.fs
srcinc:::PhongShading.vs
+srcinc:::PointLightAttenuation.glsl
srcinc:::Display.fs
srcinc:::RaytraceBase.fs
srcinc:::RaytraceRender.fs
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
--- /dev/null
+//! 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
"//! 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"
--- /dev/null
+// 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";
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:
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:
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")
"\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",
--- /dev/null
+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