Skip to content

Commit

Permalink
Added advanced diffuse shading models.
Browse files Browse the repository at this point in the history
The traditional Lambertian model can only realistically simulate the diffuse component of _smooth_ surfaces; this commit adds two alternative models that give more realistic results for non-smooth surfaces:

The _Lommel-Seeliger_ model mimics very porous or dusty surfaces. While it has no parameters in and of itself, it is frequently used in a weighted average with the Lambertian model. To activate the Lommel-Seeliger model in POV-Ray, use `diffuse FLOAT lommel_seeliger on` for the pure model, or `diffuse FLOAT lommel_seeliger FLOAT` for a blend with the Lambertian model. The default is `lommel_seeliger 0.0`, indicating a blend of 0% Lommel-Seeliger and 100% Lambertian.

The _Oren-Nayar_ model extends the Lambertian model to mimic rough (but not porous) surfaces. To activate it in POV-Ray, use `diffuse FLOAT oren_nayar FLOAT`, where the parameter specifies the desired roughness (the _sigma_ parameter in the Oren-Nayar equations). The default is `oren_nayar 0.0`, indicating a perfectly smooth surface, in which case the Oren-Nayar model simplifies to the Lambertian model.

_NOTE:_ The new diffuse shading models are still highly experimental, and changes in syntax and/or functionality are almost guaranteed; most notably, the interaction with the `diffuse albedo FLOAT` syntax and the finish-level `fresnel` keyword still needs to be reviewed and possibly modified. Also, the parameterization of the Oren-Nayar model may be changed to better match the `roughness` parameterization for specular highlights.
  • Loading branch information
c-lipka committed Mar 31, 2016
1 parent 0a062cc commit a419e30
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 24 deletions.
2 changes: 1 addition & 1 deletion source/base/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#define OFFICIAL_VERSION_STRING "3.7.1"
#define OFFICIAL_VERSION_NUMBER 371

#define POV_RAY_PRERELEASE "alpha.8514084"
#define POV_RAY_PRERELEASE "alpha.8545805"

#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
#ifdef POV_RAY_PRERELEASE
Expand Down
27 changes: 15 additions & 12 deletions source/core/material/texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1153,18 +1153,21 @@ FINISH *Create_Finish()
New->Reflection_Max.Clear();
New->Reflection_Min.Clear();

New->Reflection_Fresnel = false;
New->Reflection_Falloff = 1; /* Added by MBP 8/27/98 */
New->Diffuse = 0.6;
New->DiffuseBack = 0.0;
New->Brilliance = 1.0;
New->BrillianceOut = 1.0;
New->BrillianceAdjust = 1.0;
New->BrillianceAdjustRad = 1.0;
New->Phong = 0.0;
New->Phong_Size = 40.0;
New->Specular = 0.0;
New->Roughness = 1.0 / 0.05;
New->Reflection_Fresnel = false;
New->Reflection_Falloff = 1; /* Added by MBP 8/27/98 */
New->Diffuse = 0.6;
New->DiffuseBack = 0.0;
New->Brilliance = 1.0;
New->BrillianceOut = 1.0;
New->BrillianceAdjust = 1.0;
New->BrillianceAdjustRad = 1.0;
New->LommelSeeligerWeight = 0.0;
New->OrenNayarA = 1.0;
New->OrenNayarB = 0.0;
New->Phong = 0.0;
New->Phong_Size = 40.0;
New->Specular = 0.0;
New->Roughness = 1.0 / 0.05;

New->Crand = 0.0;

