Skip to content

Commit

Permalink
Add accurate_non_uniform_normal_scaling material option
Browse files Browse the repository at this point in the history
Fixes #373
  • Loading branch information
darksylinc committed Dec 31, 2024
1 parent 7a4b336 commit 3d68c1a
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Components/Hlms/Pbs/src/OgreHlmsPbs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,9 @@ namespace Ogre
setProperty( kNoTid, PbsProperty::FresnelWorkflow, fresnelWorkflow );
setProperty( kNoTid, PbsProperty::MetallicWorkflow, metallicWorkflow );

if( datablock->getAccurateNonUniformNormalScaling() )
setProperty( kNoTid, HlmsBaseProp::AccurateNonUniformNormalScaling, 1 );

if( datablock->getTwoSidedLighting() )
setProperty( kNoTid, PbsProperty::TwoSidedLighting, 1 );

Expand Down
1 change: 1 addition & 0 deletions Docs/2.0/JSON/PbsAllSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ including invalid combinations (i.e. having a Metallic texture and a Specular te
"blendblock" : "unique_name" ["unique_name", "unique_name_for_shadows"],
"alpha_test" : ["less" "less_equal" "equal" "not_equal" "greater_equal" "greater" "never" "always" "disabled", 0.5],
"shadow_const_bias" : 0.01,
"accurate_non_uniform_normal_scaling" : false,
"two_sided" : false,
"receive_shadows" : true,
"refraction_strength" : 0.2,
Expand Down
1 change: 1 addition & 0 deletions Docs/2.0/JSON/PbsExample.material.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"blendblock" : "unique_name",
"alpha_test" : ["disabled", 0.5],
"shadow_const_bias" : 0.01,
"accurate_non_uniform_normal_scaling" : false,
"two_sided" : false,
"receive_shadows" : true,

Expand Down
5 changes: 5 additions & 0 deletions Docs/src/manual/Scripts/HlmsPBSDatablockReference.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Reference Guide: HLMS PBS Datablock {#hlmspbsdatablockref}

# Common Datablock Parameters: {#dbCommonParameters}

## Parameter: accurate_non_uniform_normal_scaling {#dbParamAccurateNonUniformNormalScaling}
- See Ogre::HlmsDatablock::setAccurateNonUniformNormalScaling
- Value of type bool
- **DEFAULT=false**

## Parameter: alpha_test {#dbParamAlphaTest}
- Sets the alpha test to the given compare function
- Alpha_test value is type array:
Expand Down
1 change: 1 addition & 0 deletions OgreMain/include/OgreHlms.h
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,7 @@ namespace Ogre
static const IdString AlphaBlend;
static const IdString AlphaToCoverage;
static const IdString AlphaHash;
static const IdString AccurateNonUniformNormalScaling;
// Per material. Related with SsRefractionsAvailable
static const IdString ScreenSpaceRefractions;
static const IdString
Expand Down
44 changes: 44 additions & 0 deletions OgreMain/include/OgreHlmsDatablock.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ namespace Ogre

protected:
bool mIgnoreFlushRenderables;
bool mAccurateNonUniformNormalScaling;
bool mAlphaHashing;
uint8 mAlphaTestCmp; ///< @see CompareFunction
bool mAlphaTestShadowCasterOnly;
Expand Down Expand Up @@ -492,6 +493,49 @@ namespace Ogre
return mBlendblock[casterBlock];
}

/** When objects are scaled by non-uniform values, normals tend to get skewed or deformed
causing wrong lighting.
This setting enables the use of additional math in the vertex shader to ensure normals
are properly scaled in these situations.
Calling this function triggers a HlmsDatablock::flushRenderables.
@remark
This setting would make more sense to be per object (or ideally autodetect when scale
factor isn't uniform) but this is expensive to perform. Therefore the setting lives
in the material instead, which is the best next thing.
@par
@remark
Due to the way the math works, the normal isn't exactly the same even if there is no scaling
involved. This is particularly noticeable with normal-offset bias in directional lights
shadow mapping, as the shadow displaces a little bit.
@par
@remark
Non-uniform scaling is when the scale is not the same for all axes.
Examples of non-uniform scaling:
@code
node->setScale( 2.0f, 5.0f, 0.02f );
node->setScale( 1.0f, 5.0f, 1.0f );
@endcode
Examples of uniform scaling:
@code
node->setScale( 1.0f, 1.0f, 1.0f );
node->setScale( 3.0f, 3.0f, 3.0f );
@endcode
@par
@remark
For more info see:
- https://x.com/iquilezles/status/1866219178409316362
- https://www.shadertoy.com/view/3s33zj
- https://github.com/graphitemaster/normals_revisited
@param bAccurate
True to enable the additional math for correction.
False otherwise (default value).
*/
void setAccurateNonUniformNormalScaling( bool bAccurate );

bool getAccurateNonUniformNormalScaling() const { return mAccurateNonUniformNormalScaling; }

/** Uses a trick to *mimic* true Order Independent Transparency alpha blending.
The advantage of this method is that it is compatible with depth buffer writes
and is order independent.
Expand Down
2 changes: 2 additions & 0 deletions OgreMain/src/OgreHlms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ namespace Ogre
const IdString HlmsBaseProp::AlphaBlend = IdString( "hlms_alphablend" );
const IdString HlmsBaseProp::AlphaToCoverage = IdString( "hlms_alpha_to_coverage" );
const IdString HlmsBaseProp::AlphaHash = IdString( "hlms_alpha_hash" );
const IdString HlmsBaseProp::AccurateNonUniformNormalScaling =
IdString( "hlms_accurate_non_uniform_normal_scaling" );
const IdString HlmsBaseProp::ScreenSpaceRefractions = IdString( "hlms_screen_space_refractions" );
// We use a different convention because it's a really private property that ideally
// shouldn't be exposed to users.
Expand Down
9 changes: 9 additions & 0 deletions OgreMain/src/OgreHlmsDatablock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,15 @@ namespace Ogre
}
}
//-----------------------------------------------------------------------------------
void HlmsDatablock::setAccurateNonUniformNormalScaling( bool bAccurate )
{
if( mAccurateNonUniformNormalScaling != bAccurate )
{
mAccurateNonUniformNormalScaling = bAccurate;
flushRenderables();
}
}
//-----------------------------------------------------------------------------------
void HlmsDatablock::setAlphaHashing( bool bAlphaHashing )
{
if( mAlphaHashing != bAlphaHashing )
Expand Down
7 changes: 7 additions & 0 deletions OgreMain/src/OgreHlmsJson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ namespace Ogre
}
}

itor = json.FindMember( "accurate_non_uniform_normal_scaling" );
if( itor != json.MemberEnd() && itor->value.IsBool() )
datablock->setAccurateNonUniformNormalScaling( itor->value.GetBool() );

itor = json.FindMember( "alpha_test" );
if( itor != json.MemberEnd() && itor->value.IsArray() )
{
Expand Down Expand Up @@ -1054,6 +1058,9 @@ namespace Ogre
}
}

if( datablock->getAccurateNonUniformNormalScaling() )
outString += ",\n\t\t\t\"accurate_non_uniform_normal_scaling\" : true";

if( datablock->getAlphaTest() != CMPF_ALWAYS_PASS )
{
outString += ",\n\t\t\t\"alpha_test\" : ";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
@insertpiece( DeclShadowMapMacros )
@insertpiece( DeclAtmosphereNprSkyFuncs )

@property( accurate_non_uniform_scaled_normals )
@property( hlms_accurate_non_uniform_normal_scaling )
// Computes transpose( adjugate( m ) )
// See:
// https://x.com/iquilezles/status/1866219178409316362
Expand Down

0 comments on commit 3d68c1a

Please sign in to comment.