Skip to content

Commit 12f9827

Browse files
committed
Improvements to advanced diffuse shading models.
- Fixed a bug in the Oren-Nayar implementation. - Changed the interaction between the Oren-Nayar and Lommel-Seeliger models to work as originally intended, with `lommel_seeliger K oren_nayar SIGMA` giving a K:(1-K) weighted average of Lommel-Seeliger and Oren-Nayar). - Implemented mechanisms to compensate for the reduced effective brightness of the Oren-Nayar and Lommel-Seeliger models when using canonical brightness parameterization. Using `diffuse albedo FLOAT` should now give identical bihemispherical albedos (ratio of total outgoing light vs. total incoming light) for all models. Also, when using canonical brightness parameterization (`diffuse FLOAT`), the Lambertian-based approximation used in radiosity should now match the effective bihemispherical albedo.
1 parent a419e30 commit 12f9827

File tree

7 files changed

+38
-31
lines changed

7 files changed

+38
-31
lines changed

source/base/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#define OFFICIAL_VERSION_STRING "3.7.1"
4646
#define OFFICIAL_VERSION_NUMBER 371
4747

48-
#define POV_RAY_PRERELEASE "alpha.8545805"
48+
#define POV_RAY_PRERELEASE "alpha.8555867"
4949

5050
#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
5151
#ifdef POV_RAY_PRERELEASE

