yum-archive/2ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum-archive/2ner

yumbuncha shitttt0a8d744

master
51.1 KiB1277 linesraw
1#ifndef __FILAMENTED_INC
2#define __FILAMENTED_INC
3
4#include "SharedSamplingLib.hlsl"
5#include "SharedFilteringLib.hlsl"
6
7#include "UnityImageBasedLighting.cginc"
8#include "UnityStandardUtils.cginc"
9
10#include "data.cginc"
11#include "math.cginc"
12
13// I made changes to this code.
14
15/*
16                                 Apache License
17                           Version 2.0, January 2004
18                        http://www.apache.org/licenses/
19
20   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
21
22   1. Definitions.
23
24      "License" shall mean the terms and conditions for use, reproduction,
25      and distribution as defined by Sections 1 through 9 of this document.
26
27      "Licensor" shall mean the copyright owner or entity authorized by
28      the copyright owner that is granting the License.
29
30      "Legal Entity" shall mean the union of the acting entity and all
31      other entities that control, are controlled by, or are under common
32      control with that entity. For the purposes of this definition,
33      "control" means (i) the power, direct or indirect, to cause the
34      direction or management of such entity, whether by contract or
35      otherwise, or (ii) ownership of fifty percent (50%) or more of the
36      outstanding shares, or (iii) beneficial ownership of such entity.
37
38      "You" (or "Your") shall mean an individual or Legal Entity
39      exercising permissions granted by this License.
40
41      "Source" form shall mean the preferred form for making modifications,
42      including but not limited to software source code, documentation
43      source, and configuration files.
44
45      "Object" form shall mean any form resulting from mechanical
46      transformation or translation of a Source form, including but
47      not limited to compiled object code, generated documentation,
48      and conversions to other media types.
49
50      "Work" shall mean the work of authorship, whether in Source or
51      Object form, made available under the License, as indicated by a
52      copyright notice that is included in or attached to the work
53      (an example is provided in the Appendix below).
54
55      "Derivative Works" shall mean any work, whether in Source or Object
56      form, that is based on (or derived from) the Work and for which the
57      editorial revisions, annotations, elaborations, or other modifications
58      represent, as a whole, an original work of authorship. For the purposes
59      of this License, Derivative Works shall not include works that remain
60      separable from, or merely link (or bind by name) to the interfaces of,
61      the Work and Derivative Works thereof.
62
63      "Contribution" shall mean any work of authorship, including
64      the original version of the Work and any modifications or additions
65      to that Work or Derivative Works thereof, that is intentionally
66      submitted to Licensor for inclusion in the Work by the copyright owner
67      or by an individual or Legal Entity authorized to submit on behalf of
68      the copyright owner. For the purposes of this definition, "submitted"
69      means any form of electronic, verbal, or written communication sent
70      to the Licensor or its representatives, including but not limited to
71      communication on electronic mailing lists, source code control systems,
72      and issue tracking systems that are managed by, or on behalf of, the
73      Licensor for the purpose of discussing and improving the Work, but
74      excluding communication that is conspicuously marked or otherwise
75      designated in writing by the copyright owner as "Not a Contribution."
76
77      "Contributor" shall mean Licensor and any individual or Legal Entity
78      on behalf of whom a Contribution has been received by Licensor and
79      subsequently incorporated within the Work.
80
81   2. Grant of Copyright License. Subject to the terms and conditions of
82      this License, each Contributor hereby grants to You a perpetual,
83      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
84      copyright license to reproduce, prepare Derivative Works of,
85      publicly display, publicly perform, sublicense, and distribute the
86      Work and such Derivative Works in Source or Object form.
87
88   3. Grant of Patent License. Subject to the terms and conditions of
89      this License, each Contributor hereby grants to You a perpetual,
90      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
91      (except as stated in this section) patent license to make, have made,
92      use, offer to sell, sell, import, and otherwise transfer the Work,
93      where such license applies only to those patent claims licensable
94      by such Contributor that are necessarily infringed by their
95      Contribution(s) alone or by combination of their Contribution(s)
96      with the Work to which such Contribution(s) was submitted. If You
97      institute patent litigation against any entity (including a
98      cross-claim or counterclaim in a lawsuit) alleging that the Work
99      or a Contribution incorporated within the Work constitutes direct
100      or contributory patent infringement, then any patent licenses
101      granted to You under this License for that Work shall terminate
102      as of the date such litigation is filed.
103
104   4. Redistribution. You may reproduce and distribute copies of the
105      Work or Derivative Works thereof in any medium, with or without
106      modifications, and in Source or Object form, provided that You
107      meet the following conditions:
108
109      (a) You must give any other recipients of the Work or
110          Derivative Works a copy of this License; and
111
112      (b) You must cause any modified files to carry prominent notices
113          stating that You changed the files; and
114
115      (c) You must retain, in the Source form of any Derivative Works
116          that You distribute, all copyright, patent, trademark, and
117          attribution notices from the Source form of the Work,
118          excluding those notices that do not pertain to any part of
119          the Derivative Works; and
120
121      (d) If the Work includes a "NOTICE" text file as part of its
122          distribution, then any Derivative Works that You distribute must
123          include a readable copy of the attribution notices contained
124          within such NOTICE file, excluding those notices that do not
125          pertain to any part of the Derivative Works, in at least one
126          of the following places: within a NOTICE text file distributed
127          as part of the Derivative Works; within the Source form or
128          documentation, if provided along with the Derivative Works; or,
129          within a display generated by the Derivative Works, if and
130          wherever such third-party notices normally appear. The contents
131          of the NOTICE file are for informational purposes only and
132          do not modify the License. You may add Your own attribution
133          notices within Derivative Works that You distribute, alongside
134          or as an addendum to the NOTICE text from the Work, provided
135          that such additional attribution notices cannot be construed
136          as modifying the License.
137
138      You may add Your own copyright statement to Your modifications and
139      may provide additional or different license terms and conditions
140      for use, reproduction, or distribution of Your modifications, or
141      for any such Derivative Works as a whole, provided Your use,
142      reproduction, and distribution of the Work otherwise complies with
143      the conditions stated in this License.
144
145   5. Submission of Contributions. Unless You explicitly state otherwise,
146      any Contribution intentionally submitted for inclusion in the Work
147      by You to the Licensor shall be under the terms and conditions of
148      this License, without any additional terms or conditions.
149      Notwithstanding the above, nothing herein shall supersede or modify
150      the terms of any separate license agreement you may have executed
151      with Licensor regarding such Contributions.
152
153   6. Trademarks. This License does not grant permission to use the trade
154      names, trademarks, service marks, or product names of the Licensor,
155      except as required for reasonable and customary use in describing the
156      origin of the Work and reproducing the content of the NOTICE file.
157
158   7. Disclaimer of Warranty. Unless required by applicable law or
159      agreed to in writing, Licensor provides the Work (and each
160      Contributor provides its Contributions) on an "AS IS" BASIS,
161      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
162      implied, including, without limitation, any warranties or conditions
163      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
164      PARTICULAR PURPOSE. You are solely responsible for determining the
165      appropriateness of using or redistributing the Work and assume any
166      risks associated with Your exercise of permissions under this License.
167
168   8. Limitation of Liability. In no event and under no legal theory,
169      whether in tort (including negligence), contract, or otherwise,
170      unless required by applicable law (such as deliberate and grossly
171      negligent acts) or agreed to in writing, shall any Contributor be
172      liable to You for damages, including any direct, indirect, special,
173      incidental, or consequential damages of any character arising as a
174      result of this License or out of the use or inability to use the
175      Work (including but not limited to damages for loss of goodwill,
176      work stoppage, computer failure or malfunction, or any and all
177      other commercial damages or losses), even if such Contributor
178      has been advised of the possibility of such damages.
179
180   9. Accepting Warranty or Additional Liability. While redistributing
181      the Work or Derivative Works thereof, You may choose to offer,
182      and charge a fee for, acceptance of support, warranty, indemnity,
183      or other liability obligations and/or rights consistent with this
184      License. However, in accepting such obligations, You may act only
185      on Your own behalf and on Your sole responsibility, not on behalf
186      of any other Contributor, and only if You agree to indemnify,
187      defend, and hold each Contributor harmless for any liability
188      incurred by, or claims asserted against, such Contributor by reason
189      of your accepting any such warranty or additional liability.
190
191   END OF TERMS AND CONDITIONS
192
193   APPENDIX: How to apply the Apache License to your work.
194
195      To apply the Apache License to your work, attach the following
196      boilerplate notice, with the fields enclosed by brackets "[]"
197      replaced with your own identifying information. (Don't include
198      the brackets!)  The text should be enclosed in the appropriate
199      comment syntax for the file format. We also recommend that a
200      file or class name and description of purpose be included on the
201      same "printed page" as the copyright notice for easier
202      identification within third-party archives.
203
204   Copyright [yyyy] [name of copyright owner]
205
206   Licensed under the Apache License, Version 2.0 (the "License");
207   you may not use this file except in compliance with the License.
208   You may obtain a copy of the License at
209
210       http://www.apache.org/licenses/LICENSE-2.0
211
212   Unless required by applicable law or agreed to in writing, software
213   distributed under the License is distributed on an "AS IS" BASIS,
214   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
215   See the License for the specific language governing permissions and
216   limitations under the License.
217
218Unity Built-in Shaders   
219
220Copyright (c) 2016 Unity Technologies
221
222Permission is hereby granted, free of charge, to any person obtaining a copy of
223this software and associated documentation files (the "Software"), to deal in
224the Software without restriction, including without limitation the rights to
225use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
226of the Software, and to permit persons to whom the Software is furnished to do
227so, subject to the following conditions:
228
229The above copyright notice and this permission notice shall be included in all
230copies or substantial portions of the Software.
231
232THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
233IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
234FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
235COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
236IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
237CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
238*/
239
240// Check if Bakery is available
241#if defined(_BAKERY_RNM) || defined(_BAKERY_SH) || defined(_BAKERY_MONOSH)
242    #define USING_BAKERY 1
243#endif
244
245// Bakery textures (Unity auto-binds these)
246#if defined(_BAKERY_RNM) || defined(_BAKERY_SH) || defined(_BAKERY_MONOSH)
247TEXTURE2D(_RNM0);
248TEXTURE2D(_RNM1);
249TEXTURE2D(_RNM2);
250SAMPLER(sampler_RNM0);
251#endif
252
253
254
255#define MIN_PERCEPTUAL_ROUGHNESS 0.045
256
257// Filamented defines for spherical harmonics
258#define SPHERICAL_HARMONICS_DEFAULT         0
259#define SPHERICAL_HARMONICS_GEOMETRICS      1
260#define SPHERICAL_HARMONICS_ZH3             2
261#define SPHERICAL_HARMONICS SPHERICAL_HARMONICS_ZH3
262#define SPHERICAL_HARMONICS_USE_L2          0
263
264// Light struct from filamented
265struct Light {
266    float4 colorIntensity;
267    float3 l;
268    float attenuation;
269    float NoL;
270    float3 worldPosition;
271};
272
273// Helper functions
274half getExposureOcclusionBias()
275{
276    return 1.0/(_ExposureOcclusion);
277}
278
279bool getIsBakeryVertexMode()
280{
281#if defined(USING_BAKERY_VERTEXLM)
282    #define BAKERYMODE_DEFAULT 0
283    #define BAKERYMODE_VERTEXLM 1.0f
284    #define BAKERYMODE_RNM 2.0f
285    #define BAKERYMODE_SH 3.0f
286    return (bakeryLightmapMode == BAKERYMODE_VERTEXLM);
287#endif
288    return false;
289}
290
291half getLightVolumeSurfaceBias()
292{
293    #if defined(_VRCLV)
294    return _VRCLVSurfaceBias;
295    #else
296    return 0;
297    #endif
298}
299
300// Geomerics spherical harmonics evaluation
301float shEvaluateDiffuseL1Geomerics_local(float L0, float3 L1, float3 n)
302{
303    float R0 = max(L0, 0);
304    float3 R1 = 0.5f * L1;
305    float lenR1 = length(R1);
306    float q = dot(normalize(R1), n) * 0.5 + 0.5;
307    q = saturate(q);
308    float p = 1.0f + 2.0f * lenR1 / R0;
309    float a = (1.0f - lenR1 / R0) / (1.0f + lenR1 / R0);
310    return R0 * (a + (1.0f - a) * (p + 1.0f) * pow(q, p));
311}
312
313// ZH3 constants and functions
314const static float L0IrradianceToRadiance = 2 * sqrt(UNITY_PI);
315const static float L1IrradianceToRadiance = sqrt(3 * UNITY_PI);
316const static float4 L0L1IrradianceToRadiance = float4(L0IrradianceToRadiance, L1IrradianceToRadiance, L1IrradianceToRadiance, L1IrradianceToRadiance);
317
318float SHEvalLinearL0L1_ZH3Hallucinate(float4 sh, float3 normal)
319{
320    float4 radiance = sh * L0L1IrradianceToRadiance;
321    float3 zonalAxis = float3(radiance.w, radiance.y, radiance.z);
322    float l1Length = length(zonalAxis);
323    zonalAxis /= l1Length;
324    float ratio = l1Length / radiance.x;
325    float zonalL2Coeff = radiance.x * ratio * (0.08 + 0.6 * ratio);
326    float fZ = dot(zonalAxis, normal);
327    float zhNormal = sqrt(5.0f / (16.0f * UNITY_PI)) * (3.0f * fZ * fZ - 1.0f);
328    float result = dot(sh, float4(1, float3(normal.y, normal.z, normal.x)));
329    result += 0.25f * zhNormal * zonalL2Coeff;
330    return result;
331}
332
333float3 SHEvalLinearL0L1_ZH3Hallucinate(float3 normal)
334{
335    float3 shL0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w) +
336        float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z) / 3.0;
337    float3 shL1_1 = float3(unity_SHAr.y, unity_SHAg.y, unity_SHAb.y);
338    float3 shL1_2 = float3(unity_SHAr.z, unity_SHAg.z, unity_SHAb.z);
339    float3 shL1_3 = float3(unity_SHAr.x, unity_SHAg.x, unity_SHAb.x);
340
341    float3 result = 0.0;
342    float4 a = float4(shL0.r, shL1_1.r, shL1_2.r, shL1_3.r);
343    float4 b = float4(shL0.g, shL1_1.g, shL1_2.g, shL1_3.g);
344    float4 c = float4(shL0.b, shL1_1.b, shL1_2.b, shL1_3.b);
345    result.r = SHEvalLinearL0L1_ZH3Hallucinate(a, normal);
346    result.g = SHEvalLinearL0L1_ZH3Hallucinate(b, normal);
347    result.b = SHEvalLinearL0L1_ZH3Hallucinate(c, normal);
348    return result;
349}
350
351float3 Irradiance_SphericalHarmonics(const float3 n, const bool useL2) {
352    float3 finalSH = float3(0,0,0); 
353
354    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_DEFAULT)
355        finalSH = SHEvalLinearL0L1(half4(n, 1.0));
356    #endif
357
358    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_GEOMETRICS)
359        float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
360        float3 L0L2 = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z) / 3.0;
361        L0 = (useL2) ? L0+L0L2 : L0-L0L2;
362        finalSH.r = shEvaluateDiffuseL1Geomerics_local(L0.r, unity_SHAr.xyz, n);
363        finalSH.g = shEvaluateDiffuseL1Geomerics_local(L0.g, unity_SHAg.xyz, n);
364        finalSH.b = shEvaluateDiffuseL1Geomerics_local(L0.b, unity_SHAb.xyz, n);
365    #endif
366
367    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3)
368        finalSH = SHEvalLinearL0L1_ZH3Hallucinate(half4(n, 1.0));
369    #endif
370
371    #if (SPHERICAL_HARMONICS_USE_L2 == 1)
372        if (useL2) finalSH += SHEvalLinearL2(half4(n, 1.0));
373    #endif    
374
375    return finalSH;
376}
377
378float3 Irradiance_SphericalHarmonics(const float3 n) {
379    return Irradiance_SphericalHarmonics(n, true);
380}
381
382#if UNITY_LIGHT_PROBE_PROXY_VOLUME
383half3 Irradiance_SampleProbeVolume (half4 normal, float3 worldPos)
384{
385    const float transformToLocal = unity_ProbeVolumeParams.y;
386    const float texelSizeX = unity_ProbeVolumeParams.z;
387
388    float3 position = (transformToLocal == 1.0f) ? mul(unity_ProbeVolumeWorldToObject, float4(worldPos, 1.0)).xyz : worldPos;
389    float3 texCoord = (position - unity_ProbeVolumeMin.xyz) * unity_ProbeVolumeSizeInv.xyz;
390    texCoord.x = texCoord.x * 0.25f;
391
392    float texCoordX = clamp(texCoord.x, 0.5f * texelSizeX, 0.25f - 0.5f * texelSizeX);
393
394    texCoord.x = texCoordX;
395    half4 SHAr = UNITY_SAMPLE_TEX3D_SAMPLER(unity_ProbeVolumeSH, unity_ProbeVolumeSH, texCoord);
396
397    texCoord.x = texCoordX + 0.25f;
398    half4 SHAg = UNITY_SAMPLE_TEX3D_SAMPLER(unity_ProbeVolumeSH, unity_ProbeVolumeSH, texCoord);
399
400    texCoord.x = texCoordX + 0.5f;
401    half4 SHAb = UNITY_SAMPLE_TEX3D_SAMPLER(unity_ProbeVolumeSH, unity_ProbeVolumeSH, texCoord);
402
403    half3 x1;
404
405    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_DEFAULT)
406        x1.r = dot(SHAr, normal);
407        x1.g = dot(SHAg, normal);
408        x1.b = dot(SHAb, normal);
409    #endif
410
411    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_GEOMETRICS)
412        x1.r = shEvaluateDiffuseL1Geomerics_local(SHAr.w, SHAr.rgb, normal);
413        x1.g = shEvaluateDiffuseL1Geomerics_local(SHAg.w, SHAg.rgb, normal);
414        x1.b = shEvaluateDiffuseL1Geomerics_local(SHAb.w, SHAb.rgb, normal);
415    #endif
416
417    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3)
418        x1.r = SHEvalLinearL0L1_ZH3Hallucinate(float4(SHAr.w, SHAr.rgb), normal);
419        x1.g = SHEvalLinearL0L1_ZH3Hallucinate(float4(SHAg.w, SHAg.rgb), normal);
420        x1.b = SHEvalLinearL0L1_ZH3Hallucinate(float4(SHAb.w, SHAb.rgb), normal);
421    #endif
422
423    return x1;
424}
425#endif
426
427#if defined(_VRCLV)
428half3 Irradiance_SampleVRCLightVolume(half3 normal, float3 worldPos, out Light derivedLight)
429{
430    derivedLight = (Light)0;
431    float3 samplePos = worldPos + normal * getLightVolumeSurfaceBias();
432    
433    float3 L0, L1r, L1g, L1b;
434    LightVolumeSH(samplePos, L0, L1r, L1g, L1b);
435
436    half3 irradiance = 0.0;
437
438    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_DEFAULT)
439        irradiance.r = dot(L1r, normal.xyz) + L0.r;
440        irradiance.g = dot(L1g, normal.xyz) + L0.g;
441        irradiance.b = dot(L1b, normal.xyz) + L0.b;
442    #endif
443
444    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_GEOMETRICS)
445        irradiance.r = shEvaluateDiffuseL1Geomerics_local(L0.r, L1r, normal.xyz);
446        irradiance.g = shEvaluateDiffuseL1Geomerics_local(L0.g, L1g, normal.xyz);
447        irradiance.b = shEvaluateDiffuseL1Geomerics_local(L0.b, L1b, normal.xyz);
448    #endif
449
450    #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3)
451        irradiance.r = shEvaluateDiffuseL1Geomerics_local(L0.r, L1r, normal.xyz);
452        irradiance.g = shEvaluateDiffuseL1Geomerics_local(L0.g, L1g, normal.xyz);
453        irradiance.b = shEvaluateDiffuseL1Geomerics_local(L0.b, L1b, normal.xyz);
454    #endif
455    
456    #if defined(LIGHTMAP_SPECULAR)
457    float3 nL1x = float3(L1r[0], L1g[0], L1b[0]);
458    float3 nL1y = float3(L1r[1], L1g[1], L1b[1]);
459    float3 nL1z = float3(L1r[2], L1g[2], L1b[2]);
460    float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z));
461
462    derivedLight.l = dominantDir;
463    half directionality = max(FLT_EPS, length(derivedLight.l));
464    derivedLight.l /= directionality;
465
466    derivedLight.colorIntensity = float4(irradiance * directionality, 1.0);
467    derivedLight.attenuation = directionality;
468    derivedLight.NoL = saturate(dot(normal, derivedLight.l));
469    #endif
470
471    return irradiance;
472}
473
474half3 Irradiance_SampleVRCLightVolumeAdditive(half3 normal, float3 worldPos, out Light derivedLight)
475{
476    derivedLight = (Light)0;
477
478    if (!_UdonLightVolumeEnabled || _UdonLightVolumeAdditiveCount == 0) return 0;
479    
480    float3 L0, L1r, L1g, L1b;
481    LightVolumeAdditiveSH(worldPos, L0, L1r, L1g, L1b);
482
483    half3 irradiance = 0.0;
484    irradiance.r = dot(L1r, normal.xyz) + L0.r;
485    irradiance.g = dot(L1g, normal.xyz) + L0.g;
486    irradiance.b = dot(L1b, normal.xyz) + L0.b;
487    
488    #if defined(LIGHTMAP_SPECULAR)
489    float3 nL1x = float3(L1r[0], L1g[0], L1b[0]);
490    float3 nL1y = float3(L1r[1], L1g[1], L1b[1]);
491    float3 nL1z = float3(L1r[2], L1g[2], L1b[2]);
492    float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z));
493
494    derivedLight.l = dominantDir;
495    half directionality = max(FLT_EPS, length(derivedLight.l));
496    derivedLight.l /= directionality;
497
498    derivedLight.colorIntensity = float4(irradiance * directionality, 1.0);
499    derivedLight.attenuation = directionality;
500    derivedLight.NoL = saturate(dot(normal, derivedLight.l));
501    #endif
502
503    return irradiance;
504}
505#endif
506
507half3 Irradiance_SphericalHarmonicsUnity (half3 normal, half3 ambient, float3 worldPos, out Light derivedLight)
508{
509    half3 ambient_contrib = 0.0;
510    derivedLight = (Light)0;
511
512#if defined(_VRCLV)
513    #if UNITY_LIGHT_PROBE_PROXY_VOLUME
514        if (unity_ProbeVolumeParams.x == 1.0)
515            ambient_contrib = Irradiance_SampleProbeVolume(half4(normal, 1.0), worldPos);
516        else
517            ambient_contrib = Irradiance_SampleVRCLightVolume(normal, worldPos, derivedLight);
518    #else
519        ambient_contrib = Irradiance_SampleVRCLightVolume(normal, worldPos, derivedLight);
520    #endif
521
522    ambient += max(half3(0, 0, 0), ambient_contrib);
523
524    #ifdef UNITY_COLORSPACE_GAMMA
525        ambient = LinearToGammaSpace (ambient);
526    #endif
527
528    return ambient;
529#else
530
531    #if UNITY_SAMPLE_FULL_SH_PER_PIXEL
532        #if UNITY_LIGHT_PROBE_PROXY_VOLUME
533            if (unity_ProbeVolumeParams.x == 1.0)
534                ambient_contrib = Irradiance_SampleProbeVolume(half4(normal, 1.0), worldPos);
535            else
536                ambient_contrib = Irradiance_SphericalHarmonics(normal, true);
537        #else
538            ambient_contrib = Irradiance_SphericalHarmonics(normal, true);
539        #endif
540
541            ambient += max(half3(0, 0, 0), ambient_contrib);
542
543        #ifdef UNITY_COLORSPACE_GAMMA
544            ambient = LinearToGammaSpace(ambient);
545        #endif
546    #elif (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE
547        // Completely per-vertex
548    #else
549        #if UNITY_LIGHT_PROBE_PROXY_VOLUME
550            if (unity_ProbeVolumeParams.x == 1.0)
551                ambient_contrib = Irradiance_SampleProbeVolume (half4(normal, 1.0), worldPos);
552            else
553                ambient_contrib = Irradiance_SphericalHarmonics(normal, false);
554        #else
555            ambient_contrib = Irradiance_SphericalHarmonics(normal, false);
556        #endif
557
558        ambient = max(half3(0, 0, 0), ambient+ambient_contrib);
559        #ifdef UNITY_COLORSPACE_GAMMA
560            ambient = LinearToGammaSpace (ambient);
561        #endif
562    #endif
563
564    return ambient;
565#endif
566}
567
568float4 SampleLightmapBicubic(float2 uv)
569{
570    #if defined(SHADER_API_D3D11)
571        float width, height;
572        unity_Lightmap.GetDimensions(width, height);
573        float4 unity_Lightmap_TexelSize = float4(width, height, 1.0/width, 1.0/height);
574        return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap),
575            uv, unity_Lightmap_TexelSize);
576    #else
577        return SAMPLE_TEXTURE2D(unity_Lightmap, samplerunity_Lightmap, uv);
578    #endif
579}
580
581float4 SampleLightmapDirBicubic(float2 uv)
582{
583    #if defined(SHADER_API_D3D11) && false
584        float width, height;
585        unity_LightmapInd.GetDimensions(width, height);
586        float4 unity_LightmapInd_TexelSize = float4(width, height, 1.0/width, 1.0/height);
587        return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_LightmapInd, samplerunity_Lightmap),
588            uv, unity_LightmapInd_TexelSize);
589    #else
590        return SAMPLE_TEXTURE2D(unity_LightmapInd, samplerunity_Lightmap, uv);
591    #endif
592}
593
594float4 SampleDynamicLightmapBicubic(float2 uv)
595{
596    #if defined(SHADER_API_D3D11)
597        float width, height;
598        unity_DynamicLightmap.GetDimensions(width, height);
599        float4 unity_DynamicLightmap_TexelSize = float4(width, height, 1.0/width, 1.0/height);
600        return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_DynamicLightmap, samplerunity_DynamicLightmap),
601            uv, unity_DynamicLightmap_TexelSize);
602    #else
603        return SAMPLE_TEXTURE2D(unity_DynamicLightmap, samplerunity_DynamicLightmap, uv);
604    #endif
605}
606
607float4 SampleDynamicLightmapDirBicubic(float2 uv)
608{
609    #if defined(SHADER_API_D3D11) && false
610        float width, height;
611        unity_DynamicDirectionality.GetDimensions(width, height);
612        float4 unity_DynamicDirectionality_TexelSize = float4(width, height, 1.0/width, 1.0/height);
613        return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_DynamicDirectionality, samplerunity_DynamicLightmap),
614            uv, unity_DynamicDirectionality_TexelSize);
615    #else
616        return SAMPLE_TEXTURE2D(unity_DynamicDirectionality, samplerunity_DynamicLightmap, uv);
617    #endif
618}
619
620inline float3 DecodeDirectionalLightmapSpecular(half3 color, half4 dirTex, half3 normalWorld, 
621    const bool isRealtimeLightmap, fixed4 realtimeNormalTex, out Light o_light)
622{
623    o_light = (Light)0;
624    o_light.colorIntensity = float4(color, 1.0);
625    o_light.l = dirTex.xyz * 2 - 1;
626
627    half directionality = max(0.001, length(o_light.l));
628    o_light.l /= directionality;
629
630    #ifdef DYNAMICLIGHTMAP_ON
631    if (isRealtimeLightmap)
632    {
633        half3 realtimeNormal = realtimeNormalTex.xyz * 2 - 1;
634        o_light.colorIntensity /= max(0.125, dot(realtimeNormal, o_light.l));
635    }
636    #endif
637
638    half3 ambient = o_light.colorIntensity * (1 - directionality);
639    o_light.colorIntensity = o_light.colorIntensity * directionality;
640    o_light.attenuation = directionality;
641    o_light.NoL = saturate(dot(normalWorld, o_light.l));
642
643    return color;
644}
645
646#if defined(USING_BAKERY) && defined(LIGHTMAP_ON)
647float3 DecodeRNMLightmap(half3 color, half2 lightmapUV, half3 normalTangent, float3x3 tangentToWorld, out Light o_light)
648{
649    const float rnmBasis0 = float3(0.816496580927726f, 0, 0.5773502691896258f);
650    const float rnmBasis1 = float3(-0.4082482904638631f, 0.7071067811865475f, 0.5773502691896258f);
651    const float rnmBasis2 = float3(-0.4082482904638631f, -0.7071067811865475f, 0.5773502691896258f);
652
653    float3 irradiance;
654    o_light = (Light)0;
655
656    #if defined(SHADER_API_D3D11)
657        float width, height;
658        _RNM0.GetDimensions(width, height);
659        float4 rnm_TexelSize = float4(width, height, 1.0/width, 1.0/height);
660        
661        float3 rnm0 = DecodeLightmap(SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM0, sampler_RNM0), lightmapUV, rnm_TexelSize));
662        float3 rnm1 = DecodeLightmap(SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM1, sampler_RNM0), lightmapUV, rnm_TexelSize));
663        float3 rnm2 = DecodeLightmap(SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM2, sampler_RNM0), lightmapUV, rnm_TexelSize));
664    #else
665        float3 rnm0 = DecodeLightmap(SAMPLE_TEXTURE2D(_RNM0, sampler_RNM0, lightmapUV));
666        float3 rnm1 = DecodeLightmap(SAMPLE_TEXTURE2D(_RNM1, sampler_RNM0, lightmapUV));
667        float3 rnm2 = DecodeLightmap(SAMPLE_TEXTURE2D(_RNM2, sampler_RNM0, lightmapUV));
668    #endif
669
670    normalTangent.g *= -1;
671
672    irradiance =  saturate(dot(rnmBasis0, normalTangent)) * rnm0
673                + saturate(dot(rnmBasis1, normalTangent)) * rnm1
674                + saturate(dot(rnmBasis2, normalTangent)) * rnm2;
675
676    #if defined(LIGHTMAP_SPECULAR)
677    float3 dominantDirT = rnmBasis0 * luminance(rnm0) +
678                          rnmBasis1 * luminance(rnm1) +
679                          rnmBasis2 * luminance(rnm2);
680
681    float3 dominantDirTN = normalize(dominantDirT);
682    float3 specColor = saturate(dot(rnmBasis0, dominantDirTN)) * rnm0 +
683                       saturate(dot(rnmBasis1, dominantDirTN)) * rnm1 +
684                       saturate(dot(rnmBasis2, dominantDirTN)) * rnm2;                        
685
686    o_light.l = normalize(mul(tangentToWorld, dominantDirT));
687    half directionality = max(0.001, length(o_light.l));
688    o_light.l /= directionality;
689
690    o_light.colorIntensity = float4(specColor * directionality, 1.0);
691    o_light.attenuation = directionality;
692    o_light.NoL = saturate(dot(normalTangent, dominantDirTN));
693    #endif
694
695    return irradiance;
696}
697
698float3 DecodeSHLightmap(half3 L0, half2 lightmapUV, half3 normalWorld, out Light o_light)
699{
700    float3 irradiance;
701    o_light = (Light)0;
702
703    #if defined(SHADER_API_D3D11)
704        float width, height;
705        _RNM0.GetDimensions(width, height);
706        float4 rnm_TexelSize = float4(width, height, 1.0/width, 1.0/height);
707        
708        float3 nL1x = SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM0, sampler_RNM0), lightmapUV, rnm_TexelSize);
709        float3 nL1y = SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM1, sampler_RNM0), lightmapUV, rnm_TexelSize);
710        float3 nL1z = SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM2, sampler_RNM0), lightmapUV, rnm_TexelSize);
711    #else
712        float3 nL1x = SAMPLE_TEXTURE2D(_RNM0, sampler_RNM0, lightmapUV);
713        float3 nL1y = SAMPLE_TEXTURE2D(_RNM1, sampler_RNM0, lightmapUV);
714        float3 nL1z = SAMPLE_TEXTURE2D(_RNM2, sampler_RNM0, lightmapUV);
715    #endif
716
717    nL1x = nL1x * 2 - 1;
718    nL1y = nL1y * 2 - 1;
719    nL1z = nL1z * 2 - 1;
720    float3 L1x = nL1x * L0 * 2;
721    float3 L1y = nL1y * L0 * 2;
722    float3 L1z = nL1z * L0 * 2;
723
724    #ifdef BAKERY_SHNONLINEAR
725        float lumaL0 = dot(L0, float(1));
726        float lumaL1x = dot(L1x, float(1));
727        float lumaL1y = dot(L1y, float(1));
728        float lumaL1z = dot(L1z, float(1));
729
730        float lumaSH = shEvaluateDiffuseL1Geomerics_local(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld);
731
732        #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3)
733            lumaSH = SHEvalLinearL0L1_ZH3Hallucinate(float4(lumaL0, lumaL1y, lumaL1z, lumaL1x), normalWorld);
734        #endif
735
736        irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z;
737        float regularLumaSH = dot(irradiance, 1);
738        irradiance *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16));
739    #else
740        irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z;
741    #endif
742
743    #if defined(LIGHTMAP_SPECULAR)
744    float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z));
745
746    o_light.l = dominantDir;
747    half directionality = max(0.001, length(o_light.l));
748    o_light.l /= directionality;
749
750    o_light.colorIntensity = float4(irradiance * directionality, 1.0);
751    o_light.attenuation = directionality;
752    o_light.NoL = saturate(dot(normalWorld, o_light.l));
753    #endif
754
755    return irradiance;
756}
757
758float3 DecodeSHLightmapVertex(half3 L0, half3 ambientSH[3], half3 normalWorld, out Light o_light)
759{
760    float3 irradiance;
761    o_light = (Light)0;
762
763    float3 nL1x = ambientSH[0];
764    float3 nL1y = ambientSH[1];
765    float3 nL1z = ambientSH[2];
766
767    nL1x = nL1x * 2 - 1;
768    nL1y = nL1y * 2 - 1;
769    nL1z = nL1z * 2 - 1;
770    float3 L1x = nL1x * L0 * 2;
771    float3 L1y = nL1y * L0 * 2;
772    float3 L1z = nL1z * L0 * 2;
773
774    #ifdef BAKERY_SHNONLINEAR
775        float lumaL0 = dot(L0, float(1));
776        float lumaL1x = dot(L1x, float(1));
777        float lumaL1y = dot(L1y, float(1));
778        float lumaL1z = dot(L1z, float(1));
779        float lumaSH = shEvaluateDiffuseL1Geomerics_local(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld);
780
781        #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3)
782            lumaSH = SHEvalLinearL0L1_ZH3Hallucinate(float4(lumaL0, lumaL1y, lumaL1z, lumaL1x), normalWorld);
783        #endif
784
785        irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z;
786        float regularLumaSH = dot(irradiance, 1);
787        irradiance *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16));
788    #else
789        irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z;
790    #endif
791
792    #if defined(LIGHTMAP_SPECULAR)
793    float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z));
794
795    o_light.l = dominantDir;
796    half directionality = max(0.001, length(o_light.l));
797    o_light.l /= directionality;
798
799    o_light.colorIntensity = float4(irradiance * directionality, 1.0);
800    o_light.attenuation = directionality;
801    o_light.NoL = saturate(dot(normalWorld, o_light.l));
802    #endif
803
804    return irradiance;
805}
806#endif
807
808#if defined(_BAKERY_MONOSH)
809float3 DecodeMonoSHLightmap(half3 L0, half3 dominantDir, half3 normalWorld, out Light o_light, const bool remapDir = true)
810{
811    o_light = (Light)0;
812
813    float3 nL1 = remapDir? dominantDir * 2 - 1 : dominantDir;
814    float3 L1x = nL1.x * L0 * 2;
815    float3 L1y = nL1.y * L0 * 2;
816    float3 L1z = nL1.z * L0 * 2;
817
818    float3 sh;
819
820    #if BAKERY_SHNONLINEAR
821        float lumaL0 = dot(L0, 1);
822        float lumaL1x = dot(L1x, 1);
823        float lumaL1y = dot(L1y, 1);
824        float lumaL1z = dot(L1z, 1);
825        float lumaSH = shEvaluateDiffuseL1Geomerics_local(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld);
826
827        #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3)
828            lumaSH = SHEvalLinearL0L1_ZH3Hallucinate(float4(lumaL0, lumaL1y, lumaL1z, lumaL1x), normalWorld);
829        #endif
830
831        sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z;
832        float regularLumaSH = dot(sh, 1);
833
834        sh *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16));
835    #else
836        sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z;
837    #endif
838
839    #if defined(LIGHTMAP_SPECULAR)
840    dominantDir = nL1;
841
842    o_light.l = dominantDir;
843    half directionality = max(0.001, length(o_light.l));
844    o_light.l /= directionality;
845
846    o_light.colorIntensity = float4(L0 * directionality, 1.0);
847    o_light.attenuation = directionality;
848    o_light.NoL = saturate(dot(normalWorld, o_light.l));
849    #endif
850
851    return sh;
852}
853#endif
854
855float IrradianceToExposureOcclusion(float3 irradiance)
856{
857    return saturate(length(irradiance + FLT_EPS) * getExposureOcclusionBias());
858}
859
860float3 specularDFG(const float3 dfg, const float3 f0) {
861	return lerp(dfg.xxx, dfg.yyy, f0);
862}
863
864float D_GGX(float roughness, float NoH, const float3 h) {
865	// Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces"
866
867	// In mediump, there are two problems computing 1.0 - NoH^2
868	// 1) 1.0 - NoH^2 suffers floating point cancellation when NoH^2 is close to 1 (highlights)
869	// 2) NoH doesn't have enough precision around 1.0
870	// Both problem can be fixed by computing 1-NoH^2 in highp and providing NoH in highp as well
871
872	// However, we can do better using Lagrange's identity:
873	//      ||a x b||^2 = ||a||^2 ||b||^2 - (a . b)^2
874	// since N and H are unit vectors: ||N x H||^2 = 1.0 - NoH^2
875	// This computes 1.0 - NoH^2 directly (which is close to zero in the highlights and has
876	// enough precision).
877	// Overall this yields better performance, keeping all computations in mediump
878	// Not available without reworking to pass NxH to the function
879	float oneMinusNoHSquared = 1.0 - NoH * NoH;
880	float a = NoH * roughness;
881	float k = roughness / (oneMinusNoHSquared + a * a);
882	float d = k * k * (1.0 / PI);
883	return d;
884}
885
886// t = tangent vector, b = bitangent vector
887float D_GGX_Anisotropic(float at, float ab, float NoH,
888        const float3 h,
889        const float3 t, const float3 b) {
890    float ToH = dot(t, h);
891    float BoH = dot(b, h);
892    float a2 = at * ab;
893    float3 v = float3(ab * ToH, at * BoH, a2 * NoH);
894    float v2 = dot(v, v);
895    float w2 = a2 / v2;
896    return a2 * w2 * w2 * (1.0 / PI);
897}
898
899float F_Schlick(float f0, float VoH) {
900	return f0 + (1.0 - f0) * pow5(1.0 - VoH);
901}
902
903float F_Schlick(float f0, float f90, float VoH) {
904    // Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
905    return f0 + (f90 - f0) * pow5(1.0 - VoH);
906}
907
908float3 F_Schlick(const float3 f0, float VoH) {
909    float f = pow5(1.0 - VoH);
910    return f + f0 * (1.0 - f);
911}
912
913float3 F_Schlick(const float3 f0, float f90, float VoH) {
914    // Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
915    return f0 + (f90 - f0) * pow5(1.0 - VoH);
916}
917
918float Fd_Lambert() {
919    return 1.0 / PI;
920}
921
922float Fd_Burley(float roughness, float NoV, float NoL, float LoH) {
923    // Burley 2012, "Physically-Based Shading at Disney"
924    float f90 = 0.5 + 2.0 * roughness * LoH * LoH;
925    float lightScatter = F_Schlick(1.0, f90, NoL);
926    float viewScatter = F_Schlick(1.0, f90, NoV);
927    return lightScatter * viewScatter * (1.0 / PI);
928}
929
930float V_SmithGGXCorrelated(float roughness, float NoV, float NoL) {
931	// Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"
932	float a2 = roughness * roughness;
933	float lambdaV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2);
934	float lambdaL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2);
935	float v = 0.5 / (lambdaV + lambdaL);
936	return v;
937}
938
939float V_SmithGGXCorrelated_Fast(float roughness, float NoV, float NoL) {
940    // Hammon 2017, "PBR Diffuse Lighting for GGX+Smith Microsurfaces"
941    float v = 0.5 / lerp(2.0 * NoL * NoV, NoL + NoV, roughness);
942    return v;
943}
944
945float V_SmithGGXCorrelated_Anisotropic(float at, float ab, float ToV, float BoV,
946        float ToL, float BoL, float NoV, float NoL) {
947    float lambdaV = NoL * length(float3(at * ToV, ab * BoV, NoV));
948    float lambdaL = NoV * length(float3(at * ToL, ab * BoL, NoL));
949    float v = 0.5 / (lambdaV + lambdaL);
950    return saturate(v);
951}
952
953float perceptualRoughnessToRoughness(float perceptualRoughness) {
954    return perceptualRoughness * perceptualRoughness;
955}
956
957float roughnessToPerceptualRoughness(float roughness) {
958    return sqrt(roughness);
959}
960
961float normalFiltering(float perceptualRoughness, const float3 worldNormal) {
962    // Kaplanyan 2016, "Stable specular highlights"
963    // Tokuyoshi 2017, "Error Reduction and Simplification for Shading Anti-Aliasing"
964    // Tokuyoshi and Kaplanyan 2019, "Improved Geometric Specular Antialiasing"
965
966    // This implementation is meant for deferred rendering in the original paper but
967    // we use it in forward rendering as well (as discussed in Tokuyoshi and Kaplanyan
968    // 2019). The main reason is that the forward version requires an expensive transform
969    // of the half vector by the tangent frame for every light. This is therefore an
970    // approximation but it works well enough for our needs and provides an improvement
971    // over our original implementation based on Vlachos 2015, "Advanced VR Rendering".
972
973    float3 du = ddx(worldNormal);
974    float3 dv = ddy(worldNormal);
975
976    float variance = _specularAntiAliasingVariance * (dot(du, du) + dot(dv, dv));
977
978    float roughness = perceptualRoughnessToRoughness(perceptualRoughness);
979    float kernelRoughness = min(2.0 * variance, _specularAntiAliasingThreshold);
980    float squareRoughness = saturate(roughness * roughness + kernelRoughness);
981
982    return roughnessToPerceptualRoughness(sqrt(squareRoughness));
983}
984
985float3 energyCompensation(float3 dfg, float3 f0)
986{
987  // Energy compensation for multiple scattering in a microfacet model
988  // See "Multiple-Scattering Microfacet BSDFs with the Smith Model"
989  return 1.0 + f0 * (1.0 / dfg.yyy - 1.0);
990}
991
992half3 Unity_GlossyEnvironment_local (UNITY_ARGS_TEXCUBE(tex), half4 hdr, Unity_GlossyEnvironmentData glossIn)
993{
994	half perceptualRoughness = glossIn.roughness /* perceptualRoughness */ ;
995
996	// Workaround for issue where objects are blurrier than they should be
997	// due to specular AA.
998	float roughnessAdjustment = 1-perceptualRoughness;
999	roughnessAdjustment = MIN_PERCEPTUAL_ROUGHNESS * roughnessAdjustment * roughnessAdjustment;
1000	perceptualRoughness = perceptualRoughness - roughnessAdjustment;
1001
1002	// Unity derivation
1003	perceptualRoughness = perceptualRoughness*(1.7 - 0.7 * perceptualRoughness);
1004	// Filament derivation
1005	// perceptualRoughness = perceptualRoughness * (2.0 - perceptualRoughness);
1006	half mip = perceptualRoughnessToMipmapLevel(perceptualRoughness);
1007	half3 R = glossIn.reflUVW;
1008	half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);
1009
1010	return DecodeHDR(rgbm, hdr);
1011}
1012
1013inline half3 UnityGI_prefilteredRadiance(const UnityGIInput data,
1014    const float perceptualRoughness, const float3 r) {
1015  half3 specular;
1016
1017  Unity_GlossyEnvironmentData glossIn = (Unity_GlossyEnvironmentData)0;
1018  glossIn.roughness = perceptualRoughness;
1019  glossIn.reflUVW = r;
1020
1021#ifdef UNITY_SPECCUBE_BOX_PROJECTION
1022  // we will tweak reflUVW in glossIn directly (as we pass it to Unity_GlossyEnvironment twice for probe0 and pr            obe1), so keep original to pass into BoxProjectedCubemapDirection
1023	half3 originalReflUVW = glossIn.reflUVW;
1024	glossIn.reflUVW = BoxProjectedCubemapDirection(originalReflUVW,
1025			data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
1026#endif
1027
1028#ifdef _GLOSSYREFLECTIONS_OFF
1029    specular = unity_IndirectSpecColor.rgb;
1030#else
1031  half3 env0 = Unity_GlossyEnvironment_local (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
1032#ifdef UNITY_SPECCUBE_BLENDING
1033  const float kBlendFactor = 0.99999;
1034  float blendLerp = data.boxMin[0].w;
1035  UNITY_BRANCH
1036    if (blendLerp < kBlendFactor)
1037    {
1038#ifdef UNITY_SPECCUBE_BOX_PROJECTION
1039      glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition                        [1], data.boxMin[1], data.boxMax[1]);
1040#endif  // UNITY_SPECCUBE_BOX_PROJECTION
1041
1042      half3 env1 = Unity_GlossyEnvironment_local (UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0                    ), data.probeHDR[1], glossIn);
1043      specular = lerp(env1, env0, blendLerp);                                                                           }
1044    else
1045    {
1046      specular = env0;
1047    }
1048#else
1049  specular = env0;
1050#endif  // UNITY_SPECCUBE_BLENDING
1051#endif  // _GLOSSYREFLECTIONS_OFF
1052
1053  return specular;
1054}
1055
1056// R dither mask
1057float noiseR2(float2 pixel) {
1058  const float a1 = 0.75487766624669276;
1059  const float a2 = 0.569840290998;
1060  return frac(a1 * float(pixel.x) + a2 * float(pixel.y));
1061}
1062
1063// Return light probes or lightmap.
1064// Port of UnityGI_Irradiance without ShadingParams
1065float3 UnityGI_Irradiance(
1066    float3 worldNormal, 
1067    float3 worldPos,
1068    float4 lightmapUV,
1069    float3 ambient,
1070    float attenuation,
1071    float3 tangentNormal,
1072    float3x3 tangentToWorld,
1073    #if defined(USING_BAKERY_VERTEXLMSH)
1074        float3 ambientSH[3],
1075    #elif defined(USING_BAKERY_VERTEXLMDIR)
1076        float3 ambientDir,
1077    #endif
1078    out float occlusion, 
1079    out Light derivedLight)
1080{
1081    float3 irradiance = ambient;
1082    float3 irradianceForAO; 
1083    occlusion = 1.0;
1084    derivedLight = (Light)0;
1085
1086    #if UNITY_SHOULD_SAMPLE_SH
1087        irradiance += Irradiance_SphericalHarmonicsUnity(worldNormal, ambient, worldPos, derivedLight);
1088    #endif
1089
1090    irradianceForAO = irradiance;
1091
1092    // Should be stripped out at compile time if vertex LM mode is disabled.
1093    if (getIsBakeryVertexMode() == false)
1094    {
1095    #if defined(LIGHTMAP_ON)
1096        // Baked lightmaps
1097        half4 bakedColorTex = SampleLightmapBicubic(lightmapUV.xy);
1098        half3 bakedColor = DecodeLightmap(bakedColorTex);
1099
1100        #ifdef DIRLIGHTMAP_COMBINED
1101            fixed4 bakedDirTex = SampleLightmapDirBicubic(lightmapUV.xy);
1102
1103            // Bakery's MonoSH mode replaces the regular directional lightmap
1104            #if defined(_BAKERY_MONOSH)
1105                irradiance = DecodeMonoSHLightmap(bakedColor, bakedDirTex, worldNormal, derivedLight);
1106
1107                irradianceForAO = irradiance;
1108
1109                #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1110                    irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1111                #endif
1112            #else
1113                irradiance = DecodeDirectionalLightmap(bakedColor, bakedDirTex, worldNormal);
1114
1115                irradianceForAO = irradiance;
1116
1117                #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1118                    irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1119                #endif
1120
1121                #if defined(LIGHTMAP_SPECULAR) 
1122                    irradiance = DecodeDirectionalLightmapSpecular(bakedColor, bakedDirTex, worldNormal, false, 0, derivedLight);
1123                #endif
1124            #endif
1125
1126        #else // not directional lightmap
1127
1128            #if defined(USING_BAKERY)
1129                #if defined(_BAKERY_RNM)
1130                // bakery rnm mode
1131                irradiance = DecodeRNMLightmap(0, lightmapUV.xy, tangentNormal, tangentToWorld, derivedLight);
1132                #endif
1133
1134                #if defined(_BAKERY_SH)
1135                // bakery sh mode
1136                irradiance = DecodeSHLightmap(bakedColor, lightmapUV.xy, worldNormal, derivedLight);
1137                #endif
1138
1139                irradianceForAO = irradiance;
1140
1141                #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1142                    irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1143                #endif
1144
1145            #else
1146
1147                irradiance += bakedColor;
1148
1149                irradianceForAO = irradiance;
1150
1151                #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1152                    irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1153                #endif
1154            #endif
1155
1156        #endif
1157    #endif
1158    }
1159
1160    #if defined(USING_BAKERY_VERTEXLM)
1161    if (getIsBakeryVertexMode() == true)
1162    {
1163        // Lightmap colour is already stored in ambient.
1164        // If directionality is on, then ambientDir contains directionality.
1165        // If SH is on, then ambientSH[3] contains the SH data.
1166        half4 bakedColorTex = float4(ambient, 1.0);
1167
1168        #if defined(USING_BAKERY_VERTEXLMSH)
1169            irradiance = DecodeSHLightmapVertex(ambient, ambientSH, worldNormal, derivedLight);
1170            irradianceForAO = irradiance;
1171            #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1172                irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1173            #endif
1174        #else
1175            #if defined(USING_BAKERY_VERTEXLMDIR)
1176                #if defined(_BAKERY_MONOSH)
1177                    irradiance = DecodeMonoSHLightmap(ambient, ambientDir, worldNormal, derivedLight, false);
1178                    irradianceForAO = irradiance;
1179                    #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1180                        irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1181                    #endif
1182                #else
1183                    irradiance = DecodeDirectionalLightmap(ambient, ambientDir, worldNormal);
1184                    irradianceForAO = irradiance;
1185                    #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1186                        irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1187                    #endif
1188                    #if defined(LIGHTMAP_SPECULAR) 
1189                        irradiance = DecodeDirectionalLightmapSpecular(ambient, ambientDir, worldNormal, false, 0, derivedLight);
1190                    #endif
1191                #endif 
1192            #else
1193                // No directionality, just light colour.
1194                // Irradiance and IrradianceForAO already contain the irradiance, so just handle subtractive lighting. 
1195                #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
1196                    irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal);
1197                #endif
1198            #endif
1199        #endif 
1200    }
1201    #endif
1202
1203    #if defined(DYNAMICLIGHTMAP_ON)
1204        // Dynamic lightmaps
1205        fixed4 realtimeColorTex = SampleDynamicLightmapBicubic(lightmapUV.zw);
1206        half3 realtimeColor = DecodeRealtimeLightmap(realtimeColorTex);
1207
1208        irradianceForAO += realtimeColor;
1209
1210        #ifdef DIRLIGHTMAP_COMBINED
1211            half4 realtimeDirTex = SampleDynamicLightmapDirBicubic(lightmapUV.zw);
1212            irradiance += DecodeDirectionalLightmap(realtimeColor, realtimeDirTex, worldNormal);
1213        #else
1214            irradiance += realtimeColor;
1215        #endif
1216    #endif
1217    
1218    // VRC Light Volumes also have an additive component which can be added over lightmapping.
1219    #if defined(_VRCLV) && !UNITY_SHOULD_SAMPLE_SH
1220        Light volumeLight = (Light)0;
1221        irradiance += Irradiance_SampleVRCLightVolumeAdditive(worldNormal, worldPos, volumeLight);
1222
1223        // Merge lights, weighing each light's contribution by their intensity
1224        float derivedLum = luminance(derivedLight.colorIntensity.rgb);
1225        float volumeLum = luminance(volumeLight.colorIntensity.rgb);
1226        float totalIntensity = derivedLum + volumeLum + FLT_EPS;
1227        float derivedWeight = derivedLum / totalIntensity;
1228        float volumeWeight = volumeLum / totalIntensity;
1229
1230        derivedLight.l = normalize(derivedLight.l * derivedWeight + volumeLight.l * volumeWeight);
1231        derivedLight.colorIntensity = derivedLight.colorIntensity * derivedWeight + volumeLight.colorIntensity * volumeWeight;
1232        derivedLight.attenuation = derivedLight.attenuation * derivedWeight + volumeLight.attenuation * volumeWeight;
1233        derivedLight.NoL = derivedLight.NoL * derivedWeight + volumeLight.NoL * volumeWeight;
1234    #endif
1235
1236    occlusion = IrradianceToExposureOcclusion(irradianceForAO);
1237
1238    return irradiance;
1239}
1240
1241// Simplified integration function using existing Unity/Bakery functions
1242float3 BakeryGI_Irradiance(
1243    float3 worldNormal,
1244    float3 worldPos,
1245    float4 lightmapUV,  // xy = uv0, zw = uv1
1246    float3 ambient,
1247    float attenuation,
1248    float3 tangentNormal,
1249    float3x3 tangentToWorld,
1250    out float occlusion,
1251    out Light derivedLight)
1252{
1253    // The existing UnityGI_Irradiance function already handles all Bakery modes correctly,
1254    // including MonoSH via the DecodeMonoSHLightmap function that's already defined above
1255    float3 ambientSH[3] = {float3(0,0,0), float3(0,0,0), float3(0,0,0)};
1256    float3 ambientDir = float3(0,0,0);
1257    
1258    return UnityGI_Irradiance(
1259        worldNormal,
1260        worldPos,
1261        lightmapUV,
1262        ambient,
1263        attenuation,
1264        tangentNormal,
1265        tangentToWorld,
1266        #if defined(USING_BAKERY_VERTEXLMSH)
1267            ambientSH,
1268        #elif defined(USING_BAKERY_VERTEXLMDIR)
1269            ambientDir,
1270        #endif
1271        occlusion,
1272        derivedLight
1273    );
1274}
1275
1276
1277#endif // __FILAMENTED_INC