testss
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
Shader "Universal Render Pipeline/Nature/SpeedTree7"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Color("Main Color", Color) = (1,1,1,1)
|
||||
_HueVariation("Hue Variation", Color) = (1.0,0.5,0.0,0.1)
|
||||
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
|
||||
_DetailTex("Detail", 2D) = "black" {}
|
||||
_BumpMap("Normal Map", 2D) = "bump" {}
|
||||
_Cutoff("Alpha Cutoff", Range(0,1)) = 0.333
|
||||
[MaterialEnum(Off,0,Front,1,Back,2)] _Cull("Cull", Int) = 2
|
||||
[MaterialEnum(None,0,Fastest,1,Fast,2,Better,3,Best,4,Palm,5)] _WindQuality("Wind Quality", Range(0,5)) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue" = "Geometry"
|
||||
"IgnoreProjector" = "True"
|
||||
"RenderType" = "Opaque"
|
||||
"DisableBatching" = "LODFading"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
"UniversalMaterialType" = "SimpleLit"
|
||||
}
|
||||
LOD 400
|
||||
Cull [_Cull]
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "ForwardLit"
|
||||
Tags { "LightMode" = "UniversalForward" }
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree7Vert
|
||||
#pragma fragment SpeedTree7Frag
|
||||
|
||||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
|
||||
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
|
||||
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
|
||||
#pragma multi_compile _ _SHADOWS_SOFT
|
||||
#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile_fog
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
#pragma shader_feature_local EFFECT_HUE_VARIATION
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define VERTEX_COLOR
|
||||
|
||||
#include "SpeedTree7Input.hlsl"
|
||||
#include "SpeedTree7Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "SceneSelectionPass"
|
||||
Tags{"LightMode" = "SceneSelectionPass"}
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree7VertDepth
|
||||
#pragma fragment SpeedTree7FragDepth
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
#define SCENESELECTIONPASS
|
||||
|
||||
#include "SpeedTree7Input.hlsl"
|
||||
#include "SpeedTree7Passes.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "ShadowCaster"
|
||||
Tags{"LightMode" = "ShadowCaster"}
|
||||
|
||||
ColorMask 0
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree7VertDepth
|
||||
#pragma fragment SpeedTree7FragDepth
|
||||
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
#define SHADOW_CASTER
|
||||
|
||||
// -------------------------------------
|
||||
// Universal Pipeline keywords
|
||||
|
||||
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
|
||||
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
|
||||
|
||||
#include "SpeedTree7Input.hlsl"
|
||||
#include "SpeedTree7Passes.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "GBuffer"
|
||||
Tags{"LightMode" = "UniversalGBuffer"}
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex SpeedTree7Vert
|
||||
#pragma fragment SpeedTree7Frag
|
||||
|
||||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
|
||||
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
|
||||
//#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
|
||||
#pragma multi_compile _ _SHADOWS_SOFT
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
#pragma shader_feature_local EFFECT_HUE_VARIATION
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define VERTEX_COLOR
|
||||
#define GBUFFER
|
||||
|
||||
#include "SpeedTree7Input.hlsl"
|
||||
#include "SpeedTree7Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "DepthOnly"
|
||||
Tags{"LightMode" = "DepthOnly"}
|
||||
|
||||
ColorMask 0
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree7VertDepth
|
||||
#pragma fragment SpeedTree7FragDepth
|
||||
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
|
||||
#include "SpeedTree7Input.hlsl"
|
||||
#include "SpeedTree7Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
// This pass is used when drawing to a _CameraNormalsTexture texture
|
||||
Pass
|
||||
{
|
||||
Name "DepthNormals"
|
||||
Tags{"LightMode" = "DepthNormals"}
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex SpeedTree7VertDepthNormal
|
||||
#pragma fragment SpeedTree7FragDepthNormal
|
||||
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
|
||||
#define ENABLE_WIND
|
||||
|
||||
#include "SpeedTree7Input.hlsl"
|
||||
#include "SpeedTree7Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
Dependency "BillboardShader" = "Universal Render Pipeline/Nature/SpeedTree7 Billboard"
|
||||
CustomEditor "SpeedTreeMaterialInspector"
|
||||
}
|
@@ -0,0 +1,134 @@
|
||||
Shader "Universal Render Pipeline/Nature/SpeedTree7 Billboard"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Color("Main Color", Color) = (1,1,1,1)
|
||||
_HueVariation("Hue Variation", Color) = (1.0,0.5,0.0,0.1)
|
||||
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
|
||||
_BumpMap("Normal Map", 2D) = "bump" {}
|
||||
_Cutoff("Alpha Cutoff", Range(0,1)) = 0.333
|
||||
[MaterialEnum(None,0,Fastest,1)] _WindQuality("Wind Quality", Range(0,1)) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue" = "AlphaTest"
|
||||
"IgnoreProjector" = "True"
|
||||
"RenderType" = "TransparentCutout"
|
||||
"DisableBatching" = "LODFading"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
"UniversalMaterialType" = "SimpleLit"
|
||||
}
|
||||
LOD 400
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "ForwardLit"
|
||||
Tags { "LightMode" = "UniversalForward" }
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree7Vert
|
||||
#pragma fragment SpeedTree7Frag
|
||||
|
||||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
|
||||
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
|
||||
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
|
||||
#pragma multi_compile _ _SHADOWS_SOFT
|
||||
#pragma multi_compile __ BILLBOARD_FACE_CAMERA_POS
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
#pragma multi_compile_fog
|
||||
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
#pragma shader_feature_local EFFECT_HUE_VARIATION
|
||||
|
||||
#define ENABLE_WIND
|
||||
|
||||
#include "SpeedTree7BillboardInput.hlsl"
|
||||
#include "SpeedTree7BillboardPasses.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "ShadowCaster"
|
||||
Tags{"LightMode" = "ShadowCaster"}
|
||||
|
||||
ColorMask 0
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree7VertDepth
|
||||
#pragma fragment SpeedTree7FragDepth
|
||||
|
||||
#pragma multi_compile __ BILLBOARD_FACE_CAMERA_POS
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
#define SHADOW_CASTER
|
||||
|
||||
#include "SpeedTree7BillboardInput.hlsl"
|
||||
#include "SpeedTree7BillboardPasses.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "GBuffer"
|
||||
Tags{"LightMode" = "UniversalGBuffer"}
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex SpeedTree7Vert
|
||||
#pragma fragment SpeedTree7Frag
|
||||
|
||||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
|
||||
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
|
||||
//#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
|
||||
#pragma multi_compile _ _SHADOWS_SOFT
|
||||
#pragma multi_compile __ BILLBOARD_FACE_CAMERA_POS
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
|
||||
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
#pragma shader_feature_local EFFECT_HUE_VARIATION
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define GBUFFER
|
||||
|
||||
#include "SpeedTree7BillboardInput.hlsl"
|
||||
#include "SpeedTree7BillboardPasses.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "DepthOnly"
|
||||
Tags{"LightMode" = "DepthOnly"}
|
||||
|
||||
ColorMask 0
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree7VertDepth
|
||||
#pragma fragment SpeedTree7FragDepth
|
||||
|
||||
#pragma multi_compile __ BILLBOARD_FACE_CAMERA_POS
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
|
||||
#include "SpeedTree7BillboardInput.hlsl"
|
||||
#include "SpeedTree7BillboardPasses.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
#ifndef UNIVERSAL_SPEEDTREE7BILLBOARD_INPUT_INCLUDED
|
||||
#define UNIVERSAL_SPEEDTREE7BILLBOARD_INPUT_INCLUDED
|
||||
|
||||
#define SPEEDTREE_PI 3.14159265359
|
||||
|
||||
#define SPEEDTREE_ALPHATEST
|
||||
half _Cutoff;
|
||||
|
||||
#include "SpeedTree7CommonInput.hlsl"
|
||||
|
||||
CBUFFER_START(UnityBillboardPerCamera)
|
||||
float3 unity_BillboardNormal;
|
||||
float3 unity_BillboardTangent;
|
||||
float4 unity_BillboardCameraParams;
|
||||
#define unity_BillboardCameraPosition (unity_BillboardCameraParams.xyz)
|
||||
#define unity_BillboardCameraXZAngle (unity_BillboardCameraParams.w)
|
||||
CBUFFER_END
|
||||
|
||||
CBUFFER_START(UnityBillboardPerBatch)
|
||||
float4 unity_BillboardInfo; // x: num of billboard slices; y: 1.0f / (delta angle between slices)
|
||||
float4 unity_BillboardSize; // x: width; y: height; z: bottom
|
||||
float4 unity_BillboardImageTexCoords[16];
|
||||
CBUFFER_END
|
||||
|
||||
#define _Surface 0.0 // Speed Trees are always opaque
|
||||
|
||||
#endif
|
@@ -0,0 +1,138 @@
|
||||
#ifndef UNIVERSAL_SPEEDTREE7BILLBOARD_PASSES_INCLUDED
|
||||
#define UNIVERSAL_SPEEDTREE7BILLBOARD_PASSES_INCLUDED
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
#include "SpeedTree7CommonPasses.hlsl"
|
||||
|
||||
void InitializeData(inout SpeedTreeVertexInput input, out half2 outUV, out half outHueVariation)
|
||||
{
|
||||
// assume no scaling & rotation
|
||||
float3 worldPos = input.vertex.xyz + float3(UNITY_MATRIX_M[0].w, UNITY_MATRIX_M[1].w, UNITY_MATRIX_M[2].w);
|
||||
|
||||
#ifdef BILLBOARD_FACE_CAMERA_POS
|
||||
float3 eyeVec = normalize(unity_BillboardCameraPosition - worldPos);
|
||||
float3 billboardTangent = normalize(float3(-eyeVec.z, 0, eyeVec.x)); // cross(eyeVec, {0,1,0})
|
||||
float3 billboardNormal = float3(billboardTangent.z, 0, -billboardTangent.x); // cross({0,1,0},billboardTangent)
|
||||
float angle = atan2(billboardNormal.z, billboardNormal.x); // signed angle between billboardNormal to {0,0,1}
|
||||
angle += angle < 0 ? 2 * SPEEDTREE_PI : 0;
|
||||
#else
|
||||
float3 billboardTangent = unity_BillboardTangent;
|
||||
float3 billboardNormal = unity_BillboardNormal;
|
||||
float angle = unity_BillboardCameraXZAngle;
|
||||
#endif
|
||||
|
||||
float widthScale = input.texcoord1.x;
|
||||
float heightScale = input.texcoord1.y;
|
||||
float rotation = input.texcoord1.z;
|
||||
|
||||
float2 percent = input.texcoord.xy;
|
||||
float3 billboardPos = (percent.x - 0.5f) * unity_BillboardSize.x * widthScale * billboardTangent;
|
||||
billboardPos.y += (percent.y * unity_BillboardSize.y + unity_BillboardSize.z) * heightScale;
|
||||
|
||||
#ifdef ENABLE_WIND
|
||||
if (_WindQuality * _WindEnabled > 0)
|
||||
{
|
||||
billboardPos = GlobalWind(billboardPos, worldPos, true, _ST_WindVector.xyz, input.texcoord1.w);
|
||||
}
|
||||
#endif
|
||||
|
||||
input.vertex.xyz += billboardPos;
|
||||
input.vertex.w = 1.0f;
|
||||
input.normal = billboardNormal.xyz;
|
||||
input.tangent = float4(billboardTangent.xyz, -1);
|
||||
|
||||
float slices = unity_BillboardInfo.x;
|
||||
float invDelta = unity_BillboardInfo.y;
|
||||
angle += rotation;
|
||||
|
||||
float imageIndex = fmod(floor(angle * invDelta + 0.5f), slices);
|
||||
float4 imageTexCoords = unity_BillboardImageTexCoords[imageIndex];
|
||||
if (imageTexCoords.w < 0)
|
||||
{
|
||||
outUV = imageTexCoords.xy - imageTexCoords.zw * percent.yx;
|
||||
}
|
||||
else
|
||||
{
|
||||
outUV = imageTexCoords.xy + imageTexCoords.zw * percent;
|
||||
}
|
||||
|
||||
#ifdef EFFECT_HUE_VARIATION
|
||||
float hueVariationAmount = frac(worldPos.x + worldPos.y + worldPos.z);
|
||||
outHueVariation = saturate(hueVariationAmount * _HueVariation.a);
|
||||
#else
|
||||
outHueVariation = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
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, output.uvHueVariation.xy, output.uvHueVariation.z);
|
||||
|
||||
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
|
||||
half3 normalWS = input.normal; // Already calculated in world space. Can probably get rid of the world space transform in GetVertexPositionInputs too.
|
||||
|
||||
half3 vertexLight = VertexLighting(vertexInput.positionWS, normalWS);
|
||||
half fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
|
||||
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
|
||||
|
||||
half3 viewDirWS = GetWorldSpaceViewDir(vertexInput.positionWS);
|
||||
#ifdef EFFECT_BUMP
|
||||
real sign = input.tangent.w * GetOddNegativeScale();
|
||||
output.normalWS.xyz = TransformObjectToWorldNormal(input.normal);
|
||||
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.xyz = TransformObjectToWorldNormal(input.normal);
|
||||
output.viewDirWS = viewDirWS;
|
||||
#endif
|
||||
|
||||
output.positionWS = vertexInput.positionWS;
|
||||
|
||||
output.clipPos = vertexInput.positionCS;
|
||||
|
||||
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
||||
output.shadowCoord = GetShadowCoord(vertexInput);
|
||||
#endif
|
||||
|
||||
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, output.uvHueVariation.xy, output.uvHueVariation.z);
|
||||
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,40 @@
|
||||
#ifndef UNIVERSAL_SPEEDTREE7COMMON_INPUT_INCLUDED
|
||||
#define UNIVERSAL_SPEEDTREE7COMMON_INPUT_INCLUDED
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
#define _NORMALMAP
|
||||
#endif
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
|
||||
|
||||
#ifdef ENABLE_WIND
|
||||
#define WIND_QUALITY_NONE 0
|
||||
#define WIND_QUALITY_FASTEST 1
|
||||
#define WIND_QUALITY_FAST 2
|
||||
#define WIND_QUALITY_BETTER 3
|
||||
#define WIND_QUALITY_BEST 4
|
||||
#define WIND_QUALITY_PALM 5
|
||||
|
||||
uniform half _WindQuality;
|
||||
uniform half _WindEnabled;
|
||||
|
||||
#include "SpeedTreeWind.cginc"
|
||||
#endif
|
||||
|
||||
TEXTURE2D(_MainTex);
|
||||
SAMPLER(sampler_MainTex);
|
||||
|
||||
#ifdef EFFECT_HUE_VARIATION
|
||||
half4 _HueVariation;
|
||||
#endif
|
||||
|
||||
half4 _Color;
|
||||
|
||||
// Shadow Casting Light geometric parameters. These variables are used when applying the shadow Normal Bias and are set by UnityEngine.Rendering.Universal.ShadowUtils.SetupShadowCasterConstantBuffer in com.unity.render-pipelines.universal/Runtime/ShadowUtils.cs
|
||||
// For Directional lights, _LightDirection is used when applying shadow Normal Bias.
|
||||
// For Spot lights and Point lights, _LightPosition is used to compute the actual light direction because it is different at each shadow caster geometry vertex.
|
||||
float3 _LightDirection;
|
||||
float3 _LightPosition;
|
||||
|
||||
#endif
|
@@ -0,0 +1,244 @@
|
||||
#ifndef UNIVERSAL_SPEEDTREE7COMMON_PASSES_INCLUDED
|
||||
#define UNIVERSAL_SPEEDTREE7COMMON_PASSES_INCLUDED
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl"
|
||||
|
||||
struct SpeedTreeVertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
float4 tangent : TANGENT;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
float4 texcoord1 : TEXCOORD1;
|
||||
float4 texcoord2 : TEXCOORD2;
|
||||
float2 texcoord3 : TEXCOORD3;
|
||||
half4 color : COLOR;
|
||||
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct SpeedTreeVertexOutput
|
||||
{
|
||||
#ifdef VERTEX_COLOR
|
||||
half4 color : COLOR;
|
||||
#endif
|
||||
|
||||
half3 uvHueVariation : TEXCOORD0;
|
||||
|
||||
#ifdef GEOM_TYPE_BRANCH_DETAIL
|
||||
half3 detail : TEXCOORD1;
|
||||
#endif
|
||||
|
||||
half4 fogFactorAndVertexLight : TEXCOORD2; // x: fogFactor, yzw: vertex light
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
half4 normalWS : TEXCOORD3; // xyz: normal, w: viewDir.x
|
||||
half4 tangentWS : TEXCOORD4; // xyz: tangent, w: viewDir.y
|
||||
half4 bitangentWS : TEXCOORD5; // xyz: bitangent, w: viewDir.z
|
||||
#else
|
||||
half3 normalWS : TEXCOORD3;
|
||||
half3 viewDirWS : TEXCOORD4;
|
||||
#endif
|
||||
|
||||
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
||||
float4 shadowCoord : TEXCOORD6;
|
||||
#endif
|
||||
|
||||
float3 positionWS : TEXCOORD7;
|
||||
DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 8);
|
||||
float4 clipPos : SV_POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
struct SpeedTreeVertexDepthOutput
|
||||
{
|
||||
half3 uvHueVariation : TEXCOORD0;
|
||||
float4 clipPos : SV_POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
struct SpeedTreeVertexDepthNormalOutput
|
||||
{
|
||||
half3 uvHueVariation : TEXCOORD0;
|
||||
float4 clipPos : SV_POSITION;
|
||||
|
||||
#ifdef GEOM_TYPE_BRANCH_DETAIL
|
||||
half3 detail : TEXCOORD1;
|
||||
#endif
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
half4 normalWS : TEXCOORD2; // xyz: normal, w: viewDir.x
|
||||
half4 tangentWS : TEXCOORD3; // xyz: tangent, w: viewDir.y
|
||||
half4 bitangentWS : TEXCOORD4; // xyz: bitangent, w: viewDir.z
|
||||
#else
|
||||
half3 normalWS : TEXCOORD2;
|
||||
half3 viewDirWS : TEXCOORD3;
|
||||
#endif
|
||||
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
void InitializeInputData(SpeedTreeVertexOutput input, half3 normalTS, out InputData inputData)
|
||||
{
|
||||
inputData.positionWS = input.positionWS.xyz;
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
inputData.normalWS = TransformTangentToWorld(normalTS, half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz));
|
||||
inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
|
||||
inputData.viewDirectionWS = half3(input.normalWS.w, input.tangentWS.w, input.bitangentWS.w);
|
||||
#else
|
||||
inputData.normalWS = NormalizeNormalPerPixel(input.normalWS);
|
||||
inputData.viewDirectionWS = input.viewDirWS;
|
||||
#endif
|
||||
|
||||
#if SHADER_HINT_NICE_QUALITY
|
||||
inputData.viewDirectionWS = SafeNormalize(inputData.viewDirectionWS);
|
||||
#endif
|
||||
|
||||
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
||||
inputData.shadowCoord = input.shadowCoord;
|
||||
#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
|
||||
inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
|
||||
#else
|
||||
inputData.shadowCoord = float4(0, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
inputData.fogCoord = input.fogFactorAndVertexLight.x;
|
||||
inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
|
||||
inputData.bakedGI = SAMPLE_GI(input.lightmapUV, input.vertexSH, inputData.normalWS);
|
||||
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.clipPos);
|
||||
inputData.shadowMask = half4(1, 1, 1, 1); // No GI currently.
|
||||
}
|
||||
|
||||
#ifdef GBUFFER
|
||||
FragmentOutput SpeedTree7Frag(SpeedTreeVertexOutput input)
|
||||
#else
|
||||
half4 SpeedTree7Frag(SpeedTreeVertexOutput input) : SV_Target
|
||||
#endif
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(input);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
||||
|
||||
#if !defined(SHADER_QUALITY_LOW)
|
||||
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
|
||||
LODDitheringTransition(input.clipPos.xy, unity_LODFade.x);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
half2 uv = input.uvHueVariation.xy;
|
||||
half4 diffuse = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex));
|
||||
diffuse.a *= _Color.a;
|
||||
|
||||
#ifdef SPEEDTREE_ALPHATEST
|
||||
clip(diffuse.a - _Cutoff);
|
||||
#endif
|
||||
|
||||
half3 diffuseColor = diffuse.rgb;
|
||||
|
||||
#ifdef GEOM_TYPE_BRANCH_DETAIL
|
||||
half4 detailColor = tex2D(_DetailTex, input.detail.xy);
|
||||
diffuseColor.rgb = lerp(diffuseColor.rgb, detailColor.rgb, input.detail.z < 2.0f ? saturate(input.detail.z) : detailColor.a);
|
||||
#endif
|
||||
|
||||
#ifdef EFFECT_HUE_VARIATION
|
||||
half3 shiftedColor = lerp(diffuseColor.rgb, _HueVariation.rgb, input.uvHueVariation.z);
|
||||
half maxBase = max(diffuseColor.r, max(diffuseColor.g, diffuseColor.b));
|
||||
half newMaxBase = max(shiftedColor.r, max(shiftedColor.g, shiftedColor.b));
|
||||
maxBase /= newMaxBase;
|
||||
maxBase = maxBase * 0.5f + 0.5f;
|
||||
// preserve vibrance
|
||||
shiftedColor.rgb *= maxBase;
|
||||
diffuseColor.rgb = saturate(shiftedColor);
|
||||
#endif
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
half3 normalTs = SampleNormal(uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap));
|
||||
#ifdef GEOM_TYPE_BRANCH_DETAIL
|
||||
half3 detailNormal = SampleNormal(input.detail.xy, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap));
|
||||
normalTs = lerp(normalTs, detailNormal, input.detail.z < 2.0f ? saturate(input.detail.z) : detailColor.a);
|
||||
#endif
|
||||
#else
|
||||
half3 normalTs = half3(0, 0, 1);
|
||||
#endif
|
||||
|
||||
InputData inputData;
|
||||
InitializeInputData(input, normalTs, inputData);
|
||||
|
||||
#ifdef VERTEX_COLOR
|
||||
diffuseColor.rgb *= input.color.rgb;
|
||||
#else
|
||||
diffuseColor.rgb *= _Color.rgb;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GBUFFER
|
||||
half4 color = half4(inputData.bakedGI * diffuseColor.rgb, diffuse.a);
|
||||
SurfaceData surfaceData;
|
||||
surfaceData.smoothness = 0;
|
||||
surfaceData.albedo = diffuseColor.rgb;
|
||||
surfaceData.specular = half3(0, 0, 0);
|
||||
return SurfaceDataToGbuffer(surfaceData, inputData, color.rgb, kLightingSimpleLit);
|
||||
#else
|
||||
half4 color = UniversalFragmentBlinnPhong(inputData, diffuseColor.rgb, half4(0, 0, 0, 0), 0, 0, diffuse.a);
|
||||
color.rgb = MixFog(color.rgb, inputData.fogCoord);
|
||||
color.a = OutputAlpha(color.a, _Surface);
|
||||
return color;
|
||||
#endif
|
||||
}
|
||||
|
||||
half4 SpeedTree7FragDepth(SpeedTreeVertexDepthOutput input) : SV_Target
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(input);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
||||
|
||||
#if !defined(SHADER_QUALITY_LOW)
|
||||
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
|
||||
LODDitheringTransition(input.clipPos.xy, unity_LODFade.x);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
half2 uv = input.uvHueVariation.xy;
|
||||
half4 diffuse = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex));
|
||||
diffuse.a *= _Color.a;
|
||||
|
||||
#ifdef SPEEDTREE_ALPHATEST
|
||||
clip(diffuse.a - _Cutoff);
|
||||
#endif
|
||||
|
||||
#if defined(SCENESELECTIONPASS)
|
||||
// We use depth prepass for scene selection in the editor, this code allow to output the outline correctly
|
||||
return half4(_ObjectId, _PassValue, 1.0, 1.0);
|
||||
#else
|
||||
return half4(0, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
half4 SpeedTree7FragDepthNormal(SpeedTreeVertexDepthNormalOutput input) : SV_Target
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(input);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
||||
|
||||
#if !defined(SHADER_QUALITY_LOW)
|
||||
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
|
||||
LODDitheringTransition(input.clipPos.xy, unity_LODFade.x);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
half2 uv = input.uvHueVariation.xy;
|
||||
half4 diffuse = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex));
|
||||
diffuse.a *= _Color.a;
|
||||
|
||||
#ifdef SPEEDTREE_ALPHATEST
|
||||
clip(diffuse.a - _Cutoff);
|
||||
#endif
|
||||
|
||||
float3 normalWS = input.normalWS;
|
||||
return float4(PackNormalOctRectEncode(TransformWorldToViewDir(normalWS, true)), 0.0, 0.0);
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,29 @@
|
||||
#ifndef UNIVERSAL_SPEEDTREE7_INPUT_INCLUDED
|
||||
#define UNIVERSAL_SPEEDTREE7_INPUT_INCLUDED
|
||||
|
||||
#define SPEEDTREE_Y_UP
|
||||
|
||||
#ifdef GEOM_TYPE_BRANCH_DETAIL
|
||||
#define GEOM_TYPE_BRANCH
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(GEOM_TYPE_FROND) || defined(GEOM_TYPE_LEAF) || defined(GEOM_TYPE_FACING_LEAF)
|
||||
#define SPEEDTREE_ALPHATEST
|
||||
half _Cutoff;
|
||||
#endif
|
||||
|
||||
#ifdef SCENESELECTIONPASS
|
||||
int _ObjectId;
|
||||
int _PassValue;
|
||||
#endif
|
||||
|
||||
#include "SpeedTree7CommonInput.hlsl"
|
||||
|
||||
#ifdef GEOM_TYPE_BRANCH_DETAIL
|
||||
sampler2D _DetailTex;
|
||||
#endif
|
||||
|
||||
#define _Surface 0.0 // Speed Trees are always opaque
|
||||
|
||||
#endif
|
@@ -0,0 +1,231 @@
|
||||
#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 = ComputeFogFactor(vertexInput.positionCS.z);
|
||||
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
|
||||
|
||||
half3 viewDirWS = GetWorldSpaceViewDir(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);
|
||||
|
||||
#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 = GetWorldSpaceViewDir(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;
|
||||
#endif
|
||||
|
||||
output.clipPos = vertexInput.positionCS;
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,244 @@
|
||||
Shader "Universal Render Pipeline/Nature/SpeedTree8"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Base (RGB) Transparency (A)", 2D) = "white" {}
|
||||
_Color ("Color", Color) = (1,1,1,1)
|
||||
|
||||
[Toggle(EFFECT_HUE_VARIATION)] _HueVariationKwToggle("Hue Variation", Float) = 0
|
||||
_HueVariationColor ("Hue Variation Color", Color) = (1.0,0.5,0.0,0.1)
|
||||
|
||||
[Toggle(EFFECT_BUMP)] _NormalMapKwToggle("Normal Mapping", Float) = 0
|
||||
_BumpMap("Normal Map", 2D) = "bump" {}
|
||||
|
||||
_ExtraTex ("Smoothness (R), Metallic (G), AO (B)", 2D) = "(0.5, 0.0, 1.0)" {}
|
||||
_Glossiness ("Smoothness", Range(0.0, 1.0)) = 0.5
|
||||
_Metallic ("Metallic", Range(0.0, 1.0)) = 0.0
|
||||
|
||||
[Toggle(EFFECT_SUBSURFACE)] _SubsurfaceKwToggle("Subsurface", Float) = 0
|
||||
_SubsurfaceTex ("Subsurface (RGB)", 2D) = "white" {}
|
||||
_SubsurfaceColor ("Subsurface Color", Color) = (1,1,1,1)
|
||||
_SubsurfaceIndirect ("Subsurface Indirect", Range(0.0, 1.0)) = 0.25
|
||||
|
||||
[Toggle(EFFECT_BILLBOARD)] _BillboardKwToggle("Billboard", Float) = 0
|
||||
_BillboardShadowFade ("Billboard Shadow Fade", Range(0.0, 1.0)) = 0.5
|
||||
|
||||
[Enum(No,2,Yes,0)] _TwoSided ("Two Sided", Int) = 2 // enum matches cull mode
|
||||
[KeywordEnum(None,Fastest,Fast,Better,Best,Palm)] _WindQuality ("Wind Quality", Range(0,5)) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue"="AlphaTest"
|
||||
"IgnoreProjector"="True"
|
||||
"RenderType"="TransparentCutout"
|
||||
"DisableBatching"="LODFading"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
"UniversalMaterialType" = "Lit"
|
||||
}
|
||||
LOD 400
|
||||
Cull [_TwoSided]
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "ForwardLit"
|
||||
Tags { "LightMode" = "UniversalForward" }
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree8Vert
|
||||
#pragma fragment SpeedTree8Frag
|
||||
|
||||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
|
||||
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
|
||||
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
|
||||
#pragma multi_compile _ _SHADOWS_SOFT
|
||||
#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
#pragma multi_compile_fog
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local _WINDQUALITY_NONE _WINDQUALITY_FASTEST _WINDQUALITY_FAST _WINDQUALITY_BETTER _WINDQUALITY_BEST _WINDQUALITY_PALM
|
||||
#pragma shader_feature_local EFFECT_BILLBOARD
|
||||
#pragma shader_feature_local EFFECT_HUE_VARIATION
|
||||
//#pragma shader_feature_local EFFECT_SUBSURFACE // GI dependent.
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
#pragma shader_feature_local EFFECT_EXTRA_TEX
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define EFFECT_BACKSIDE_NORMALS
|
||||
|
||||
#include "SpeedTree8Input.hlsl"
|
||||
#include "SpeedTree8Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "SceneSelectionPass"
|
||||
Tags{"LightMode" = "SceneSelectionPass"}
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree8VertDepth
|
||||
#pragma fragment SpeedTree8FragDepth
|
||||
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local _WINDQUALITY_NONE _WINDQUALITY_FASTEST _WINDQUALITY_FAST _WINDQUALITY_BETTER _WINDQUALITY_BEST _WINDQUALITY_PALM
|
||||
#pragma shader_feature_local EFFECT_BILLBOARD
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
#define SCENESELECTIONPASS
|
||||
|
||||
#include "SpeedTree8Input.hlsl"
|
||||
#include "SpeedTree8Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "GBuffer"
|
||||
Tags{"LightMode" = "UniversalGBuffer"}
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma exclude_renderers gles
|
||||
#pragma vertex SpeedTree8Vert
|
||||
#pragma fragment SpeedTree8Frag
|
||||
|
||||
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
|
||||
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
|
||||
//#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
|
||||
#pragma multi_compile _ _SHADOWS_SOFT
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local _WINDQUALITY_NONE _WINDQUALITY_FASTEST _WINDQUALITY_FAST _WINDQUALITY_BETTER _WINDQUALITY_BEST _WINDQUALITY_PALM
|
||||
#pragma shader_feature_local EFFECT_BILLBOARD
|
||||
#pragma shader_feature_local EFFECT_HUE_VARIATION
|
||||
//#pragma shader_feature_local EFFECT_SUBSURFACE // GI dependent.
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
#pragma shader_feature_local EFFECT_EXTRA_TEX
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define EFFECT_BACKSIDE_NORMALS
|
||||
#define GBUFFER
|
||||
|
||||
#include "SpeedTree8Input.hlsl"
|
||||
#include "SpeedTree8Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "ShadowCaster"
|
||||
Tags{"LightMode" = "ShadowCaster"}
|
||||
|
||||
ColorMask 0
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree8VertDepth
|
||||
#pragma fragment SpeedTree8FragDepth
|
||||
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local _WINDQUALITY_NONE _WINDQUALITY_FASTEST _WINDQUALITY_FAST _WINDQUALITY_BETTER _WINDQUALITY_BEST _WINDQUALITY_PALM
|
||||
#pragma shader_feature_local EFFECT_BILLBOARD
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
#define SHADOW_CASTER
|
||||
|
||||
// -------------------------------------
|
||||
// Universal Pipeline keywords
|
||||
|
||||
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
|
||||
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
|
||||
|
||||
#include "SpeedTree8Input.hlsl"
|
||||
#include "SpeedTree8Passes.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "DepthOnly"
|
||||
Tags{"LightMode" = "DepthOnly"}
|
||||
|
||||
ZWrite On
|
||||
ColorMask 0
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex SpeedTree8VertDepth
|
||||
#pragma fragment SpeedTree8FragDepth
|
||||
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
#pragma multi_compile_instancing
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#pragma shader_feature_local _WINDQUALITY_NONE _WINDQUALITY_FASTEST _WINDQUALITY_FAST _WINDQUALITY_BETTER _WINDQUALITY_BEST _WINDQUALITY_PALM
|
||||
#pragma shader_feature_local EFFECT_BILLBOARD
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define DEPTH_ONLY
|
||||
|
||||
#include "SpeedTree8Input.hlsl"
|
||||
#include "SpeedTree8Passes.hlsl"
|
||||
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
// This pass is used when drawing to a _CameraNormalsTexture texture
|
||||
Pass
|
||||
{
|
||||
Name "DepthNormals"
|
||||
Tags{"LightMode" = "DepthNormals"}
|
||||
|
||||
ZWrite On
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex SpeedTree8VertDepthNormal
|
||||
#pragma fragment SpeedTree8FragDepthNormal
|
||||
|
||||
#pragma shader_feature_local _WINDQUALITY_NONE _WINDQUALITY_FASTEST _WINDQUALITY_FAST _WINDQUALITY_BETTER _WINDQUALITY_BEST _WINDQUALITY_PALM
|
||||
#pragma shader_feature_local EFFECT_BUMP
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma multi_compile_vertex LOD_FADE_PERCENTAGE
|
||||
#pragma multi_compile __ LOD_FADE_CROSSFADE
|
||||
|
||||
#pragma instancing_options assumeuniformscaling maxcount:50
|
||||
|
||||
#define ENABLE_WIND
|
||||
#define EFFECT_BACKSIDE_NORMALS
|
||||
|
||||
#include "SpeedTree8Input.hlsl"
|
||||
#include "SpeedTree8Passes.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
CustomEditor "SpeedTree8ShaderGUI"
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
#ifndef UNIVERSAL_SPEEDTREE8_INPUT_INCLUDED
|
||||
#define UNIVERSAL_SPEEDTREE8_INPUT_INCLUDED
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
#define _NORMALMAP
|
||||
#endif
|
||||
|
||||
#define _ALPHATEST_ON
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
|
||||
|
||||
#if defined(ENABLE_WIND) && !defined(_WINDQUALITY_NONE)
|
||||
#define SPEEDTREE_Y_UP
|
||||
#include "SpeedTreeWind.cginc"
|
||||
float _WindEnabled;
|
||||
UNITY_INSTANCING_BUFFER_START(STWind)
|
||||
UNITY_DEFINE_INSTANCED_PROP(float, _GlobalWindTime)
|
||||
UNITY_INSTANCING_BUFFER_END(STWind)
|
||||
#endif
|
||||
|
||||
half4 _Color;
|
||||
int _TwoSided;
|
||||
|
||||
#ifdef SCENESELECTIONPASS
|
||||
int _ObjectId;
|
||||
int _PassValue;
|
||||
#endif
|
||||
|
||||
TEXTURE2D(_MainTex);
|
||||
SAMPLER(sampler_MainTex);
|
||||
|
||||
#ifdef EFFECT_EXTRA_TEX
|
||||
sampler2D _ExtraTex;
|
||||
#else
|
||||
half _Glossiness;
|
||||
half _Metallic;
|
||||
#endif
|
||||
|
||||
#ifdef EFFECT_HUE_VARIATION
|
||||
half4 _HueVariationColor;
|
||||
#endif
|
||||
|
||||
#ifdef EFFECT_BILLBOARD
|
||||
half _BillboardShadowFade;
|
||||
#endif
|
||||
|
||||
#ifdef EFFECT_SUBSURFACE
|
||||
sampler2D _SubsurfaceTex;
|
||||
half4 _SubsurfaceColor;
|
||||
half _SubsurfaceIndirect;
|
||||
#endif
|
||||
|
||||
// Shadow Casting Light geometric parameters. These variables are used when applying the shadow Normal Bias and are set by UnityEngine.Rendering.Universal.ShadowUtils.SetupShadowCasterConstantBuffer in com.unity.render-pipelines.universal/Runtime/ShadowUtils.cs
|
||||
// For Directional lights, _LightDirection is used when applying shadow Normal Bias.
|
||||
// For Spot lights and Point lights, _LightPosition is used to compute the actual light direction because it is different at each shadow caster geometry vertex.
|
||||
float3 _LightDirection;
|
||||
float3 _LightPosition;
|
||||
|
||||
#define GEOM_TYPE_BRANCH 0
|
||||
#define GEOM_TYPE_FROND 1
|
||||
#define GEOM_TYPE_LEAF 2
|
||||
#define GEOM_TYPE_FACINGLEAF 3
|
||||
|
||||
#define _Surface 0.0 // Speed Trees are always opaque
|
||||
|
||||
#endif
|
@@ -0,0 +1,530 @@
|
||||
#ifndef UNIVERSAL_SPEEDTREE8_PASSES_INCLUDED
|
||||
#define UNIVERSAL_SPEEDTREE8_PASSES_INCLUDED
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl"
|
||||
|
||||
struct SpeedTreeVertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
float4 tangent : TANGENT;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
float4 texcoord1 : TEXCOORD1;
|
||||
float4 texcoord2 : TEXCOORD2;
|
||||
float4 texcoord3 : TEXCOORD3;
|
||||
float4 color : COLOR;
|
||||
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct SpeedTreeVertexOutput
|
||||
{
|
||||
half2 uv : TEXCOORD0;
|
||||
half4 color : TEXCOORD1;
|
||||
|
||||
half4 fogFactorAndVertexLight : TEXCOORD2; // x: fogFactor, yzw: vertex light
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
half4 normalWS : TEXCOORD3; // xyz: normal, w: viewDir.x
|
||||
half4 tangentWS : TEXCOORD4; // xyz: tangent, w: viewDir.y
|
||||
half4 bitangentWS : TEXCOORD5; // xyz: bitangent, w: viewDir.z
|
||||
#else
|
||||
half3 normalWS : TEXCOORD3;
|
||||
half3 viewDirWS : TEXCOORD4;
|
||||
#endif
|
||||
|
||||
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
||||
float4 shadowCoord : TEXCOORD6;
|
||||
#endif
|
||||
|
||||
float3 positionWS : TEXCOORD7;
|
||||
DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 8);
|
||||
float4 clipPos : SV_POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
struct SpeedTreeVertexDepthOutput
|
||||
{
|
||||
half2 uv : TEXCOORD0;
|
||||
half4 color : TEXCOORD1;
|
||||
float4 clipPos : SV_POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
struct SpeedTreeVertexDepthNormalOutput
|
||||
{
|
||||
half2 uv : TEXCOORD0;
|
||||
half4 color : TEXCOORD1;
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
half4 normalWS : TEXCOORD2; // xyz: normal, w: viewDir.x
|
||||
half4 tangentWS : TEXCOORD3; // xyz: tangent, w: viewDir.y
|
||||
half4 bitangentWS : TEXCOORD4; // xyz: bitangent, w: viewDir.z
|
||||
#else
|
||||
half3 normalWS : TEXCOORD2;
|
||||
half3 viewDirWS : TEXCOORD3;
|
||||
#endif
|
||||
|
||||
float4 clipPos : SV_POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
struct SpeedTreeDepthNormalFragmentInput
|
||||
{
|
||||
SpeedTreeVertexDepthNormalOutput interpolated;
|
||||
#ifdef EFFECT_BACKSIDE_NORMALS
|
||||
half facing : VFACE;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SpeedTreeFragmentInput
|
||||
{
|
||||
SpeedTreeVertexOutput interpolated;
|
||||
#ifdef EFFECT_BACKSIDE_NORMALS
|
||||
half facing : VFACE;
|
||||
#endif
|
||||
};
|
||||
|
||||
void InitializeData(inout SpeedTreeVertexInput input, float lodValue)
|
||||
{
|
||||
// smooth LOD
|
||||
#if defined(LOD_FADE_PERCENTAGE) && !defined(EFFECT_BILLBOARD)
|
||||
input.vertex.xyz = lerp(input.vertex.xyz, input.texcoord2.xyz, lodValue);
|
||||
#endif
|
||||
|
||||
// wind
|
||||
#if defined(ENABLE_WIND) && !defined(_WINDQUALITY_NONE)
|
||||
if (_WindEnabled > 0)
|
||||
{
|
||||
float3 rotatedWindVector = mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld);
|
||||
float windLength = length(rotatedWindVector);
|
||||
if (windLength < 1e-5)
|
||||
{
|
||||
// sanity check that wind data is available
|
||||
return;
|
||||
}
|
||||
rotatedWindVector /= windLength;
|
||||
|
||||
float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
|
||||
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
|
||||
bool bBestWind = true;
|
||||
#else
|
||||
bool bBestWind = false;
|
||||
#endif
|
||||
float leafWindTrigOffset = anchor.x + anchor.y;
|
||||
windyPosition = LeafWind(bBestWind, leafTwo, windyPosition, input.normal, input.texcoord3.x, float3(0,0,0), input.texcoord3.y, input.texcoord3.z, leafWindTrigOffset, rotatedWindVector);
|
||||
#endif
|
||||
|
||||
// move back out to anchor
|
||||
windyPosition += anchor;
|
||||
}
|
||||
|
||||
// frond wind
|
||||
bool bPalmWind = false;
|
||||
#ifdef _WINDQUALITY_PALM
|
||||
bPalmWind = true;
|
||||
if (geometryType == GEOM_TYPE_FROND)
|
||||
{
|
||||
windyPosition = RippleFrond(windyPosition, input.normal, input.texcoord.x, input.texcoord.y, input.texcoord3.x, input.texcoord3.y, input.texcoord3.z);
|
||||
}
|
||||
#endif
|
||||
|
||||
// branch wind (applies to all 3D geometry)
|
||||
#if defined(_WINDQUALITY_BETTER) || defined(_WINDQUALITY_BEST) || defined(_WINDQUALITY_PALM)
|
||||
float3 rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
|
||||
windyPosition = BranchWind(bPalmWind, windyPosition, treePos, float4(input.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
|
||||
#endif
|
||||
|
||||
#endif // !EFFECT_BILLBOARD
|
||||
|
||||
// global wind
|
||||
float globalWindTime = _ST_WindGlobal.x;
|
||||
#if defined(EFFECT_BILLBOARD) && defined(UNITY_INSTANCING_ENABLED)
|
||||
globalWindTime += UNITY_ACCESS_INSTANCED_PROP(STWind, _GlobalWindTime);
|
||||
#endif
|
||||
|
||||
windyPosition = GlobalWind(windyPosition, treePos, true, rotatedWindVector, globalWindTime);
|
||||
input.vertex.xyz = windyPosition;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(EFFECT_BILLBOARD)
|
||||
float3 treePos = float3(UNITY_MATRIX_M[0].w, UNITY_MATRIX_M[1].w, UNITY_MATRIX_M[2].w);
|
||||
// crossfade faces
|
||||
bool topDown = (input.texcoord.z > 0.5);
|
||||
float3 viewDir = UNITY_MATRIX_IT_MV[2].xyz;
|
||||
float3 cameraDir = normalize(mul((float3x3)UNITY_MATRIX_M, _WorldSpaceCameraPos - treePos));
|
||||
float viewDot = max(dot(viewDir, input.normal), dot(cameraDir, input.normal));
|
||||
viewDot *= viewDot;
|
||||
viewDot *= viewDot;
|
||||
viewDot += topDown ? 0.38 : 0.18; // different scales for horz and vert billboards to fix transition zone
|
||||
|
||||
// if invisible, avoid overdraw
|
||||
if (viewDot < 0.3333)
|
||||
{
|
||||
input.vertex.xyz = float3(0, 0, 0);
|
||||
}
|
||||
|
||||
input.color = float4(1, 1, 1, clamp(viewDot, 0, 1));
|
||||
|
||||
// adjust lighting on billboards to prevent seams between the different faces
|
||||
if (topDown)
|
||||
{
|
||||
input.normal += cameraDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
half3 binormal = cross(input.normal, input.tangent.xyz) * input.tangent.w;
|
||||
float3 right = cross(cameraDir, binormal);
|
||||
input.normal = cross(binormal, right);
|
||||
}
|
||||
input.normal = normalize(input.normal);
|
||||
#endif
|
||||
}
|
||||
|
||||
SpeedTreeVertexOutput SpeedTree8Vert(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);
|
||||
|
||||
output.uv = input.texcoord.xy;
|
||||
output.color = input.color;
|
||||
|
||||
// color already contains (ao, ao, ao, blend)
|
||||
// put hue variation amount in there
|
||||
#ifdef EFFECT_HUE_VARIATION
|
||||
float3 treePos = float3(UNITY_MATRIX_M[0].w, UNITY_MATRIX_M[1].w, UNITY_MATRIX_M[2].w);
|
||||
float hueVariationAmount = frac(treePos.x + treePos.y + treePos.z);
|
||||
output.color.g = saturate(hueVariationAmount * _HueVariationColor.a);
|
||||
#endif
|
||||
|
||||
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
|
||||
half3 normalWS = TransformObjectToWorldNormal(input.normal);
|
||||
|
||||
half3 vertexLight = VertexLighting(vertexInput.positionWS, normalWS);
|
||||
half fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
|
||||
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
|
||||
|
||||
half3 viewDirWS = GetWorldSpaceViewDir(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
|
||||
|
||||
output.positionWS = vertexInput.positionWS;
|
||||
|
||||
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
||||
output.shadowCoord = GetShadowCoord(vertexInput);
|
||||
#endif
|
||||
|
||||
output.clipPos = vertexInput.positionCS;
|
||||
|
||||
OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
SpeedTreeVertexDepthOutput SpeedTree8VertDepth(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.uv = input.texcoord.xy;
|
||||
output.color = input.color;
|
||||
|
||||
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
|
||||
|
||||
#ifdef SHADOW_CASTER
|
||||
half3 normalWS = TransformObjectToWorldNormal(input.normal);
|
||||
|
||||
#if _CASTING_PUNCTUAL_LIGHT_SHADOW
|
||||
float3 lightDirectionWS = normalize(_LightPosition - vertexInput.positionWS);
|
||||
#else
|
||||
float3 lightDirectionWS = _LightDirection;
|
||||
#endif
|
||||
|
||||
float4 positionCS = TransformWorldToHClip(ApplyShadowBias(vertexInput.positionWS, normalWS, lightDirectionWS));
|
||||
output.clipPos = positionCS;
|
||||
#else
|
||||
output.clipPos = vertexInput.positionCS;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void InitializeInputData(SpeedTreeFragmentInput input, half3 normalTS, out InputData inputData)
|
||||
{
|
||||
inputData.positionWS = input.interpolated.positionWS.xyz;
|
||||
|
||||
#ifdef EFFECT_BUMP
|
||||
inputData.normalWS = TransformTangentToWorld(normalTS, half3x3(input.interpolated.tangentWS.xyz, input.interpolated.bitangentWS.xyz, input.interpolated.normalWS.xyz));
|
||||
inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
|
||||
inputData.viewDirectionWS = half3(input.interpolated.normalWS.w, input.interpolated.tangentWS.w, input.interpolated.bitangentWS.w);
|
||||
#else
|
||||
inputData.normalWS = NormalizeNormalPerPixel(input.interpolated.normalWS);
|
||||
inputData.viewDirectionWS = input.interpolated.viewDirWS;
|
||||
#endif
|
||||
|
||||
#if SHADER_HINT_NICE_QUALITY
|
||||
inputData.viewDirectionWS = SafeNormalize(inputData.viewDirectionWS);
|
||||
#endif
|
||||
|
||||
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
||||
inputData.shadowCoord = input.interpolated.shadowCoord;
|
||||
#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
|
||||
inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
|
||||
#else
|
||||
inputData.shadowCoord = float4(0, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
inputData.fogCoord = input.interpolated.fogFactorAndVertexLight.x;
|
||||
inputData.vertexLighting = input.interpolated.fogFactorAndVertexLight.yzw;
|
||||
inputData.bakedGI = SAMPLE_GI(input.interpolated.lightmapUV, input.interpolated.vertexSH, inputData.normalWS);
|
||||
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.interpolated.clipPos);
|
||||
inputData.shadowMask = half4(1, 1, 1, 1); // No GI currently.
|
||||
}
|
||||
|
||||
#ifdef GBUFFER
|
||||
FragmentOutput SpeedTree8Frag(SpeedTreeFragmentInput input)
|
||||
#else
|
||||
half4 SpeedTree8Frag(SpeedTreeFragmentInput input) : SV_Target
|
||||
#endif
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(input.interpolated);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input.interpolated);
|
||||
|
||||
#if !defined(SHADER_QUALITY_LOW)
|
||||
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
|
||||
#ifdef EFFECT_BILLBOARD
|
||||
LODDitheringTransition(input.interpolated.clipPos.xy, unity_LODFade.x);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
half2 uv = input.interpolated.uv;
|
||||
half4 diffuse = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex)) * _Color;
|
||||
|
||||
half alpha = diffuse.a * input.interpolated.color.a;
|
||||
AlphaDiscard(alpha - 0.3333, 0.0);
|
||||
|
||||
half3 albedo = diffuse.rgb;
|
||||
half3 emission = 0;
|
||||
half metallic = 0;
|
||||
half smoothness = 0;
|
||||
half occlusion = 0;
|
||||
half3 specular = 0;
|
||||
|
||||
// hue variation
|
||||
#ifdef EFFECT_HUE_VARIATION
|
||||
half3 shiftedColor = lerp(albedo, _HueVariationColor.rgb, input.interpolated.color.g);
|
||||
|
||||
// preserve vibrance
|
||||
half maxBase = max(albedo.r, max(albedo.g, albedo.b));
|
||||
half newMaxBase = max(shiftedColor.r, max(shiftedColor.g, shiftedColor.b));
|
||||
maxBase /= newMaxBase;
|
||||
maxBase = maxBase * 0.5f + 0.5f;
|
||||
shiftedColor.rgb *= maxBase;
|
||||
|
||||
albedo = saturate(shiftedColor);
|
||||
#endif
|
||||
|
||||
// normal
|
||||
#ifdef EFFECT_BUMP
|
||||
half3 normalTs = SampleNormal(uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap));
|
||||
#else
|
||||
half3 normalTs = half3(0, 0, 1);
|
||||
#endif
|
||||
|
||||
// flip normal on backsides
|
||||
#ifdef EFFECT_BACKSIDE_NORMALS
|
||||
if (input.facing < 0.5)
|
||||
{
|
||||
normalTs.z = -normalTs.z;
|
||||
}
|
||||
#endif
|
||||
|
||||
// adjust billboard normals to improve GI and matching
|
||||
#ifdef EFFECT_BILLBOARD
|
||||
normalTs.z *= 0.5;
|
||||
normalTs = normalize(normalTs);
|
||||
#endif
|
||||
|
||||
// extra
|
||||
#ifdef EFFECT_EXTRA_TEX
|
||||
half4 extra = tex2D(_ExtraTex, uv);
|
||||
smoothness = extra.r;
|
||||
metallic = extra.g;
|
||||
occlusion = extra.b * input.interpolated.color.r;
|
||||
#else
|
||||
smoothness = _Glossiness;
|
||||
metallic = _Metallic;
|
||||
occlusion = input.interpolated.color.r;
|
||||
#endif
|
||||
|
||||
// subsurface (hijack emissive)
|
||||
#ifdef EFFECT_SUBSURFACE
|
||||
emission = tex2D(_SubsurfaceTex, uv).rgb * _SubsurfaceColor.rgb;
|
||||
#endif
|
||||
|
||||
InputData inputData;
|
||||
InitializeInputData(input, normalTs, inputData);
|
||||
|
||||
#ifdef GBUFFER
|
||||
// in LitForwardPass GlobalIllumination (and temporarily LightingPhysicallyBased) are called inside UniversalFragmentPBR
|
||||
// in Deferred rendering we store the sum of these values (and of emission as well) in the GBuffer
|
||||
BRDFData brdfData;
|
||||
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
|
||||
|
||||
Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, inputData.shadowMask);
|
||||
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, inputData.shadowMask);
|
||||
half3 color = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS);
|
||||
|
||||
return BRDFDataToGbuffer(brdfData, inputData, smoothness, emission + color);
|
||||
|
||||
#else
|
||||
half4 color = UniversalFragmentPBR(inputData, albedo, metallic, specular, smoothness, occlusion, emission, alpha);
|
||||
color.rgb = MixFog(color.rgb, inputData.fogCoord);
|
||||
color.a = OutputAlpha(color.a, _Surface);
|
||||
|
||||
return color;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
half4 SpeedTree8FragDepth(SpeedTreeVertexDepthOutput input) : SV_Target
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(input);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
||||
|
||||
#if !defined(SHADER_QUALITY_LOW)
|
||||
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
|
||||
#ifdef EFFECT_BILLBOARD
|
||||
LODDitheringTransition(input.clipPos.xy, unity_LODFade.x);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
half2 uv = input.uv;
|
||||
half4 diffuse = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex)) * _Color;
|
||||
|
||||
half alpha = diffuse.a * input.color.a;
|
||||
AlphaDiscard(alpha - 0.3333, 0.0);
|
||||
|
||||
#if defined(SCENESELECTIONPASS)
|
||||
// We use depth prepass for scene selection in the editor, this code allow to output the outline correctly
|
||||
return half4(_ObjectId, _PassValue, 1.0, 1.0);
|
||||
#else
|
||||
return half4(0, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SpeedTreeVertexDepthNormalOutput SpeedTree8VertDepthNormal(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.uv = input.texcoord.xy;
|
||||
output.color = input.color;
|
||||
|
||||
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
|
||||
half3 normalWS = TransformObjectToWorldNormal(input.normal);
|
||||
half3 viewDirWS = GetWorldSpaceViewDir(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;
|
||||
#endif
|
||||
|
||||
output.clipPos = vertexInput.positionCS;
|
||||
return output;
|
||||
}
|
||||
|
||||
half4 SpeedTree8FragDepthNormal(SpeedTreeDepthNormalFragmentInput input) : SV_Target
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(input.interpolated);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input.interpolated);
|
||||
|
||||
#if !defined(SHADER_QUALITY_LOW)
|
||||
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group
|
||||
#ifdef EFFECT_BILLBOARD
|
||||
LODDitheringTransition(input.interpolated.clipPos.xy, unity_LODFade.x);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
half2 uv = input.interpolated.uv;
|
||||
half4 diffuse = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex)) * _Color;
|
||||
|
||||
half alpha = diffuse.a * input.interpolated.color.a;
|
||||
AlphaDiscard(alpha - 0.3333, 0.0);
|
||||
|
||||
float3 normalWS = NormalizeNormalPerPixel(input.interpolated.normalWS);
|
||||
return float4(PackNormalOctRectEncode(TransformWorldToViewDir(normalWS, true)), 0.0, 0.0);
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user