source/core/lighting/photons.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ void PhotonTrace::ComputeLightedTexture(MathColour& LightCol, ColourChannel&, co
460460
diffuseWeight = ResCol.WeightAbsGreyscale();
461461
// use top-layer finish only
462462
if(Texture->Finish)
463-
diffuseWeight*=Texture->Finish->Diffuse * Texture->Finish->BrillianceAdjust;
463+
diffuseWeight*=Texture->Finish->Diffuse * Texture->Finish->DiffuseAlbedoAdjust;
464464
refractionWeight = Trans;
465465
// reflection only for top layer!!!!!!
466466
// TODO is "rend()" the top layer or the bottom layer???

source/core/material/texture.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,8 +1159,8 @@ FINISH *Create_Finish()
11591159
New->DiffuseBack = 0.0;
11601160
New->Brilliance = 1.0;
11611161
New->BrillianceOut = 1.0;
1162-
New->BrillianceAdjust = 1.0;
1163-
New->BrillianceAdjustRad = 1.0;
1162+
New->DiffuseAlbedoAdjust = 1.0;
1163+
New->DiffuseAlbedoAdjustRad = 1.0;
11641164
New->LommelSeeligerWeight = 0.0;
11651165
New->OrenNayarA = 1.0;
11661166
New->OrenNayarB = 0.0;

source/core/material/texture.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct Texture_Struct : public Pattern_Struct
117117

118118
struct Finish_Struct
119119
{
120-
SNGL Diffuse, DiffuseBack, Brilliance, BrillianceOut, BrillianceAdjust, BrillianceAdjustRad;
120+
SNGL Diffuse, DiffuseBack, Brilliance, BrillianceOut, DiffuseAlbedoAdjust, DiffuseAlbedoAdjustRad;
121121

122122
/// How much of the diffuse contribution should be computed using the Lommel-Seeliger model.
123123
///

source/core/render/trace.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ void Trace::ComputeLightedTexture(MathColour& resultColour, ColourChannel& resul
882882

883883
if (sceneData->radiositySettings.brilliance)
884884
{
885-
diffuse *= layer->Finish->BrillianceAdjustRad;
885+
diffuse *= layer->Finish->DiffuseAlbedoAdjustRad;
886886
brilliance = layer->Finish->Brilliance;
887887
}
888888

@@ -909,7 +909,7 @@ void Trace::ComputeLightedTexture(MathColour& resultColour, ColourChannel& resul
909909

910910
diffuse = layer->Finish->DiffuseBack;
911911
if (sceneData->radiositySettings.brilliance)
912-
diffuse *= layer->Finish->BrillianceAdjustRad;
912+
diffuse *= layer->Finish->DiffuseAlbedoAdjustRad;
913913

914914
// if backside radiosity calculation needed, but not yet done, do it now
915915
// TODO FIXME - [CLi] with "normal on", shouldn't we compute radiosity for each layer separately (if it has pertubed normals)?
@@ -2374,35 +2374,40 @@ void Trace::ComputeDiffuseColour(const FINISH *finish, const Vector3d& lightDire
23742374
const MathColour& layer_pigment_colour, double relativeIor, double attenuation, bool backside)
23752375
{
23762376
double cos_in, cos_out, intensity;
2377-
double diffuse = (backside? finish->DiffuseBack : finish->Diffuse) * finish->BrillianceAdjust;
2377+
double diffuse = (backside? finish->DiffuseBack : finish->Diffuse) * finish->DiffuseAlbedoAdjust;
23782378

23792379
if (diffuse <= 0.0)
23802380
return;
23812381

2382-
cos_in = dot(layer_normal, lightDirection);
2382+
cos_in = fabs(dot(layer_normal, lightDirection));
23832383

23842384
// Brilliance is likely to be 1.0 (default value)
23852385
if(finish->Brilliance != 1.0)
2386-
intensity = pow(fabs(cos_in), (double) finish->Brilliance);
2386+
intensity = pow(cos_in, (double) finish->Brilliance);
23872387
else
2388-
intensity = fabs(cos_in);
2388+
intensity = cos_in;
23892389

23902390
if (finish->Fresnel || (finish->LommelSeeligerWeight != 0.0) || (finish->OrenNayarB != 0.0))
2391-
cos_out = -dot(layer_normal, eyeDirection);
2392-
2393-
if (finish->LommelSeeligerWeight != 0.0)
2394-
intensity *= (1.0 - finish->LommelSeeligerWeight + finish->LommelSeeligerWeight / (cos_in + cos_out));
2391+
cos_out = fabs(dot(layer_normal, eyeDirection));
23952392

2393+
if (finish->OrenNayarA != 1.0)
2394+
intensity *= finish->OrenNayarA;
23962395
if (finish->OrenNayarB != 0.0)
23972396
{
2398-
Vector3d projected_in = lightDirection - layer_normal * cos_in;
2399-
Vector3d projected_out = -eyeDirection - layer_normal * cos_out;
2397+
Vector3d projected_in = (lightDirection - layer_normal * cos_in ).normalized();
2398+
Vector3d projected_out = (-eyeDirection - layer_normal * cos_out).normalized();
24002399
double cos_phi = dot(projected_in, projected_out);
24012400
double theta_in = acos(cos_in);
24022401
double theta_out = acos(cos_out);
24032402
double alpha = max(theta_in, theta_out);
24042403
double beta = min(theta_in, theta_out);
2405-
intensity *= (finish->OrenNayarA + finish->OrenNayarB*max(0.0,cos_phi)*sin(alpha)*tan(beta));
2404+
intensity += finish->OrenNayarB * cos_in * max(0.0,cos_phi) * sin(alpha) * tan(beta);
2405+
}
2406+
2407+
if (finish->LommelSeeligerWeight != 0.0)
2408+
{
2409+
intensity *= (1.0 - finish->LommelSeeligerWeight);
2410+
intensity += finish->LommelSeeligerWeight * cos_in / (cos_in + cos_out);
24062411
}
24072412

24082413
intensity *= diffuse * attenuation;

source/parser/parser_materials.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,10 +2616,6 @@ void Parser::Parse_Finish (FINISH **Finish_Ptr)
26162616
PossibleError("Finish-level 'fresnel' keyword found in combination with the Oren-Nayar diffuse model."
26172617
" The interaction of these features has not been finalized yet, and is known to be bogus."
26182618
" Expect future versions of POV-Ray to render this scene differently without warning.");
2619-
if (diffuseAdjust)
2620-
PossibleError("'diffuse albedo' found in combination with the Oren-Nayar diffuse model."
2621-
" The interaction of these features has not been finalized yet."
2622-
" Expect future versions of POV-Ray to render this scene differently without warning.");
26232619
}
26242620

26252621
if (New->LommelSeeligerWeight != 0.0)
@@ -2628,10 +2624,6 @@ void Parser::Parse_Finish (FINISH **Finish_Ptr)
26282624
PossibleError("Finish-level 'fresnel' keyword found in combination with the Lommel-Seeliger diffuse model."
26292625
" The interaction of these features has not been finalized yet, and is known to be bogus."
26302626
" Expect future versions of POV-Ray to render this scene differently without warning.");
2631-
if (diffuseAdjust)
2632-
PossibleError("'diffuse albedo' found in combination with the Lommel_Seeliger diffuse model."
2633-
" The interaction of these features has not been finalized yet."
2634-
" Expect future versions of POV-Ray to render this scene differently without warning.");
26352627
}
26362628

26372629
if ((sceneData->EffectiveLanguageVersion() >= 370) && ambientSet)
@@ -2659,15 +2651,25 @@ void Parser::Parse_Finish (FINISH **Finish_Ptr)
26592651
// adjust diffuse, phong and/or specular intensity parameters
26602652
// so that a user-specified value of 1.0 corresponds to a
26612653
// backscattering of 100% of the incoming light
2654+
double EffectiveBiHemisphericalAlbedo = 2.0 / (New->Brilliance + 1.0);
2655+
if (New->OrenNayarA != 1.0)
2656+
EffectiveBiHemisphericalAlbedo *= New->OrenNayarA;
2657+
if (New->OrenNayarB != 0.0)
2658+
EffectiveBiHemisphericalAlbedo += New->OrenNayarB * (2.0/3.0 - (64.0/45.0)*(1.0/M_PI));
2659+
if (New->LommelSeeligerWeight != 0.0)
2660+
{
2661+
EffectiveBiHemisphericalAlbedo *= (1.0 - New->LommelSeeligerWeight);
2662+
EffectiveBiHemisphericalAlbedo += New->LommelSeeligerWeight * ((8.0 * (1.0-log(2.0))) / 3.0);
2663+
}
26622664
if (diffuseAdjust)
26632665
{
2664-
New->BrillianceAdjust = (New->Brilliance + 1.0) / 2.0;
2665-
New->BrillianceAdjustRad = 1.0;
2666+
New->DiffuseAlbedoAdjust = 1.0 / EffectiveBiHemisphericalAlbedo;
2667+
New->DiffuseAlbedoAdjustRad = 1.0;
26662668
}
26672669
else
26682670
{
2669-
New->BrillianceAdjust = 1.0;
2670-
New->BrillianceAdjustRad = 2.0 / (New->Brilliance + 1.0);
2671+
New->DiffuseAlbedoAdjust = 1.0;
2672+
New->DiffuseAlbedoAdjustRad = EffectiveBiHemisphericalAlbedo;
26712673
}
26722674
if (phongAdjust)
26732675
New->Phong *= (New->Phong_Size + 1.0) / 2.0;

unix/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.7.1-alpha.8545805
1+
3.7.1-alpha.8555867

0 commit comments

Comments
 (0)