Expand Down
39 changes: 36 additions & 3 deletions source/core/material/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,32 @@ struct Texture_Struct : public Pattern_Struct
struct Finish_Struct
{
SNGL Diffuse, DiffuseBack, Brilliance, BrillianceOut, BrillianceAdjust, BrillianceAdjustRad;

/// How much of the diffuse contribution should be computed using the Lommel-Seeliger model.
///
/// By default, POV-Ray uses a Lambertian-based diffuse reflectivity model. While this model is useful for
/// comparatively smooth surfaces, rough surfaces are better simulated using other models, one of the simplest
/// being the Lommel-Seeliger model. In astronomy, a weighted average of the Lambertian and Lommel-Seeliger models
/// is frequently used.
SNGL LommelSeeligerWeight;

/// @name Oren-Nayar diffuse model parameters.
///
/// By default, POV-Ray uses a Lambertian-based diffuse reflectivity model. While this model is useful for
/// comparatively smooth surfaces, rough surfaces are better simulated using other models, one of which is the
/// (simplified) Oren-Nayar model, being a superset of the Lambertian model and governed by the following
/// parameters.
///
/// @{

/// Factor A of the simplified Oren-Nayar model, defaulting to 1.0 for the Lambertian model.
SNGL OrenNayarA;

/// Factor B of the simplified Oren-Nayar model, defaulting to 0.0 for the Lambertian model.
SNGL OrenNayarB;

/// @}

SNGL Specular, Roughness;
SNGL Phong, Phong_Size;
SNGL Irid, Irid_Film_Thickness, Irid_Turb;
Expand All @@ -129,9 +155,16 @@ struct Finish_Struct
SNGL Reflection_Falloff; // Added by MBP 8/27/98
bool Reflection_Fresnel;
bool Fresnel;
SNGL Reflect_Metallic; // MBP
int Conserve_Energy; // added by NK Dec 19 1999
bool UseSubsurface; // whether to use subsurface light transport
SNGL Reflect_Metallic; // MBP
int Conserve_Energy; // added by NK Dec 19 1999
bool UseSubsurface; // whether to use subsurface light transport

void SetOrenNayarSigma(double sigma)
{
double sigmaSqr = sigma*sigma;
OrenNayarA = 1.0 - 0.50 * sigmaSqr / (sigmaSqr + 0.57);
OrenNayarB = 0.45 * sigmaSqr / (sigmaSqr + 0.09);
}
};


