Skip to content

Commit

Permalink
[SpeedTree] backport-2022.3: Fix camera facing leaf effect
Browse files Browse the repository at this point in the history
Backport of https://github.cds.internal.unity3d.com/unity/unity/pull/48921

This PR doesn't include SpeedTree9 changes as ST9 support is Unity6+.
It also doesn't include the SpeedTree shadergraph/subgraph improvements in the original PR to keep changes minimal and only fix the bugs.

| Shader | Leaf Facing | No-wind LOD Transition | 
| :-- | :-- |  :-- |
| BiRP | Fixed in PR | Already working |
| URP_hlsl | Fixed in PR | Already working |
| URP_sg | Already working for windy<br/>Fixed in PR no-wind | Fixed in PR |
| HDRP_sg | Already working for windy<br/>Fixed in PR no-wind | Fixed in PR |
  • Loading branch information
volkan-unity authored and Evergreen committed Aug 15, 2024
1 parent 3fae7bb commit cd0e347
Show file tree
Hide file tree
Showing 25 changed files with 2,217 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl"
#include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Nature/SpeedTreeCommon.hlsl"
#include "SpeedTreeUtility.hlsl"
#if defined(LOD_FADE_CROSSFADE)
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl"
Expand Down Expand Up @@ -96,8 +97,26 @@ struct SpeedTreeFragmentInput

