Rasagar/Library/PackageCache/com.unity.render-pipelines.universal/Shaders/Nature/SpeedTree7Passes.hlsl

239 lines
8.8 KiB
HLSL
Raw Normal View History

2024-08-26 13:07:20 -07:00
#ifndef UNIVERSAL_SPEEDTREE7_PASSES_INCLUDED
#define UNIVERSAL_SPEEDTREE7_PASSES_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "SpeedTree7CommonPasses.hlsl"
void InitializeData(inout SpeedTreeVertexInput input, float lodValue)
{
float3 finalPosition = input.vertex.xyz;
#ifdef ENABLE_WIND
half windQuality = _WindQuality * _WindEnabled;
float3 rotatedWindVector, rotatedBranchAnchor;
if (windQuality <= WIND_QUALITY_NONE)
{
rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
}
else
{
// compute rotated wind parameters
rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)UNITY_MATRIX_M));
rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)UNITY_MATRIX_M)) * _ST_WindBranchAnchor.w;
}
#endif
#if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
// smooth LOD
#ifdef LOD_FADE_PERCENTAGE
finalPosition = lerp(finalPosition, input.texcoord1.xyz, lodValue);
#endif
// frond wind, if needed
#if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
if (windQuality == WIND_QUALITY_PALM)
finalPosition = RippleFrond(finalPosition, input.normal, input.texcoord.x, input.texcoord.y, input.texcoord2.x, input.texcoord2.y, input.texcoord2.z);
#endif
#elif defined(GEOM_TYPE_LEAF)
// remove anchor position
finalPosition -= input.texcoord1.xyz;
bool isFacingLeaf = input.color.a == 0;
if (isFacingLeaf)
{
#ifdef LOD_FADE_PERCENTAGE
finalPosition *= lerp(1.0, input.texcoord1.w, lodValue);
#endif
// face camera-facing leaf to camera
float offsetLen = length(finalPosition);
finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition
finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
}
else
{
#ifdef LOD_FADE_PERCENTAGE
float3 lodPosition = float3(input.texcoord1.w, input.texcoord3.x, input.texcoord3.y);
finalPosition = lerp(finalPosition, lodPosition, lodValue);
#endif
}
#ifdef ENABLE_WIND
// leaf wind
if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
{
float leafWindTrigOffset = input.texcoord1.x + input.texcoord1.y;
finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, input.texcoord2.w > 0.0, finalPosition, input.normal, input.texcoord2.x, float3(0,0,0), input.texcoord2.y, input.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
}
#endif
// move back out to anchor
finalPosition += input.texcoord1.xyz;
#endif
#ifdef ENABLE_WIND
float3 treePos = float3(UNITY_MATRIX_M[0].w, UNITY_MATRIX_M[1].w, UNITY_MATRIX_M[2].w);
#ifndef GEOM_TYPE_MESH
if (windQuality >= WIND_QUALITY_BETTER)
{
// branch wind (applies to all 3D geometry)
finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(input.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
}
#endif
// global wind
if (windQuality > WIND_QUALITY_NONE)
{
finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
}
#endif
input.vertex.xyz = finalPosition;
}
SpeedTreeVertexOutput SpeedTree7Vert(SpeedTreeVertexInput input)
{
SpeedTreeVertexOutput output = (SpeedTreeVertexOutput)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
// handle speedtree wind and lod
InitializeData(input, unity_LODFade.x);
#ifdef VERTEX_COLOR
output.color = _Color;
output.color.rgb *= input.color.r; // ambient occlusion factor
#endif
output.uvHueVariation.xy = input.texcoord.xy;
#ifdef EFFECT_HUE_VARIATION
half hueVariationAmount = frac(UNITY_MATRIX_M[0].w + UNITY_MATRIX_M[1].w + UNITY_MATRIX_M[2].w);
hueVariationAmount += frac(input.vertex.x + input.normal.y + input.normal.x) * 0.5 - 0.3;
output.uvHueVariation.z = saturate(hueVariationAmount * _HueVariation.a);
#endif
#ifdef GEOM_TYPE_BRANCH_DETAIL
// The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
output.detail.xy = input.texcoord2.xy;
output.detail.z = input.color.a == 0 ? input.texcoord2.z : 2.5; // stay out of Blend's .z range
#endif
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
half3 normalWS = TransformObjectToWorldNormal(input.normal);
half3 vertexLight = VertexLighting(vertexInput.positionWS, normalWS);
half fogFactor = 0;
#if !defined(_FOG_FRAGMENT)
fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
#endif
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS);
#ifdef EFFECT_BUMP
real sign = input.tangent.w * GetOddNegativeScale();
output.normalWS.xyz = normalWS;
output.tangentWS.xyz = TransformObjectToWorldDir(input.tangent.xyz);
output.bitangentWS.xyz = cross(output.normalWS.xyz, output.tangentWS.xyz) * sign;
// View dir packed in w.
output.normalWS.w = viewDirWS.x;
output.tangentWS.w = viewDirWS.y;
output.bitangentWS.w = viewDirWS.z;
#else
output.normalWS = normalWS;
output.viewDirWS = viewDirWS;
#endif
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
output.shadowCoord = GetShadowCoord(vertexInput);
#endif
output.positionWS = vertexInput.positionWS;
output.clipPos = vertexInput.positionCS;
OUTPUT_SH4(vertexInput.positionWS, output.normalWS.xyz, GetWorldSpaceNormalizeViewDir(vertexInput.positionWS), output.vertexSH, output.probeOcclusion);
return output;
}
SpeedTreeVertexDepthOutput SpeedTree7VertDepth(SpeedTreeVertexInput input)
{
SpeedTreeVertexDepthOutput output = (SpeedTreeVertexDepthOutput)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
// handle speedtree wind and lod
InitializeData(input, unity_LODFade.x);
output.uvHueVariation.xy = input.texcoord.xy;
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
output.viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS);
#ifdef SHADOW_CASTER
half3 normalWS = TransformObjectToWorldNormal(input.normal);
#if _CASTING_PUNCTUAL_LIGHT_SHADOW
float3 lightDirectionWS = normalize(_LightPosition - vertexInput.positionWS);
#else
float3 lightDirectionWS = _LightDirection;
#endif
output.clipPos = TransformWorldToHClip(ApplyShadowBias(vertexInput.positionWS, normalWS, lightDirectionWS));
#else
output.clipPos = vertexInput.positionCS;
#endif
return output;
}
SpeedTreeVertexDepthNormalOutput SpeedTree7VertDepthNormal(SpeedTreeVertexInput input)
{
SpeedTreeVertexDepthNormalOutput output = (SpeedTreeVertexDepthNormalOutput)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
// handle speedtree wind and lod
InitializeData(input, unity_LODFade.x);
output.uvHueVariation.xy = input.texcoord.xy;
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
half3 normalWS = TransformObjectToWorldNormal(input.normal);
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS);
#ifdef GEOM_TYPE_BRANCH_DETAIL
// The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
output.detail.xy = input.texcoord2.xy;
output.detail.z = input.color.a == 0 ? input.texcoord2.z : 2.5; // stay out of Blend's .z range
#endif
#ifdef EFFECT_BUMP
real sign = input.tangent.w * GetOddNegativeScale();
output.normalWS.xyz = normalWS;
output.tangentWS.xyz = TransformObjectToWorldDir(input.tangent.xyz);
output.bitangentWS.xyz = cross(output.normalWS.xyz, output.tangentWS.xyz) * sign;
// View dir packed in w.
output.normalWS.w = viewDirWS.x;
output.tangentWS.w = viewDirWS.y;
output.bitangentWS.w = viewDirWS.z;
#else
output.normalWS = normalWS;
output.viewDirWS = viewDirWS;
#endif
output.clipPos = vertexInput.positionCS;
return output;
}
#endif