Expand Down
31 changes: 24 additions & 7 deletions source/core/render/trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2373,19 +2373,37 @@ void Trace::ComputeShadowColour(const LightSource &lightsource, Intersection& is
void Trace::ComputeDiffuseColour(const FINISH *finish, const Vector3d& lightDirection, const Vector3d& eyeDirection, const Vector3d& layer_normal, MathColour& colour, const MathColour& light_colour,
const MathColour& layer_pigment_colour, double relativeIor, double attenuation, bool backside)
{
double cos_angle_of_incidence, intensity;
double cos_in, cos_out, intensity;
double diffuse = (backside? finish->DiffuseBack : finish->Diffuse) * finish->BrillianceAdjust;

if (diffuse <= 0.0)
return;

cos_angle_of_incidence = dot(layer_normal, lightDirection);
cos_in = dot(layer_normal, lightDirection);

// Brilliance is likely to be 1.0 (default value)
if(finish->Brilliance != 1.0)
intensity = pow(fabs(cos_angle_of_incidence), (double) finish->Brilliance);
intensity = pow(fabs(cos_in), (double) finish->Brilliance);
else
intensity = fabs(cos_angle_of_incidence);
intensity = fabs(cos_in);

if (finish->Fresnel || (finish->LommelSeeligerWeight != 0.0) || (finish->OrenNayarB != 0.0))
cos_out = -dot(layer_normal, eyeDirection);

if (finish->LommelSeeligerWeight != 0.0)
intensity *= (1.0 - finish->LommelSeeligerWeight + finish->LommelSeeligerWeight / (cos_in + cos_out));

if (finish->OrenNayarB != 0.0)
{
Vector3d projected_in = lightDirection - layer_normal * cos_in;
Vector3d projected_out = -eyeDirection - layer_normal * cos_out;
double cos_phi = dot(projected_in, projected_out);
double theta_in = acos(cos_in);
double theta_out = acos(cos_out);
double alpha = max(theta_in, theta_out);
double beta = min(theta_in, theta_out);
intensity *= (finish->OrenNayarA + finish->OrenNayarB*max(0.0,cos_phi)*sin(alpha)*tan(beta));
}

intensity *= diffuse * attenuation;

Expand All @@ -2395,9 +2413,8 @@ void Trace::ComputeDiffuseColour(const FINISH *finish, const Vector3d& lightDire
if (finish->Fresnel)
{
MathColour cs1, cs2;
ComputeFresnel(cs1, MathColour(0.0), MathColour(1.0), cos_angle_of_incidence, relativeIor);
cos_angle_of_incidence = -dot(layer_normal, eyeDirection);
ComputeFresnel(cs2, MathColour(0.0), MathColour(1.0), cos_angle_of_incidence, relativeIor);
ComputeFresnel(cs1, MathColour(0.0), MathColour(1.0), cos_in, relativeIor);
ComputeFresnel(cs2, MathColour(0.0), MathColour(1.0), cos_out, relativeIor);
colour += intensity * layer_pigment_colour * light_colour * cs1 * cs2;
}
else
Expand Down
4 changes: 4 additions & 0 deletions source/parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@ struct ExperimentalFlags
{
bool backsideIllumination : 1;
bool functionHf : 1;
bool lommelSeeliger : 1;
bool meshCamera : 1;
bool orenNayar : 1;
bool slopeAltitude : 1;
bool spline : 1;
bool subsurface : 1;
Expand All @@ -166,7 +168,9 @@ struct ExperimentalFlags
ExperimentalFlags() :
backsideIllumination(false),
functionHf(false),
lommelSeeliger(false),
meshCamera(false),
orenNayar(false),
slopeAltitude(false),
spline(false),
subsurface(false),
Expand Down
36 changes: 36 additions & 0 deletions source/parser/parser_materials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2371,6 +2371,18 @@ void Parser::Parse_Finish (FINISH **Finish_Ptr)
mExperimentalFlags.backsideIllumination = true;
END_CASE

CASE (LOMMEL_SEELIGER_TOKEN)
New->LommelSeeligerWeight = Parse_Float ();
mExperimentalFlags.lommelSeeliger = true;
END_CASE

CASE (OREN_NAYAR_TOKEN)
New->SetOrenNayarSigma(Parse_Float ());
mExperimentalFlags.orenNayar = true;
PossibleError("Parameterization of the Oren-Nayar diffuse model has not been finalized yet."
" Expect future versions of POV-Ray to render this scene differently without warning.");
END_CASE

CASE (REFLECTION_TOKEN)
{
bool found_second_color = false;
Expand Down Expand Up @@ -2598,6 +2610,30 @@ void Parser::Parse_Finish (FINISH **Finish_Ptr)
END_EXPECT /* End of finish_mods */
#endif

if ((New->OrenNayarA != 1.0) || (New->OrenNayarB != 0.0))
{
if (New->Fresnel)
PossibleError("Finish-level 'fresnel' keyword found in combination with the Oren-Nayar diffuse model."
" The interaction of these features has not been finalized yet, and is known to be bogus."
" Expect future versions of POV-Ray to render this scene differently without warning.");
if (diffuseAdjust)
PossibleError("'diffuse albedo' found in combination with the Oren-Nayar diffuse model."
" The interaction of these features has not been finalized yet."
" Expect future versions of POV-Ray to render this scene differently without warning.");
}

if (New->LommelSeeligerWeight != 0.0)
{
if (New->Fresnel)
PossibleError("Finish-level 'fresnel' keyword found in combination with the Lommel-Seeliger diffuse model."
" The interaction of these features has not been finalized yet, and is known to be bogus."
" Expect future versions of POV-Ray to render this scene differently without warning.");
if (diffuseAdjust)
PossibleError("'diffuse albedo' found in combination with the Lommel_Seeliger diffuse model."
" The interaction of these features has not been finalized yet."
" Expect future versions of POV-Ray to render this scene differently without warning.");
}

if ((sceneData->EffectiveLanguageVersion() >= 370) && ambientSet)
{
// As of version 3.7, use of "ambient" to model glowing materials is deprecated, and "emission" should be used
Expand Down
2 changes: 2 additions & 0 deletions source/parser/reservedwords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
{LOCAL_TOKEN, "local"},
{LOCATION_TOKEN, "location"},
{LOG_TOKEN, "log"},
{LOMMEL_SEELIGER_TOKEN, "lommel_seeliger"},
{LOOKS_LIKE_TOKEN, "looks_like"},
{LOOK_AT_TOKEN, "look_at"},
{LOW_ERROR_FACTOR_TOKEN, "low_error_factor" },
Expand Down Expand Up @@ -389,6 +390,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
{ON_TOKEN, "on"},
{OPEN_TOKEN, "open"},
{OPTIONAL_TOKEN, "optional"},
{OREN_NAYAR_TOKEN, "oren_nayar"},
{ORIENTATION_TOKEN, "orientation"},
{ORIENT_TOKEN,"orient"},
{ORTHOGRAPHIC_TOKEN, "orthographic"},
Expand Down
2 changes: 2 additions & 0 deletions source/parser/reservedwords.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ enum TOKEN_IDS
LEOPARD_TOKEN,
LIGHT_SOURCE_TOKEN,
LOCATION_TOKEN,
LOMMEL_SEELIGER_TOKEN,
LOOKS_LIKE_TOKEN,
LOOK_AT_TOKEN,
MANDEL_TOKEN,
Expand All @@ -269,6 +270,7 @@ enum TOKEN_IDS
ONCE_TOKEN,
ONION_TOKEN,
OPTIONAL_TOKEN,
OREN_NAYAR_TOKEN,
OVUS_TOKEN,
PERCENT_TOKEN,
PHASE_TOKEN,
Expand Down
2 changes: 1 addition & 1 deletion unix/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.7.1-alpha.8514084
3.7.1-alpha.8545805

0 comments on commit a419e30

Please sign in to comment.