-
Notifications
You must be signed in to change notification settings - Fork 167
/
Copy pathLit.hlsl
130 lines (109 loc) · 4.83 KB
/
Lit.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef FUR_SHELL_LIT_HLSL
#define FUR_SHELL_LIT_HLSL
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "./Param.hlsl"
#include "../Common/Common.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 texcoord : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 positionWS : TEXCOORD0;
float3 normalWS : TEXCOORD1;
float4 tangentWS : TANGENT;
float2 uv : TEXCOORD4;
DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 5);
float4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
float layer : TEXCOORD7;
};
Attributes vert(Attributes input)
{
return input;
}
void AppendShellVertex(inout TriangleStream<Varyings> stream, Attributes input, int index)
{
Varyings output = (Varyings)0;
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
float moveFactor = pow(abs((float)index / _ShellAmount), _BaseMove.w);
float3 posOS = input.positionOS.xyz;
float3 windAngle = _Time.w * _WindFreq.xyz;
float3 windMove = moveFactor * _WindMove.xyz * sin(windAngle + posOS * _WindMove.w);
float3 move = moveFactor * _BaseMove.xyz;
float3 shellDir = SafeNormalize(normalInput.normalWS + move + windMove);
float3 viewDirWS = GetCameraPositionWS() - vertexInput.positionWS;
output.positionWS = vertexInput.positionWS + shellDir * (_ShellStep * index);
output.positionCS = TransformWorldToHClip(output.positionWS);
output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
output.normalWS = normalInput.normalWS;
output.tangentWS = float4(normalInput.tangentWS, input.tangentOS.w);
output.layer = (float)index / _ShellAmount;
float3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS);
float fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
output.fogFactorAndVertexLight = float4(fogFactor, vertexLight);
OUTPUT_LIGHTMAP_UV(input.lightmapUV, unity_LightmapST, output.lightmapUV);
OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
stream.Append(output);
}
[maxvertexcount(42)]
void geom(triangle Attributes input[3], inout TriangleStream<Varyings> stream)
{
[loop] for (float i = 0; i < _ShellAmount; ++i)
{
[unroll] for (float j = 0; j < 3; ++j)
{
AppendShellVertex(stream, input[j], i);
}
stream.RestartStrip();
}
}
inline float3 TransformHClipToWorld(float4 positionCS)
{
return mul(UNITY_MATRIX_I_VP, positionCS).xyz;
}
float4 frag(Varyings input) : SV_Target
{
float2 furUv = input.uv / _BaseMap_ST.xy * _FurScale;
float4 furColor = SAMPLE_TEXTURE2D(_FurMap, sampler_FurMap, furUv);
float alpha = furColor.r * (1.0 - input.layer);
if (input.layer > 0.0 && alpha < _AlphaCutout) discard;
float3 viewDirWS = SafeNormalize(GetCameraPositionWS() - input.positionWS);
float3 normalTS = UnpackNormalScale(
SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, furUv),
_NormalScale);
float3 bitangent = SafeNormalize(input.tangentWS.w * cross(input.normalWS, input.tangentWS));
float3 normalWS = SafeNormalize(TransformTangentToWorld(
normalTS,
float3x3(input.tangentWS.xyz, bitangent, input.normalWS)));
SurfaceData surfaceData = (SurfaceData)0;
InitializeStandardLitSurfaceData(input.uv, surfaceData);
surfaceData.occlusion = lerp(1.0 - _Occlusion, 1.0, input.layer);
surfaceData.albedo *= surfaceData.occlusion;
InputData inputData = (InputData)0;
inputData.positionWS = input.positionWS;
inputData.normalWS = normalWS;
inputData.viewDirectionWS = viewDirWS;
#if (defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN)) && !defined(_RECEIVE_SHADOWS_OFF)
inputData.shadowCoord = TransformWorldToShadowCoord(input.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, normalWS);
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
float4 color = UniversalFragmentPBR(inputData, surfaceData);
ApplyRimLight(color.rgb, input.positionWS, viewDirWS, normalWS);
color.rgb += _AmbientColor;
color.rgb = MixFog(color.rgb, inputData.fogCoord);
return color;
}
#endif