void InitializeData(inout SpeedTreeVertexInput input, float lodValue)
{
#if defined(LOD_FADE_PERCENTAGE) && (!defined(LOD_FADE_CROSSFADE) && !defined(EFFECT_BILLBOARD))
#if !defined(EFFECT_BILLBOARD)
#if defined(LOD_FADE_PERCENTAGE) && (!defined(LOD_FADE_CROSSFADE))
input.vertex.xyz = lerp(input.vertex.xyz, input.texcoord2.xyz, lodValue);
#endif

// geometry type
float geometryType = (int) (input.texcoord3.w + 0.25);
bool leafTwo = false;
if (geometryType > GEOM_TYPE_FACINGLEAF)
{
geometryType -= 2;
leafTwo = true;
}

// leaf facing
if (geometryType == GEOM_TYPE_FACINGLEAF)
{
float3 anchor = float3(input.texcoord1.zw, input.texcoord2.w);
input.vertex.xyz = DoLeafFacing(input.vertex.xyz, anchor);
}
#endif

// wind
Expand All @@ -117,30 +136,14 @@ void InitializeData(inout SpeedTreeVertexInput input, float lodValue)
float3 windyPosition = input.vertex.xyz;

#ifndef EFFECT_BILLBOARD
// geometry type
float geometryType = (int)(input.texcoord3.w + 0.25);
bool leafTwo = false;
if (geometryType > GEOM_TYPE_FACINGLEAF)
{
geometryType -= 2;
leafTwo = true;
}

// leaves
if (geometryType > GEOM_TYPE_FROND)
{
// remove anchor position
float3 anchor = float3(input.texcoord1.zw, input.texcoord2.w);
windyPosition -= anchor;

if (geometryType == GEOM_TYPE_FACINGLEAF)
{
// face camera-facing leaf to camera
float offsetLen = length(windyPosition);
windyPosition = mul(windyPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * windyPosition
windyPosition = normalize(windyPosition) * offsetLen; // make sure the offset vector is still scaled
}


// leaf wind
#if defined(_WINDQUALITY_FAST) || defined(_WINDQUALITY_BETTER) || defined(_WINDQUALITY_BEST)
#ifdef _WINDQUALITY_BEST
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -802,23 +802,6 @@ float3 SpeedTreeWind(
{
float3 vReturnPos = vPos;

// ---------------------------------------------------------------------------------
// TODO: move this outside of this function as they have nothing to do with wind
// - ApplySmoothLODTransition()
// - DoLeafFacing()
// ---------------------------------------------------------------------------------
if (!bCrossfade && !bBillboard)
{
vReturnPos = ApplySmoothLODTransition(vPos, vTexcoord2.xyz);
}
bool leafTwo = false;
int geometryType = GetGeometryType(vTexcoord3, leafTwo);
if (leafTwo) // leaf facing is done regardless of wind
{
vReturnPos = DoLeafFacing(vReturnPos, vTexcoord1, vTexcoord2);
}
// ---------------------------------------------------------------------------------

// check wind enabled & data available
const float3 windVector = GetCBuffer_WindVector(bHistory).xyz;
float3 rotatedWindVector = TransformWorldToObjectDir(windVector);
Expand All @@ -829,7 +812,9 @@ float3 SpeedTreeWind(
return vReturnPos; // sanity check that wind data is available
}

// do wind
bool leafTwo = false;
int geometryType = GetGeometryType(vTexcoord3, leafTwo);

rotatedWindVector /= windLength;
float4x4 matObjectToWorld = GetObjectToWorldMatrix();
float3 treePos = GetAbsolutePositionWS(float3(matObjectToWorld[0].w, matObjectToWorld[1].w, matObjectToWorld[2].w));
Expand Down Expand Up @@ -872,7 +857,7 @@ float3 SpeedTreeWind(
float3 rotatedBranchAnchor = TransformWorldToObjectDir(windBranchAnchorHistory.xyz) * windBranchAnchorHistory.w;
vReturnPos = BranchWind(bDoPalmWind, vReturnPos, treePos, float4(vTexcoord0.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor, bHistory);
}

// global wind
vReturnPos = GlobalWind(vReturnPos, treePos, true, rotatedWindVector, globalWindTime, bHistory);
return vReturnPos;
Expand All @@ -882,12 +867,33 @@ float3 SpeedTreeWind(
// This version is used by ShaderGraph
void SpeedTreeWind_float(float3 vPos, float3 vNormal, float4 vTexcoord0, float4 vTexcoord1, float4 vTexcoord2, float4 vTexcoord3, int iWindQuality, bool bBillboard, bool bCrossfade, bool bHistory, out float3 outPos)
{
if (iWindQuality != ST_WIND_QUALITY_NONE)
outPos = vPos;

// determine geometry type
bool leafTwo = false;
int geometryType = GetGeometryType(vTexcoord3, leafTwo);

// apply 3D SpeedTree FX
if (!bBillboard)
{
outPos = SpeedTreeWind(vPos, vNormal, vTexcoord0, vTexcoord1, vTexcoord2, vTexcoord3, iWindQuality, bBillboard, bCrossfade, bHistory);
// lod transition
if (!bCrossfade)
{
outPos = ApplySmoothLODTransition(vPos, vTexcoord2.xyz);
}

// leaf facing
if (geometryType == ST_GEOM_TYPE_FACINGLEAF)
{
float3 anchor = float3(vTexcoord1.zw, vTexcoord2.w);
outPos = DoLeafFacing(outPos, anchor);
}
}
else
outPos = vPos;

// do wind
if (iWindQuality != ST_WIND_QUALITY_NONE)
{
outPos = SpeedTreeWind(outPos, vNormal, vTexcoord0, vTexcoord1, vTexcoord2, vTexcoord3, iWindQuality, bBillboard, bCrossfade, bHistory);
}
}
#endif // SPEEDTREE_WIND_INCLUDED
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#ifndef SPEEDTREE_COMMON_INCLUDED
#define SPEEDTREE_COMMON_INCLUDED

#define ST_GEOM_TYPE_BRANCH 0
#define ST_GEOM_TYPE_FROND 1
#define ST_GEOM_TYPE_LEAF 2
#define ST_GEOM_TYPE_BRANCH 0
#define ST_GEOM_TYPE_FROND 1
#define ST_GEOM_TYPE_LEAF 2
#define ST_GEOM_TYPE_FACINGLEAF 3

// @uv2 packs the object space position of the next LOD
Expand All @@ -14,19 +14,18 @@ float3 ApplySmoothLODTransition(float3 ObjectSpacePosition, float3 uv2)
return lerp(ObjectSpacePosition, uv2, unity_LODFade.x);
}

float3 DoLeafFacing(float3 vPos, float4 vTexcoord1, float4 vTexcoord2)
float3 DoLeafFacing(float3 vPos, float3 anchor)
{
float3 anchor = float3(vTexcoord1.zw, vTexcoord2.w);
float3 facingPosition = vPos - anchor;
float3 facingPosition = vPos - anchor;

// face camera-facing leaf to camera
float offsetLen = length(facingPosition);
facingPosition = float3(facingPosition.x, -facingPosition.z, facingPosition.y);
float4x4 itmv = transpose(mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V));
facingPosition = mul(facingPosition.xyz, (float3x3)itmv);
facingPosition = normalize(facingPosition) * offsetLen; // make sure the offset vector is still scaled
// face camera-facing leaf to camera
float offsetLen = length(facingPosition);
facingPosition = float3(facingPosition.x, -facingPosition.z, facingPosition.y);
float4x4 itmv = transpose(mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V));
facingPosition = mul(facingPosition.xyz, (float3x3)itmv);
facingPosition = normalize(facingPosition) * offsetLen; // make sure the offset vector is still scaled

return facingPosition + anchor;
return facingPosition + anchor;
}

int GetGeometryType(float4 uv3, out bool bLeafTwo)
Expand Down
Loading

0 comments on commit cd0e347

Please sign in to comment.