1
+ //// ACiiL
2
+ //// Citations in readme and in source.
3
+ //// https://github.com/ACIIL/ACLS-Shader
4
+ #include "./ACLS_HELPERS.cginc"
5
+
6
+ uniform sampler2D _Outline_Sampler; uniform float4 _Outline_Sampler_ST;
7
+ uniform Texture2D _MainTex; uniform float4 _MainTex_ST;
8
+ uniform Texture2D _OutlineTex; uniform float4 _OutlineTex_ST;
9
+ // uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
10
+ // uniform sampler2D _OutlineTex; uniform float4 _OutlineTex_ST;
11
+
12
+ SamplerState sampler_MainTex_trilinear_repeat;
13
+
14
+ uniform half _shadowCastMin_black;
15
+ uniform float4 _Color;
16
+ uniform float4 _Outline_Color;
17
+
18
+ uniform int _outline_mode;
19
+ uniform half _Outline_Width;
20
+ uniform half _Farthest_Distance;
21
+ uniform half _Nearest_Distance;
22
+ uniform half _Is_BlendBaseColor;
23
+ uniform half _Offset_Z;
24
+ uniform int _Is_OutlineTex;
25
+
26
+ uniform half _indirectAlbedoMaxAveScale;
27
+ uniform half _indirectGIDirectionalMix;
28
+ uniform half _indirectGIBlur;
29
+ uniform half _directLightIntensity;
30
+ uniform half _forceLightClamp;
31
+
32
+
33
+
34
+ #ifndef NotAlpha
35
+ uniform Texture2D _ClippingMask; uniform float4 _ClippingMask_ST;
36
+ uniform half _Clipping_Level;
37
+ uniform half _Tweak_transparency;
38
+ uniform int _Inverse_Clipping;
39
+ uniform int _IsBaseMapAlphaAsClippingMask;
40
+ #endif
41
+
42
+
43
+
44
+ struct VertexInput {
45
+ float4 vertex : POSITION ;
46
+ float3 normal : NORMAL ;
47
+ float2 texcoord0 : TEXCOORD0 ;
48
+ UNITY_VERTEX_INPUT_INSTANCE_ID
49
+ };
50
+
51
+ struct VertexOutput {
52
+ float4 pos : SV_POSITION ;
53
+ float4 worldPos : TEXCOORD0 ;
54
+ float2 uv0 : TEXCOORD1 ;
55
+ float3 wNormal : TEXCOORD2 ;
56
+ float3 dirGI : TEXCOORD3 ;
57
+ UNITY_SHADOW_COORDS (4 )
58
+ // LIGHTING_COORDS(3,4)
59
+ UNITY_FOG_COORDS (5 )
60
+ half3 vertexLighting : TEXCOORD6 ;
61
+ float outlineThick : TEXCOORD7 ;
62
+ UNITY_VERTEX_INPUT_INSTANCE_ID
63
+ UNITY_VERTEX_OUTPUT_STEREO
64
+ };
65
+
66
+
67
+
68
+ //// vert
69
+ VertexOutput vert (VertexInput v) {
70
+ UNITY_SETUP_INSTANCE_ID (v);
71
+ VertexOutput o;
72
+ UNITY_INITIALIZE_OUTPUT (VertexOutput, o);
73
+ UNITY_TRANSFER_INSTANCE_ID (v, o);
74
+ UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO (o);
75
+
76
+ o.uv0 = v.texcoord0;
77
+ o.wNormal = UnityObjectToWorldNormal ( v.normal);
78
+ o.worldPos = mul ( unity_ObjectToWorld, v.vertex);
79
+ // float3 worldviewPos = float4(0,1,0);
80
+ float3 worldviewPos = _WorldSpaceCameraPos;
81
+ // float3 worldviewPos = StereoWorldViewPos(); //// wrong stereo for offline offset
82
+ float outlineControlTex = tex2Dlod (_Outline_Sampler, float4 (TRANSFORM_TEX (o.uv0, _Outline_Sampler), 0 , 0 )).r;
83
+ o.outlineThick = outlineControlTex;
84
+ float outlineWidth = saturate ( RemapRange ( (distance (o.worldPos.xyz, worldviewPos.xyz)),
85
+ _Farthest_Distance, _Nearest_Distance, 0 , 1 ));
86
+ outlineWidth *= outlineControlTex * _Outline_Width * 0.001 ;
87
+ float3 posDiff = worldviewPos.xyz - o.worldPos.xyz;
88
+ float3 dirView = normalize (posDiff);
89
+ float4 viewDirectionVP = mul ( UNITY_MATRIX_VP, float4 ( dirView.xyz, 1 ));
90
+ float4 posWorldHull = o.worldPos;
91
+ posWorldHull = float4 (posWorldHull.xyz + o.wNormal * outlineWidth, 1 );
92
+
93
+ UNITY_TRANSFER_FOG (o, o.pos);
94
+ UNITY_TRANSFER_FOG (o, UnityWorldToClipPos (posWorldHull));
95
+ posWorldHull.xyz = posWorldHull.xyz + dirView * _Offset_Z;
96
+ o.pos = UnityWorldToClipPos (posWorldHull);
97
+ #ifdef VERTEXLIGHT_ON
98
+ float3 vertTo0;
99
+ o.vertexLighting = softShade4PointLights_Atten (
100
+ unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0
101
+ , unity_LightColor
102
+ , unity_4LightAtten0
103
+ , o.worldPos, o.wNormal, vertTo0);
104
+ #endif
105
+ #ifdef UNITY_PASS_FORWARDBASE
106
+ o.dirGI = GIDominantDir ();
107
+ #endif
108
+ return o;
109
+ }
110
+
111
+
112
+
113
+
114
+
115
+
116
+ //// frag
117
+ float4 frag (
118
+ VertexOutput i,
119
+ bool frontFace : SV_IsFrontFace ) : SV_Target {
120
+ UNITY_SETUP_INSTANCE_ID (i);
121
+ bool isAmbientOnlyMap = !(any (_LightColor0.rgb));
122
+ bool isBackFace = !frontFace;
123
+ //// dynamic shadow
124
+ //// found dynamic shadows dont work in the spatiality of outline hulls.
125
+ half shadowAtten = 1 ;
126
+ #ifdef DIRECTIONAL
127
+ half lightAtten = 1 ;
128
+ #else
129
+ UNITY_LIGHT_ATTENUATION_NOSHADOW (lightAtten, i, i.worldPos.xyz);
130
+ #endif
131
+
132
+ //// world light albedo
133
+ #ifdef UNITY_PASS_FORWARDBASE
134
+ //// prepare cubemap albedo support lighting
135
+ // half3 refGIcol = shadeSH9LinearAndWhole(float4(normalize(i.wNormal + dEnv.dirViewReflection),1)); //// gi light at a weird angle
136
+ // half3 colGIGray = LinearRgbToLuminance_ac(refGIcol);
137
+
138
+ //// get vertex lighting
139
+ half3 vertexLit = i.vertexLighting;
140
+ //// build indirect light source
141
+ half3 lightIndirectColAve = DecodeLightProbe_average (); //// L0 Average light
142
+ half3 lightIndirectColL1 = max (0 , SHEvalDirectL1 (normalize (i.dirGI))); //// L1 raw. Add to L0 as max color of GI
143
+ half3 lightIndirectColStatic = 0 , lightIndirectColDir = 0 ;
144
+ // if ((_indirectGIDirectionalMix) < 1)
145
+ if (true )
146
+ {
147
+ half3 stackIndirectMaxL0L1 = lightIndirectColL1 + lightIndirectColAve;
148
+ half ratioCols = RatioOfColors (stackIndirectMaxL0L1, lightIndirectColAve, _indirectAlbedoMaxAveScale);
149
+ lightIndirectColStatic = lerp (stackIndirectMaxL0L1, lightIndirectColAve, ratioCols);
150
+ }
151
+ if (_indirectGIDirectionalMix > 0 )
152
+ {
153
+ float4 indirectGIDirectionBlur = float4 (i.wNormal, (_indirectGIBlur + 0.001 ) );
154
+ lightIndirectColDir = max (0 , ShadeSH9_ac (indirectGIDirectionBlur)) / (indirectGIDirectionBlur.w);
155
+ }
156
+ half3 lightIndirectCol = lerp (lightIndirectColStatic, lightIndirectColDir, _indirectGIDirectionalMix);
157
+
158
+ //// build direct, indirect
159
+ half3 lightDirect = _LightColor0.rgb;
160
+ half3 lightIndirectSource = (lightIndirectCol);
161
+ half3 lightDirectSource = 0 ;
162
+ if (isAmbientOnlyMap) //// this setup sucks for preserving Direct light effects
163
+ {
164
+ if (any (lightIndirectColL1)) //// L1 in pure ambient maps is black. Recover by spliting indirect energy.
165
+ {
166
+ lightDirectSource = lightIndirectColL1;
167
+ }
168
+ else
169
+ {
170
+ lightDirectSource = lightIndirectColAve * .2 ;
171
+ lightIndirectSource = lightIndirectColAve * .7 ;
172
+ }
173
+ }
174
+ else
175
+ {
176
+ lightDirectSource = lightDirect;
177
+ }
178
+ lightDirectSource = (lightDirectSource + vertexLit) * _directLightIntensity;
179
+ lightIndirectSource += vertexLit;
180
+
181
+ #elif UNITY_PASS_FORWARDADD
182
+ float3 lightDirect = _LightColor0.rgb;
183
+ lightDirect *= lightAtten;
184
+ //// out light source by types
185
+ float3 lightDirectSource = lightDirect * _directLightIntensity;
186
+ float3 lightIndirectSource = 0 ;
187
+ #endif
188
+
189
+ //// simple light systems reused
190
+ // half3 lightSimpleSystem = (lightDirectSource * shadowAtten) + lightIndirectSource;
191
+ lightDirect = _LightColor0.rgb;
192
+ #ifdef UNITY_PASS_FORWARDBASE
193
+ half3 cubeMapAveAlbedo = ((lightDirect * max (_shadowCastMin_black,_LightShadowData.x) * .5 ) + lightDirect ) * .5 + lightIndirectSource;
194
+ half lightAverageLum = LinearRgbToLuminance_ac (cubeMapAveAlbedo);
195
+ #elif UNITY_PASS_FORWARDADD
196
+ half3 cubeMapAveAlbedo = ((lightDirect * max (_shadowCastMin_black,_LightShadowData.x) * .5 ) + lightDirect) * .5 * lightAtten;
197
+ half lightAverageLum = LinearRgbToLuminance_ac (cubeMapAveAlbedo);
198
+ #endif
199
+
200
+ //// maintex
201
+ UV_DD uv_toon = UVDD ( TRANSFORM_TEX ( i.uv0, _MainTex));
202
+ float4 mainTex = _MainTex.SampleGrad (sampler_MainTex_trilinear_repeat, uv_toon.uv, uv_toon.dx, uv_toon.dy);
203
+
204
+ //// clip & alpha handling. Here so clip() may interrupt flow.
205
+ if (!(i.outlineThick)) //// a black mask means nothing
206
+ {
207
+ clip (-1 );
208
+ }
209
+ #ifndef NotAlpha
210
+ half4 clipMask = _ClippingMask.Sample (sampler_MainTex_trilinear_repeat, TRANSFORM_TEX (i.uv0, _ClippingMask));
211
+ half useMainTexAlpha = (_IsBaseMapAlphaAsClippingMask) ? mainTex.a : clipMask.r;
212
+ half alpha = (_Inverse_Clipping) ? (1.0 - useMainTexAlpha) : useMainTexAlpha;
213
+
214
+ half clipTest = (alpha - _Clipping_Level);
215
+ clip (clipTest);
216
+
217
+ #ifndef IsClip
218
+ alpha = saturate (alpha + _Tweak_transparency);
219
+ #ifdef UseAlphaDither
220
+ // dither pattern with some a2c blending.
221
+ //// citation to Silent and Xiexe for guidance and research documentation.
222
+ //// assumes cutout blending + alpha to coverage. Subtracted alpha must return.
223
+ float dither = ScreenDitherToAlphaCutout_ac (screenUV.xy, (1 - alpha));
224
+ alpha = alpha - dither;
225
+ clip (alpha);
226
+ #endif //// UseAlphaDither
227
+ alpha = saturate (alpha);
228
+ #else //// IsClip
229
+ alpha = 1 ;
230
+ #endif //// IsClip
231
+ #else //// NotAlpha
232
+ float alpha = 1 ;
233
+ #endif //// NotAlpha
234
+
235
+ //// albedo mixer
236
+ float4 outlineTex = _OutlineTex.SampleGrad (sampler_MainTex_trilinear_repeat, uv_toon.uv, uv_toon.dx, uv_toon.dy);
237
+ // float4 outlineTex = tex2D( _OutlineTex, TRANSFORM_TEX( i.uv0, _OutlineTex));
238
+ float3 outlineColor = _Outline_Color.rgb;
239
+ UNITY_BRANCH
240
+ if (_Is_BlendBaseColor)
241
+ {
242
+ outlineColor *= mainTex.rgb;
243
+ }
244
+ UNITY_BRANCH
245
+ if (_Is_OutlineTex)
246
+ {
247
+ outlineColor *= outlineTex.rgb;
248
+ }
249
+ outlineColor *= cubeMapAveAlbedo;
250
+
251
+ //// color proccessing
252
+ if (_forceLightClamp)
253
+ {
254
+ float sceneIntensity = LinearRgbToLuminance_ac (lightDirectSource + lightIndirectSource); //// grab all light at max potencial
255
+ if (sceneIntensity > 1.0 ) //// bloom defaults at > 1.1
256
+ {
257
+ outlineColor.rgb = outlineColor.rgb / sceneIntensity;
258
+ }
259
+ }
260
+ if (!(_forceLightClamp)) /// non HDR self post pressing, like how Standard cheats on emission.
261
+ {
262
+ #ifndef UNITY_HDR_ON
263
+ //// non HDR maps recurve
264
+ float ExposureBias = 2 ;
265
+ float3 curr = Uncharted2Tonemap (outlineColor.rgb * ExposureBias);
266
+ float3 whiteScale = 1 / Uncharted2Tonemap (11.2 );
267
+ outlineColor.rgb = curr * whiteScale;
268
+ #endif
269
+ }
270
+
271
+ UNITY_APPLY_FOG ( i.fogCoord, outlineColor);
272
+ float4 outlineColorA = float4 (outlineColor, alpha);
273
+ return outlineColorA;
274
+ }
0 commit comments