Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Shader "L02_URP/Grass"{
- Properties{
- _TopColor("Top Color", Color) = (1,1,1,1)
- _BottomColor("Bottom Color", Color) = (1,1,1,1)
- _TranslucentGain("Translucent Gain", Range(0,1)) = 0.5
- _BendRotationRandom("Bend Rotation Random", Range(0, 1)) = 0.2
- _BladeWidth("Blade Width", Float) = 0.05
- _BladeWidthRandom("Blade Width Random", Float) = 0.02
- _BladeHeight("Blade Height", Float) = 0.5
- _BladeHeightRandom("Blade Height Random", Float) = 0.3
- [KeywordEnum(INTEGER, FRAC_EVEN, FRAC_ODD, POW2)] _PARTITIONING("Partition algoritm", Int) = 0
- [KeywordEnum(FIXED, SCREEN_BASE, WORLD_BASE)] _DYNAMIC("Dynamic Partition Mode", Int) = 0
- _TessellationFactor_FIXED("Tessellation FIXED", Range(1, 8)) = 1
- _TessellationFactor_SCREEN_BASE("Tessellation SCREEN_BASE", Range(0.01, 8)) = 0.05
- _TessellationFactor_WORLD_BASE("Tessellation WORLD_BASE", Range(0.01, 8)) = 0.08
- _WindDistortionMap("Wind Distortion Map", 2D) = "white" {}
- _WindFrequency("Wind Frequency", Vector) = (0.05, 0.05, 0, 0)
- _WindStrength("Wind Strength", Float) = 1
- _BladeForward("Blade Forward Amount", Float) = 0.38
- _BladeCurve("Blade Curvature Amount", Range(1, 4)) = 2
- [KeywordEnum(TRUE, FALSE)] _CUTTESS("Cut Tess", Int) = 0
- }
- SubShader{
- Tags{
- "RenderType" = "Opaque"
- "Queue" = "Geometry"
- "RenderPipeline" = "UniversalPipeline"
- }
- LOD 100
- Cull Off
- HLSLINCLUDE
- #pragma require geometry
- #pragma require tessellation tessHW
- #pragma vertex vert
- #pragma fragment frag
- #pragma hull hull
- #pragma domain domain
- #pragma geometry geo
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
- #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
- #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
- #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
- #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
- #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
- #pragma multi_compile _ _SHADOWS_SOFT
- #pragma shader_feature_local _PARTITIONING_INTEGER _PARTITIONING_FRAC_EVEN _PARTITIONING_FRAC_ODD _PARTITIONING_POW2
- #pragma shader_feature_local _CUTTESS_TRUE _CUTTESS_FALSE
- #pragma shader_feature_local _DYNAMIC_FIXED _DYNAMIC_SCREEN_BASE _DYNAMIC_WORLD_BASE
- #define UNITY_PI 3.14159265359f
- #define UNITY_TWO_PI 6.28318530718f
- #define BLADE_SEGMENTS 3
- CBUFFER_START(UnityPerMaterial)
- float4 _BaseColor;
- float4 _BaseMap_ST;
- float _BendRotationRandom;
- float _BladeHeight;
- float _BladeHeightRandom;
- float _BladeWidth;
- float _BladeWidthRandom;
- sampler2D _WindDistortionMap;
- float4 _WindDistortionMap_ST;
- float2 _WindFrequency;
- float _WindStrength;
- float _BladeForward;
- float _BladeCurve;
- float4 _TopColor;
- float4 _BottomColor;
- float _TessellationFactor_FIXED;
- float _TessellationFactor_SCREEN_BASE;
- float _TessellationFactor_WORLD_BASE;
- float _TranslucentGain;
- CBUFFER_END
- TEXTURE2D (_BaseMap);SAMPLER(sampler_BaseMap);
- struct Attributes
- {
- float4 posOS : POSITION;
- float3 normalOS : NORMAL;
- float4 tangentOS : TANGENT;
- };
- struct TessellationControlPoint
- {
- float4 posOS : INTERNALTESSPOS;
- float3 normalOS : NORMAL;
- float4 tangentOS : TANGENT;
- float4 positionCS : TEXCOORD0;
- };
- struct Interpolators
- {
- float4 posOS : POSITION;
- float3 normalOS : NORMAL;
- float4 tangentOS : TANGENT;
- };
- struct TessellationFactors
- {
- float edge[3] : SV_TessFactor;
- float inside : SV_InsideTessFactor;
- };
- struct geometryOutput{
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- float4 shadowCoord : TEXCOORD1;
- float3 norWS : TEXCOORD2;
- // float3 normal : NORMAL;
- };
- /*
- Tools Function
- */
- float rand(float3 co){
- return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
- }
- float3x3 AngleAxis3x3(float angle, float3 axis){
- float c, s;
- sincos(angle, s, c);
- float t = 1 - c;
- float x = axis.x;
- float y = axis.y;
- float z = axis.z;
- return float3x3(
- t * x * x + c, t * x * y - s * z, t * x * z + s * y,
- t * x * y + s * z, t * y * y + c, t * y * z - s * x,
- t * x * z - s * y, t * y * z + s * x, t * z * z + c
- );
- }
- bool IsOutOfBounds(float3 p, float3 lower, float3 higher) { //给定矩形判断
- return p.x < lower.x || p.x > higher.x || p.y < lower.y || p.y > higher.y || p.z < lower.z || p.z > higher.z;
- }
- bool IsPointOutOfFrustum(float4 positionCS) { //视锥体判断
- float3 culling = positionCS.xyz;
- float w = positionCS.w;
- float3 lowerBounds = float3(-w, -w, -w * _ProjectionParams.z);
- float3 higherBounds = float3(w, w, w);
- return IsOutOfBounds(culling, lowerBounds, higherBounds);
- }
- bool ShouldClipPatch(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS) {
- bool allOutside = IsPointOutOfFrustum(p0PositionCS) &&
- IsPointOutOfFrustum(p1PositionCS) &&
- IsPointOutOfFrustum(p2PositionCS);
- return allOutside;
- }
- // 生成草的具體座標, 草的寬度, 草的高度, 草的朝向, uv傳遞, 變換矩陣
- geometryOutput GenerateGrassVertex(float3 vertexPosition, float width, float height, float forward, float2 uv, float3x3 transformMatrix) {
- float3 tangentPoint = float3(width, forward, height);
- float3 localPosition = vertexPosition + mul(transformMatrix, tangentPoint);
- float3 tangentNormal = normalize(float3(0, -1, forward));
- float3 localNormal = mul(transformMatrix, tangentNormal);
- float3 posWS = TransformObjectToWorld(localPosition.xyz);
- float3 norWS = TransformObjectToWorldNormal(localNormal);
- geometryOutput o;
- o.pos = TransformObjectToHClip(localPosition);
- o.uv = uv;
- o.norWS = norWS;
- o.shadowCoord = TransformWorldToShadowCoord(posWS);
- #if UNITY_PASS_SHADOWCASTER
- // o.pos = UnityApplyLinearShadowBias(o.pos);
- o.shadowCoord = TransformWorldToShadowCoord(ApplyShadowBias(posWS, norWS, 0));
- #endif
- return o;
- }
- float EdgeTessellationFactor_ScreenBase(float scale, float4 p0PositionCS, float4 p1PositionCS) {
- float factor = distance(p0PositionCS.xyz / p0PositionCS.w, p1PositionCS.xyz / p1PositionCS.w);
- return max(1, factor / scale);
- }
- float EdgeTessellationFactor_WorldBase(float scale, float3 p0PositionWS, float3 p1PositionWS) {
- float length = distance(p0PositionWS, p1PositionWS);
- float distanceToCamera = distance(_WorldSpaceCameraPos, (p0PositionWS + p1PositionWS) * 0.5);
- // 使用平方根函数调整距离的影响,使中距离的镶嵌因子变化更平滑
- float adjustedDistance = sqrt(distanceToCamera);
- float factor = length / (scale * adjustedDistance);
- return max(1, factor);
- }
- /*
- Vertex Shader
- */
- TessellationControlPoint vert(Attributes v){
- TessellationControlPoint o;
- o.posOS = v.posOS;
- o.normalOS = v.normalOS;
- o.tangentOS = v.tangentOS;
- o.positionCS = TransformObjectToHClip(v.posOS);
- return o;
- }
- /*
- Tesselation Shader
- */
- TessellationFactors patchConstantFunction (InputPatch<TessellationControlPoint, 3> patch){
- TessellationFactors f;
- #if defined(_DYNAMIC_FIXED)
- f.edge[0] = _TessellationFactor_FIXED;
- f.edge[1] = _TessellationFactor_FIXED;
- f.edge[2] = _TessellationFactor_FIXED;
- f.inside = _TessellationFactor_FIXED;
- #elif defined(_DYNAMIC_SCREEN_BASE)
- f.edge[0] = EdgeTessellationFactor_ScreenBase(_TessellationFactor_SCREEN_BASE,
- patch[1].positionCS, patch[2].positionCS);
- f.edge[1] = EdgeTessellationFactor_ScreenBase(_TessellationFactor_SCREEN_BASE,
- patch[2].positionCS, patch[0].positionCS);
- f.edge[2] = EdgeTessellationFactor_ScreenBase(_TessellationFactor_SCREEN_BASE,
- patch[0].positionCS, patch[1].positionCS);
- f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) / 3.0;
- #elif defined(_DYNAMIC_WORLD_BASE)
- f.edge[0] = EdgeTessellationFactor_WorldBase(_TessellationFactor_WORLD_BASE,
- patch[1].posOS, patch[2].posOS);
- f.edge[1] = EdgeTessellationFactor_WorldBase(_TessellationFactor_WORLD_BASE,
- patch[2].posOS, patch[0].posOS);
- f.edge[2] = EdgeTessellationFactor_WorldBase(_TessellationFactor_WORLD_BASE,
- patch[0].posOS, patch[1].posOS);
- f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) / 3.0;
- #else
- f.edge[0] = _TessellationFactor_FIXED;
- f.edge[1] = _TessellationFactor_FIXED;
- f.edge[2] = _TessellationFactor_FIXED;
- f.inside = _TessellationFactor_FIXED;
- #endif
- #if defined(_CUTTESS_TRUE)
- if(ShouldClipPatch(patch[0].positionCS, patch[1].positionCS, patch[2].positionCS))
- f.edge[0] = f.edge[1] = f.edge[2] = f.inside = 0;
- #endif
- return f;
- }
- [patchconstantfunc("patchConstantFunction")]
- [domain("tri")][outputcontrolpoints(3)]
- [outputtopology("triangle_cw")]
- #if defined(_PARTITIONING_INTEGER)
- [partitioning("integer")]
- #elif defined(_PARTITIONING_FRAC_EVEN)
- [partitioning("fractional_even")]
- #elif defined(_PARTITIONING_FRAC_ODD)
- [partitioning("fractional_odd")]
- #elif defined(_PARTITIONING_POW2)
- [partitioning("pow2")]
- #else
- [partitioning("integer")]
- #endif
- TessellationControlPoint hull (InputPatch<TessellationControlPoint, 3> patch, uint id : SV_OutputControlPointID){
- return patch[id];
- }
- [domain("tri")]
- Interpolators domain(TessellationFactors factors, OutputPatch<TessellationControlPoint, 3> patch,
- float3 barycentricCoordinates : SV_DomainLocation)
- {
- Interpolators v;
- #define MY_DOMAIN_PROGRAM_INTERPOLATE(fieldName) v.fieldName = \
- patch[0].fieldName * barycentricCoordinates.x + \
- patch[1].fieldName * barycentricCoordinates.y + \
- patch[2].fieldName * barycentricCoordinates.z;
- MY_DOMAIN_PROGRAM_INTERPOLATE(posOS)
- MY_DOMAIN_PROGRAM_INTERPOLATE(normalOS)
- MY_DOMAIN_PROGRAM_INTERPOLATE(tangentOS)
- return v;
- }
- [maxvertexcount(BLADE_SEGMENTS * 2 + 1)]
- void geo(triangle Interpolators IN[3], inout TriangleStream<geometryOutput> triStream){
- float3 vNormal = IN[0].normalOS;
- float4 vTangent = IN[0].tangentOS;
- float3 vBinormal = cross(vNormal, vTangent) * vTangent.w;
- float3x3 tangentToLocal = float3x3(
- vTangent.x, vBinormal.x, vNormal.x,
- vTangent.y, vBinormal.y, vNormal.y,
- vTangent.z, vBinormal.z, vNormal.z
- );
- float3 pos = IN[0].posOS;
- float3x3 facingRotationMatrix = AngleAxis3x3(rand(pos) * UNITY_TWO_PI, float3(0, 0, 1));
- float3x3 bendRotationMatrix = AngleAxis3x3(rand(pos.zzx) * _BendRotationRandom * UNITY_PI * 0.2, float3(-1, 0, 0));
- float2 uv = pos.xz * _WindDistortionMap_ST.xy + _WindDistortionMap_ST.zw + _WindFrequency * _Time.y;
- float2 windSample = (tex2Dlod(_WindDistortionMap, float4(uv, 0, 0)).xy * 2 - 1) * _WindStrength;
- float3 wind = normalize(float3(windSample.x, windSample.y, 0));
- float3x3 windRotation = AngleAxis3x3(UNITY_PI * windSample * 0.2, wind);
- float3x3 transformationMatrix = mul(mul(mul(tangentToLocal, windRotation), facingRotationMatrix), bendRotationMatrix);
- float height = (rand(pos.zyx) * 2 - 1) * _BladeHeightRandom + _BladeHeight;
- float width = (rand(pos.xzy) * 2 - 1) * _BladeWidthRandom + _BladeWidth;
- float forward = rand(pos.yyz) * _BladeForward;
- float3x3 transformationMatrixFacing = mul(tangentToLocal, facingRotationMatrix);
- for (int i = 0; i < BLADE_SEGMENTS; i++){
- float t = i / (float)BLADE_SEGMENTS;
- float segmentHeight = height * t;
- float segmentWidth = width * (1 - t);
- float segmentForward = pow(t, _BladeCurve) * forward;
- float3x3 transformMatrix = i == 0 ? transformationMatrixFacing : transformationMatrix;
- triStream.Append(GenerateGrassVertex(pos, segmentWidth, segmentHeight, segmentForward, float2(0, t), transformMatrix));
- triStream.Append(GenerateGrassVertex(pos, -segmentWidth, segmentHeight, segmentForward, float2(1, t), transformMatrix));
- }
- triStream.Append(GenerateGrassVertex(pos, 0, height, forward, float2(0.5, 1), transformationMatrix));
- }
- ENDHLSL
- Pass{
- Name "GrassPass"
- Tags{ "LightMode" = "UniversalForward" }
- HLSLPROGRAM
- float4 frag (geometryOutput IN, float facing : VFACE) : SV_Target {
- Light mainLight = GetMainLight(IN.shadowCoord);
- float3 normal = facing > 0 ? IN.norWS : -IN.norWS;
- float shadow = lerp(0.0, 1.0, mainLight.shadowAttenuation + 0.25f);
- float NdotL = saturate(saturate(dot(normal, mainLight.direction)) + _TranslucentGain) * shadow;
- float3 ambient = SampleSH(float4(normal, 1));
- float4 lightIntensity = float4(ambient + NdotL * _MainLightColor.rgb, 1.0);
- float4 col = lerp(_BottomColor, _TopColor * lightIntensity, IN.uv.y);
- return col;
- }
- ENDHLSL
- }
- Pass{
- Name "ShadowCaster"
- Tags{ "RenderType" = "Opaque" "LightMode" = "ShadowCaster" }
- ZWrite On
- ZTest LEqual
- HLSLPROGRAM
- half4 frag(geometryOutput input) : SV_TARGET{
- return 1;
- }
- ENDHLSL
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement