You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
8.7 KiB
238 lines
8.7 KiB
#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_SH(output.normalWS.xyz, output.vertexSH); |
|
|
|
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
|
|
|