summaryrefslogtreecommitdiff
path: root/VRCSDK3AvatarsLegacy/Assets/_PoiyomiShaders/Shaders/Includes/CGI_PoiLighting.cginc
blob: 37feb5cc8bcdc7b9640a16c23d621a1e2af97e0b (plain)
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
#ifndef POI_LIGHTING
    #define POI_LIGHTING
    
    int _LightingType;
    float _ForceLightDirection;
    float _ShadowStrength;
    float _OutlineShadowStrength;
    float _ShadowOffset;
    float3 _LightDirection;
    float _ForceShadowStrength;
    float _CastedShadowSmoothing;
    float _LightingIndirectContribution;
    float _AttenuationMultiplier;
    float _EnableLighting;
    float _LightingControlledUseLightColor;
    fixed _LightingStandardSmoothness;
    fixed _LightingStandardControlsToon;
    fixed _LightingMinLightBrightness;
    float _LightingUseShadowRamp;
    UNITY_DECLARE_TEX2D(_ToonRamp);
    fixed _LightingMonochromatic;
    
    uint _LightingNumRamps;
    UNITY_DECLARE_TEX2D_NOSAMPLER(_ToonRamp1);
    UNITY_DECLARE_TEX2D_NOSAMPLER(_ToonRamp2);
    half _LightingShadowStrength1;
    half _LightingShadowStrength2;
    half _ShadowOffset1;
    half _ShadowOffset2;
    
    fixed _LightingGradientStart;
    fixed _LightingGradientEnd;
    float3 _LightingStartColor;
    float3 _LightingEndColor;
    float _AOStrength;
    fixed _LightingDetailStrength;
    fixed _LightingAdditiveDetailStrength;
    fixed _LightingNoIndirectMultiplier;
    fixed _LightingNoIndirectThreshold;
    
    uint _LightingAdditiveType;
    fixed _LightingAdditiveGradientStart;
    fixed _LightingAdditiveGradientEnd;
    fixed _LightingAdditivePassthrough;
    /*
    UNITY_DECLARE_TEX2D_NOSAMPLER(_ToonRamp3);
    half _LightingShadowStrength3;
    half _ShadowOffset3;
    */
    
    POI_TEXTURE_NOSAMPLER(_LightingDetailShadows);
    POI_TEXTURE_NOSAMPLER(_LightingAOTex);
    POI_TEXTURE_NOSAMPLER(_LightingShadowMask);
    
    /*
    * Standard stuff Start
    */
    UnityLight CreateLight(float3 normal)
    {
        UnityLight light;
        light.dir = poiLight.direction;
        light.color = saturate(_LightColor0.rgb * lerp(1, poiLight.attenuation, _AttenuationMultiplier));
        light.ndotl = DotClamped(normal, poiLight.direction);
        return light;
    }
    
    float FadeShadows(float attenuation)
    {
        #if HANDLE_SHADOWS_BLENDING_IN_GI || ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS
            // UNITY_LIGHT_ATTENUATION doesn't fade shadows for us.
            
            #if ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS
                attenuation = lerp(1, poiLight.attenuation, _AttenuationMultiplier);
            #endif
            
            float viewZ = dot(_WorldSpaceCameraPos - poiMesh.worldPos, UNITY_MATRIX_V[2].xyz);
            float shadowFadeDistance = UnityComputeShadowFadeDistance(poiMesh.worldPos, viewZ);
            float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
            float bakedAttenuation = UnitySampleBakedOcclusion(poiMesh.lightmapUV.xy, poiMesh.worldPos);
            attenuation = UnityMixRealtimeAndBakedShadows(
                attenuation, bakedAttenuation, shadowFade
            );
        #endif
        
        return attenuation;
    }
    
    void ApplySubtractiveLighting(inout UnityIndirect indirectLight)
    {
        #if SUBTRACTIVE_LIGHTING
            poiLight.attenuation = FadeShadows(lerp(1, poiLight.attenuation, _AttenuationMultiplier));
            
            float ndotl = saturate(dot(i.normal, _WorldSpaceLightPos0.xyz));
            float3 shadowedLightEstimate = ndotl * (1 - poiLight.attenuation) * _LightColor0.rgb;
            float3 subtractedLight = indirectLight.diffuse - shadowedLightEstimate;
            subtractedLight = max(subtractedLight, unity_ShadowColor.rgb);
            subtractedLight = lerp(subtractedLight, indirectLight.diffuse, _LightShadowData.x);
            indirectLight.diffuse = min(subtractedLight, indirectLight.diffuse);
        #endif
    }
    
    UnityIndirect CreateIndirectLight(float3 normal)
    {
        UnityIndirect indirectLight;
        indirectLight.diffuse = 0;
        indirectLight.specular = 0;
        
        #if defined(FORWARD_BASE_PASS)
            #if defined(LIGHTMAP_ON)
                indirectLight.diffuse = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, poiMesh.lightmapUV.xy));
                
                #if defined(DIRLIGHTMAP_COMBINED)
                    float4 lightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER(
                        unity_LightmapInd, unity_Lightmap, poiMesh.lightmapUV.xy
                    );
                    indirectLight.diffuse = DecodeDirectionalLightmap(
                        indirectLight.diffuse, lightmapDirection, normal
                    );
                #endif
                ApplySubtractiveLighting(indirectLight);
            #endif
            
            #if defined(DYNAMICLIGHTMAP_ON)
                float3 dynamicLightDiffuse = DecodeRealtimeLightmap(
                    UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, poiMesh.lightmapUV.zw)
                );
                
                #if defined(DIRLIGHTMAP_COMBINED)
                    float4 dynamicLightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER(
                        unity_DynamicDirectionality, unity_DynamicLightmap,
                        poiMesh.lightmapUV.zw
                    );
                    indirectLight.diffuse += DecodeDirectionalLightmap(
                        dynamicLightDiffuse, dynamicLightmapDirection, normal
                    );
                #else
                    indirectLight.diffuse += dynamicLightDiffuse;
                #endif
            #endif
            
            #if !defined(LIGHTMAP_ON) && !defined(DYNAMICLIGHTMAP_ON)
                #if UNITY_LIGHT_PROBE_PROXY_VOLUME
                    if (unity_ProbeVolumeParams.x == 1)
                    {
                        indirectLight.diffuse = SHEvalLinearL0L1_SampleProbeVolume(
                            float4(normal, 1), poiMesh.worldPos
                        );
                        indirectLight.diffuse = max(0, indirectLight.diffuse);
                        #if defined(UNITY_COLORSPACE_GAMMA)
                            indirectLight.diffuse = LinearToGammaSpace(indirectLight.diffuse);
                        #endif
                    }
                    else
                    {
                        indirectLight.diffuse += max(0, ShadeSH9(float4(normal, 1)));
                    }
                #else
                    indirectLight.diffuse += max(0, ShadeSH9(float4(normal, 1)));
                #endif
            #endif
            
            float3 reflectionDir = reflect(-poiCam.viewDir, normal);
            Unity_GlossyEnvironmentData envData;
            envData.roughness = 1 - _LightingStandardSmoothness;
            envData.reflUVW = BoxProjection(
                reflectionDir, poiMesh.worldPos.xyz,
                unity_SpecCube0_ProbePosition,
                unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax
            );
            float3 probe0 = Unity_GlossyEnvironment(
                UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, envData
            );
            envData.reflUVW = BoxProjection(
                reflectionDir, poiMesh.worldPos.xyz,
                unity_SpecCube1_ProbePosition,
                unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax
            );
            #if UNITY_SPECCUBE_BLENDING
                float interpolator = unity_SpecCube0_BoxMin.w;
                UNITY_BRANCH
                if(interpolator < 0.99999)
                {
                    float3 probe1 = Unity_GlossyEnvironment(
                        UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0),
                        unity_SpecCube0_HDR, envData
                    );
                    indirectLight.specular = lerp(probe1, probe0, interpolator);
                }
                else
                {
                    indirectLight.specular = probe0;
                }
            #else
                indirectLight.specular = probe0;
            #endif
            
            float occlusion = lerp(1, POI2D_SAMPLER_PAN(_LightingAOTex, _MainTex, poiMesh.uv[_LightingAOTexUV], _LightingAOTexPan), _AOStrength);
            
            indirectLight.diffuse *= occlusion;
            indirectLight.diffuse = max(indirectLight.diffuse, _LightingMinLightBrightness);
            indirectLight.specular *= occlusion;
        #endif
        
        return indirectLight;
    }
    
    /*
    * Standard stuff End
    */
    
    half PoiDiffuse(half NdotV, half NdotL, half LdotH)
    {
        half fd90 = 0.5 + 2 * LdotH * LdotH * SmoothnessToPerceptualRoughness(.5);
        // Two schlick fresnel term
        half lightScatter = (1 + (fd90 - 1) * Pow5(1 - NdotL));
        half viewScatter = (1 + (fd90 - 1) * Pow5(1 - NdotV));
        
        return lightScatter * viewScatter;
    }
    
    float3 ShadeSH9Indirect()
    {
        return ShadeSH9(half4(0.0, -1.0, 0.0, 1.0));
    }
    
    float3 ShadeSH9Direct()
    {
        return ShadeSH9(half4(0.0, 1.0, 0.0, 1.0));
    }
    
    float3 ShadeSH9Normal(float3 normalDirection)
    {
        return ShadeSH9(half4(normalDirection, 1.0));
    }
    
    half3 GetSHLength()
    {
        half3 x, x1;
        x.r = length(unity_SHAr);
        x.g = length(unity_SHAg);
        x.b = length(unity_SHAb);
        x1.r = length(unity_SHBr);
        x1.g = length(unity_SHBg);
        x1.b = length(unity_SHBb);
        return x + x1;
    }
    
    float3 calculateRealisticLighting(float4 colorToLight)
    {
        return UNITY_BRDF_PBS(1, 0, 0, _LightingStandardSmoothness,
        poiMesh.normals[1], poiCam.viewDir, CreateLight(poiMesh.normals[1]), CreateIndirectLight(poiMesh.normals[1]));
    }
    
    void calculateBasePassLighting()
    {
        #ifdef SIMPLE
            _LightingType = 1;
            _LightingIndirectContribution = 0.2;
        #endif
        float AOMap = 1;
        float3 lightColor = poiLight.color;
        #ifndef OUTLINE
            AOMap = POI2D_SAMPLER_PAN(_LightingAOTex, _MainTex, poiMesh.uv[_LightingAOTexUV], _LightingAOTexPan);
            
            #ifdef FORWARD_BASE_PASS
                //poiLight.color = saturate(_LightColor0.rgb) + saturate(ShadeSH9(normalize(unity_SHAr + unity_SHAg + unity_SHAb)));
                float3 magic = saturate(ShadeSH9(normalize(unity_SHAr + unity_SHAg + unity_SHAb)));
                float3 normalLight = saturate(_LightColor0.rgb);
                lightColor = saturate(magic * lerp(1, AOMap, _AOStrength) + normalLight);
            #endif
        #endif
        
        float3 grayscale_vector = float3(.33333, .33333, .33333);
        float3 ShadeSH9Plus = GetSHLength();
        float3 ShadeSH9Minus = ShadeSH9(float4(0, 0, 0, 1));
        poiLight.directLighting = saturate(lerp(ShadeSH9Plus, lightColor, 1 - _LightingIndirectContribution));
        poiLight.indirectLighting = saturate(ShadeSH9Minus);
        
        float3 directLighting = lerp(poiLight.directLighting, dot(poiLight.directLighting, float3(0.299, 0.587, 0.114)), _LightingMonochromatic);
        float3 indirectLighting = lerp(poiLight.indirectLighting, dot(poiLight.indirectLighting, float3(0.299, 0.587, 0.114)), _LightingMonochromatic);

        if (max(max(indirectLighting.x, indirectLighting.y), indirectLighting.z) <= _LightingNoIndirectThreshold && max(max(directLighting.x, directLighting.y), directLighting.z) >= 0)
        {
            indirectLighting = directLighting * _LightingNoIndirectMultiplier;
        }
        
        half4 shadowStrength = 1;
        #ifndef OUTLINE
            #ifndef SIMPLE
                shadowStrength = POI2D_SAMPLER_PAN(_LightingShadowMask, _MainTex, poiMesh.uv[_LightingShadowMaskUV], _LightingShadowMaskPan);
            #endif
            shadowStrength *= half4(_ShadowStrength, _LightingShadowStrength1, _LightingShadowStrength2, 0);
        #else
            shadowStrength = _OutlineShadowStrength;
        #endif
        
        float bw_lightColor = dot(lightColor, grayscale_vector);
        float bw_directLighting = (((poiLight.nDotL * 0.5 + 0.5) * bw_lightColor * lerp(1, poiLight.attenuation, _AttenuationMultiplier)) + dot(ShadeSH9Normal(poiMesh.normals[1]), grayscale_vector));
        float bw_bottomIndirectLighting = dot(ShadeSH9Minus, grayscale_vector);
        float bw_topIndirectLighting = dot(ShadeSH9Plus, grayscale_vector);
        float lightDifference = ((bw_topIndirectLighting + bw_lightColor) - bw_bottomIndirectLighting);
        
        fixed detailShadow = lerp(1, POI2D_SAMPLER_PAN(_LightingDetailShadows, _MainTex, poiMesh.uv[_LightingDetailShadowsUV], _LightingDetailShadowsPan), _LightingDetailStrength).r;
        poiLight.lightMap = smoothstep(0, lightDifference, bw_directLighting - bw_bottomIndirectLighting);
        poiLight.lightMap *= detailShadow;
        poiLight.rampedLightMap = lerp(1, UNITY_SAMPLE_TEX2D(_ToonRamp, poiLight.lightMap + _ShadowOffset), shadowStrength.r);
        
        UNITY_BRANCH
        if(_LightingNumRamps >= 2)
        {
            poiLight.rampedLightMap *= lerp(1, UNITY_SAMPLE_TEX2D_SAMPLER(_ToonRamp1, _ToonRamp, poiLight.lightMap + _ShadowOffset1), shadowStrength.g);
        }
        UNITY_BRANCH
        if(_LightingNumRamps >= 3)
        {
            poiLight.rampedLightMap *= lerp(1, UNITY_SAMPLE_TEX2D_SAMPLER(_ToonRamp2, _ToonRamp, poiLight.lightMap + _ShadowOffset2), shadowStrength.b);
        }
        
        UNITY_BRANCH
        if(_LightingStandardControlsToon)
        {
            float3 realisticLighting = calculateRealisticLighting(1);
            poiLight.rampedLightMap = UNITY_SAMPLE_TEX2D(_ToonRamp, (.5 + dot(realisticLighting, float3(.33333, .33333, .33333)) * .5) + _ShadowOffset);
            return;
        }
        
        UNITY_BRANCH
        if(_LightingType == 0)
        {
            poiLight.finalLighting = lerp(indirectLighting * lerp(1, AOMap, _AOStrength), directLighting, poiLight.rampedLightMap);
        }
        UNITY_BRANCH
        if(_LightingType == 1)
        {
            poiLight.finalLighting = lerp(poiLight.rampedLightMap * directLighting * lerp(1, AOMap, _AOStrength), directLighting, poiLight.rampedLightMap);
        }
        UNITY_BRANCH
        if(_LightingType == 3)
        {
            poiLight.finalLighting = lerp(saturate(directLighting * _LightingStartColor), saturate(indirectLighting * _LightingEndColor * lerp(1, AOMap, _AOStrength)), smoothstep(_LightingGradientStart, _LightingGradientEnd, 1 - poiLight.lightMap));
        }
    }
    
    float3 calculateNonImportantLighting(float attenuation, float attenuationDotNL, float3 albedo, float3 lightColor, half dotNL)
    {
        UNITY_BRANCH
        if(_LightingAdditiveType == 0)
        {
            return lightColor * attenuationDotNL;
        }
        else
        {
            fixed detailShadow = lerp(1, POI2D_SAMPLER_PAN(_LightingDetailShadows, _MainTex, poiMesh.uv[_LightingDetailShadowsUV], _LightingDetailShadowsPan), _LightingAdditiveDetailStrength).r;
            return lerp(lightColor * attenuation, lightColor * _LightingAdditivePassthrough * attenuation, smoothstep(_LightingAdditiveGradientStart, _LightingAdditiveGradientEnd, dotNL)) * detailShadow;
        }
    }
    
    float3 calculateLighting(float3 albedo)
    {
        #ifdef SIMPLE
            _LightingType = 1;
        #endif
        #ifdef FORWARD_BASE_PASS
            calculateBasePassLighting();

            #ifdef VERTEXLIGHT_ON
                poiLight.vFinalLighting = 0;
                
                for (int index = 0; index < 4; index ++)
                {
                    poiLight.vFinalLighting += calculateNonImportantLighting(poiLight.vAttenuation[index], poiLight.vAttenuationDotNL[index], albedo, poiLight.vColor[index], poiLight.vCorrectedDotNL[index]);
                }
            #endif
        #else
            #if defined(POINT) || defined(SPOT)
                #ifndef SIMPLE
                    fixed detailShadow = lerp(1, POI2D_SAMPLER_PAN(_LightingDetailShadows, _MainTex, poiMesh.uv[_LightingDetailShadowsUV], _LightingDetailShadowsPan), _LightingAdditiveDetailStrength).r;
                    UNITY_BRANCH
                    if(_LightingAdditiveType == 0)
                    {
                        return poiLight.color * poiLight.attenuation * max(0, poiLight.nDotL) * detailShadow;
                    }
                    else
                    {
                        return lerp(poiLight.color * max(poiLight.additiveShadow, _LightingAdditivePassthrough), poiLight.color * _LightingAdditivePassthrough, smoothstep(_LightingAdditiveGradientStart, _LightingAdditiveGradientEnd, 1 - (.5 * poiLight.nDotL + .5))) * poiLight.attenuation * detailShadow;
                    }
                #else
                    poiLight.finalLighting = poiLight.color * poiLight.attenuation;
                #endif
            #endif
        #endif
        
        #ifdef FORWARD_BASE_PASS
            UNITY_BRANCH
            if(_LightingType == 2)
            {
                float3 realisticLighting = calculateRealisticLighting(finalColor).rgb;
                return lerp(realisticLighting, dot(realisticLighting, float3(0.299, 0.587, 0.114)), _LightingMonochromatic);
            }
            else
            {
                return max(poiLight.finalLighting, _LightingMinLightBrightness);
            }
        #else
            return max(poiLight.finalLighting, _LightingMinLightBrightness);
        #endif
    }
#endif