1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

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.
This commit is contained in:
iko 2019-12-24 16:05:00 +03:00 committed by bugmaster
parent 0858125fd4
commit 88b312d3a4
12 changed files with 232 additions and 27 deletions

View 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;
};

View 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:

View 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,"

View 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

View 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)

View 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

View 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

View File

@ -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);
}

View 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"

View File

@ -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";

View 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",

View File

@ -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