From a9dbbfa1488a9ec3bd772fc9847888502f49a65e Mon Sep 17 00:00:00 2001 From: yum Date: Fri, 13 Jun 2025 17:59:00 -0700 Subject: Fix some filamented inconsistencies --- 2ner.cginc | 3 + SharedFilteringLib.hlsl | 47 +++ SharedSamplingLib.hlsl | 1042 +++++++++++++++++++++++++++++++++++++++++++++++ filamented.cginc | 783 +++++++++++++++++++++++++++++++++++ globals.cginc | 17 + yum_brdf.cginc | 365 ++++++++++------- yum_lighting.cginc | 626 ++++++++++++++-------------- 7 files changed, 2430 insertions(+), 453 deletions(-) create mode 100644 SharedFilteringLib.hlsl create mode 100644 SharedSamplingLib.hlsl diff --git a/2ner.cginc b/2ner.cginc index 3a650df..ff22ecb 100644 --- a/2ner.cginc +++ b/2ner.cginc @@ -37,6 +37,9 @@ v2f vert(appdata v) { #if defined(DEPTH_PREPASS) && !defined(_DEPTH_PREPASS) return (v2f) (0.0/0.0); #endif +#if defined(EXTRA_STENCIL_COLOR_PASS) && !defined(_EXTRA_STENCIL_COLOR_PASS) + return (v2f) (0.0/0.0); +#endif #if defined(MASKED_STENCIL1_PASS) #if !defined(_MASKED_STENCIL1) return (v2f) (0.0/0.0); diff --git a/SharedFilteringLib.hlsl b/SharedFilteringLib.hlsl new file mode 100644 index 0000000..582adff --- /dev/null +++ b/SharedFilteringLib.hlsl @@ -0,0 +1,47 @@ +#ifndef SERVICE_FILTERING_INCLUDED +#define SERVICE_FILTERING_INCLUDED + +float4 cubic(float v) +{ + float4 n = float4(1.0, 2.0, 3.0, 4.0) - v; + float4 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return float4(x, y, z, w); +} + + +// Unity's SampleTexture2DBicubic doesn't exist in 2018, which is our target here. +// So this is a similar function with tweaks to have similar semantics. + +float4 SampleTexture2DBicubicFilter(TEXTURE2D_PARAM(tex, smp), float2 coord, float4 texSize) +{ + coord = coord * texSize.xy - 0.5; + float fx = frac(coord.x); + float fy = frac(coord.y); + coord.x -= fx; + coord.y -= fy; + + float4 xcubic = cubic(fx); + float4 ycubic = cubic(fy); + + float4 c = float4(coord.x - 0.5, coord.x + 1.5, coord.y - 0.5, coord.y + 1.5); + float4 s = float4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x + ycubic.y, ycubic.z + ycubic.w); + float4 offset = c + float4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) / s; + + float4 sample0 = SAMPLE_TEXTURE2D(tex, smp, float2(offset.x, offset.z) * texSize.zw); + float4 sample1 = SAMPLE_TEXTURE2D(tex, smp, float2(offset.y, offset.z) * texSize.zw); + float4 sample2 = SAMPLE_TEXTURE2D(tex, smp, float2(offset.x, offset.w) * texSize.zw); + float4 sample3 = SAMPLE_TEXTURE2D(tex, smp, float2(offset.y, offset.w) * texSize.zw); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return lerp( + lerp(sample3, sample2, sx), + lerp(sample1, sample0, sx), sy); +} + +#endif // SERVICE_FILTERING_INCLUDED \ No newline at end of file diff --git a/SharedSamplingLib.hlsl b/SharedSamplingLib.hlsl new file mode 100644 index 0000000..32f04c7 --- /dev/null +++ b/SharedSamplingLib.hlsl @@ -0,0 +1,1042 @@ +#ifndef COMMON_TEXTURE_SAMPLING +#define COMMON_TEXTURE_SAMPLING + +// From https://github.com/orels1/orels-Unity-Shaders +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Credit to Jason Booth for digging this all up +// This originally comes from CoreRP, see Jason's comment below + +// If your looking in here and thinking WTF, yeah, I know. These are taken from the SRPs, to allow us to use the same +// texturing library they use. However, since they are not included in the standard pipeline by default, there is no +// way to include them in and they have to be inlined, since someone could copy this shader onto another machine without +// Better Shaders installed. Unfortunate, but I'd rather do this and have a nice library for texture sampling instead +// of the patchy one Unity provides being inlined/emulated in HDRP/URP. Strangely, PSSL and XBoxOne libraries are not +// included in the standard SRP code, but they are in tons of Unity own projects on the web, so I grabbed them from there. + +#if defined(SHADER_API_XBOXONE) + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_FLOAT(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_FLOAT(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_FLOAT(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_HALF(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_HALF(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_HALF(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_HALF(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_HALF(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName +#define RW_TEXTURE3D(type, textureName) RWTexture3D textureName + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias) +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) +#define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) + +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) + +#elif defined(SHADER_API_PSSL) + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.GetLOD(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_FLOAT(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_FLOAT(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_FLOAT(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_HALF(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_HALF(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_HALF(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_HALF(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_HALF(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#define RW_TEXTURE2D(type, textureName) RW_Texture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RW_Texture2D_Array textureName +#define RW_TEXTURE3D(type, textureName) RW_Texture3D textureName + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias) +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) +#define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) + +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) + +#elif defined(SHADER_API_D3D11) + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_FLOAT(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_FLOAT(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_FLOAT(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_HALF(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_HALF(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_HALF(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_HALF(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_HALF(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName +#define RW_TEXTURE3D(type, textureName) RWTexture3D textureName + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias) +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) +#define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) + +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) + +#elif defined(SHADER_API_METAL) + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) Texture2D_float textureName +#define TEXTURE2D_ARRAY_FLOAT(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_FLOAT(textureName) TextureCube_float textureName +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_FLOAT(textureName) Texture3D_float textureName + +#define TEXTURE2D_HALF(textureName) Texture2D_half textureName +#define TEXTURE2D_ARRAY_HALF(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_HALF(textureName) TextureCube_half textureName +#define TEXTURECUBE_ARRAY_HALF(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_HALF(textureName) Texture3D_half textureName + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName +#define RW_TEXTURE3D(type, textureName) RWTexture3D textureName + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias) +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) +#define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) + +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) + +#elif defined(SHADER_API_VULKAN) +// This file assume SHADER_API_VULKAN is defined +// TODO: This is a straight copy from D3D11.hlsl. Go through all this stuff and adjust where needed. + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) Texture2D_float textureName +#define TEXTURE2D_ARRAY_FLOAT(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_FLOAT(textureName) TextureCube_float textureName +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_FLOAT(textureName) Texture3D_float textureName + +#define TEXTURE2D_HALF(textureName) Texture2D_half textureName +#define TEXTURE2D_ARRAY_HALF(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_HALF(textureName) TextureCube_half textureName +#define TEXTURECUBE_ARRAY_HALF(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_HALF(textureName) Texture3D_half textureName + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName +#define RW_TEXTURE3D(type, textureName) RWTexture3D textureName + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias) +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) +#define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) + +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) + +#elif defined(SHADER_API_SWITCH) +// This file assume SHADER_API_SWITCH is defined + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) Texture2D_float textureName +#define TEXTURE2D_ARRAY_FLOAT(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_FLOAT(textureName) TextureCube_float textureName +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_FLOAT(textureName) Texture3D_float textureName + +#define TEXTURE2D_HALF(textureName) Texture2D_half textureName +#define TEXTURE2D_ARRAY_HALF(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_HALF(textureName) TextureCube_half textureName +#define TEXTURECUBE_ARRAY_HALF(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_HALF(textureName) Texture3D_half textureName + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName +#define RW_TEXTURE3D(type, textureName) RWTexture3D textureName + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias) +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) +#define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) + +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) + +#elif defined(SHADER_API_GLCORE) + +// OpenGL 4.1 SM 5.0 https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html +#if (SHADER_TARGET >= 46) +#define OPENGL4_1_SM5 1 +#else +#define OPENGL4_1_SM5 0 +#endif + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_FLOAT(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_FLOAT(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_FLOAT(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_HALF(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_HALF(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_HALF(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_HALF(textureName) TEXTURECUBE_ARRAY(textureName) +#define TEXTURE3D_HALF(textureName) TEXTURE3D(textureName) + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName +#define RW_TEXTURE3D(type, textureName) RWTexture3D textureName + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, ddx, ddy) textureName.SampleGrad(samplerName, coord2, ddx, ddy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) +#ifdef UNITY_NO_CUBEMAP_ARRAY +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY_LOD) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, bias) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY_LOD) +#else +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias)textureName.SampleBias(samplerName, float4(coord3, index), bias) +#endif +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) + +#if OPENGL4_1_SM5 +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#else +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURE2D) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURE2D_ARRAY) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURECUBE) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURECUBE_ARRAY) +#endif + +#elif defined(SHADER_API_GLES3) + +// GLES 3.1 + AEP shader feature https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html +#if (SHADER_TARGET >= 40) +#define GLES3_1_AEP 1 +#else +#define GLES3_1_AEP 0 +#endif + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2) + +// Texture abstraction + +#define TEXTURE2D(textureName) Texture2D textureName +#define TEXTURE2D_ARRAY(textureName) Texture2DArray textureName +#define TEXTURECUBE(textureName) TextureCube textureName +#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName +#define TEXTURE3D(textureName) Texture3D textureName + +#define TEXTURE2D_FLOAT(textureName) Texture2D_float textureName +#define TEXTURE2D_ARRAY_FLOAT(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_FLOAT(textureName) TextureCube_float textureName +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_FLOAT(textureName) Texture3D_float textureName + +#define TEXTURE2D_HALF(textureName) Texture2D_half textureName +#define TEXTURE2D_ARRAY_HALF(textureName) Texture2DArray textureName // no support to _float on Array, it's being added +#define TEXTURECUBE_HALF(textureName) TextureCube_half textureName +#define TEXTURECUBE_ARRAY_HALF(textureName) TextureCubeArray textureName // no support to _float on Array, it's being added +#define TEXTURE3D_HALF(textureName) Texture3D_half textureName + +#define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) +#define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) + +#if GLES3_1_AEP +#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName +#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName +#define RW_TEXTURE3D(type, textureName) RWTexture3D textureName +#else +#define RW_TEXTURE2D(type, textureName) ERROR_ON_UNSUPPORTED_FUNCTION(RWTexture2D) +#define RW_TEXTURE2D_ARRAY(type, textureName) ERROR_ON_UNSUPPORTED_FUNCTION(RWTexture2DArray) +#define RW_TEXTURE3D(type, textureName) ERROR_ON_UNSUPPORTED_FUNCTION(RWTexture3D) +#endif + +#define SAMPLER(samplerName) SamplerState samplerName +#define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName + +#define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) +#define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) + +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) +#define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName + +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName +#define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, ddx, ddy) textureName.SampleGrad(samplerName, coord2, ddx, ddy) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) + +#ifdef UNITY_NO_CUBEMAP_ARRAY +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY_LOD) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias)ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY_BIAS) +#else +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias)textureName.SampleBias(samplerName, float4(coord3, index), bias) +#endif + +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) + +#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) +#define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) + +#if GLES3_1_AEP +#define PLATFORM_SUPPORT_GATHER +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) +#else +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURE2D) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURE2D_ARRAY) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURECUBE) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURECUBE_ARRAY) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_RED_TEXTURE2D) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_GREEN_TEXTURE2D) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_BLUE_TEXTURE2D) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_ALPHA_TEXTURE2D) +#endif + +#elif defined(SHADER_API_GLES) + +#define uint int + +#define rcp(x) 1.0 / (x) +#define ddx_fine ddx +#define ddy_fine ddy +#define asfloat +#define asuint(x) asint(x) +#define f32tof16 +#define f16tof32 + +#define ERROR_ON_UNSUPPORTED_FUNCTION(funcName) #error #funcName is not supported on GLES 2.0 + +// Initialize arbitrary structure with zero values. +// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0 +#define ZERO_INITIALIZE(type, name) name = (type)0; +#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } } + +// Texture util abstraction + +#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) #error calculate Level of Detail not supported in GLES2 + +// Texture abstraction + +#define TEXTURE2D(textureName) sampler2D textureName +#define TEXTURE2D_ARRAY(textureName) samplerCUBE textureName // No support to texture2DArray +#define TEXTURECUBE(textureName) samplerCUBE textureName +#define TEXTURECUBE_ARRAY(textureName) samplerCUBE textureName // No supoport to textureCubeArray and can't emulate with texture2DArray +#define TEXTURE3D(textureName) sampler3D textureName + +#define TEXTURE2D_FLOAT(textureName) sampler2D_float textureName +#define TEXTURE2D_ARRAY_FLOAT(textureName) TEXTURECUBE_FLOAT(textureName) // No support to texture2DArray +#define TEXTURECUBE_FLOAT(textureName) samplerCUBE_float textureName +#define TEXTURECUBE_ARRAY_FLOAT(textureName) TEXTURECUBE_FLOAT(textureName) // No support to textureCubeArray +#define TEXTURE3D_FLOAT(textureName) sampler3D_float textureName + +#define TEXTURE2D_HALF(textureName) sampler2D_half textureName +#define TEXTURE2D_ARRAY_HALF(textureName) TEXTURECUBE_HALF(textureName) // No support to texture2DArray +#define TEXTURECUBE_HALF(textureName) samplerCUBE_half textureName +#define TEXTURECUBE_ARRAY_HALF(textureName) TEXTURECUBE_HALF(textureName) // No support to textureCubeArray +#define TEXTURE3D_HALF(textureName) sampler3D_half textureName + +#define TEXTURE2D_SHADOW(textureName) SHADOW2D_TEXTURE_AND_SAMPLER textureName +#define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURECUBE_SHADOW(textureName) // No support to texture array +#define TEXTURECUBE_SHADOW(textureName) SHADOWCUBE_TEXTURE_AND_SAMPLER textureName +#define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_SHADOW(textureName) // No support to texture array + +#define RW_TEXTURE2D(type, textureNam) ERROR_ON_UNSUPPORTED_FUNCTION(RWTexture2D) +#define RW_TEXTURE2D_ARRAY(type, textureName) ERROR_ON_UNSUPPORTED_FUNCTION(RWTexture2DArray) +#define RW_TEXTURE3D(type, textureNam) ERROR_ON_UNSUPPORTED_FUNCTION(RWTexture3D) + +#define SAMPLER(samplerName) +#define SAMPLER_CMP(samplerName) + +#define TEXTURE2D_PARAM(textureName, samplerName) sampler2D textureName +#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) samplerCUBE textureName +#define TEXTURECUBE_PARAM(textureName, samplerName) samplerCUBE textureName +#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) samplerCUBE textureName +#define TEXTURE3D_PARAM(textureName, samplerName) sampler3D textureName +#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) SHADOW2D_TEXTURE_AND_SAMPLER textureName +#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) SHADOWCUBE_TEXTURE_AND_SAMPLER textureName +#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) SHADOWCUBE_TEXTURE_AND_SAMPLER textureName + +#define TEXTURE2D_ARGS(textureName, samplerName) textureName +#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName +#define TEXTURECUBE_ARGS(textureName, samplerName) textureName +#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName +#define TEXTURE3D_ARGS(textureName, samplerName) textureName +#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName +#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName +#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName + +#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) tex2D(textureName, coord2) + +#if (SHADER_TARGET >= 30) +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) tex2Dlod(textureName, float4(coord2, 0, lod)) +#else +// No lod support. Very poor approximation with bias. +#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, lod) +#endif + +#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) tex2Dbias(textureName, float4(coord2, 0, bias)) +#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, ddx, ddy) SAMPLE_TEXTURE2D(textureName, samplerName, coord2) +#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURE2D_ARRAY) +#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURE2D_ARRAY_LOD) +#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURE2D_ARRAY_BIAS) +#define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURE2D_ARRAY_GRAD) +#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) texCUBE(textureName, coord3) +// No lod support. Very poor approximation with bias. +#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, lod) +#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) texCUBEbias(textureName, float4(coord3, bias)) +#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY) +#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY_LOD) +#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY_BIAS) +#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) tex3D(textureName, coord3) +#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURE3D_LOD) + +#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) SHADOW2D_SAMPLE(textureName, samplerName, coord3) +#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURE2D_ARRAY_SHADOW) +#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) SHADOWCUBE_SAMPLE(textureName, samplerName, coord4) +#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) ERROR_ON_UNSUPPORTED_FUNCTION(SAMPLE_TEXTURECUBE_ARRAY_SHADOW) + +// Not supported. Can't define as error because shader library is calling these functions. +#define LOAD_TEXTURE2D(textureName, unCoord2) half4(0, 0, 0, 0) +#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) half4(0, 0, 0, 0) +#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) half4(0, 0, 0, 0) +#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) half4(0, 0, 0, 0) +#define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) half4(0, 0, 0, 0) +#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) half4(0, 0, 0, 0) +#define LOAD_TEXTURE3D(textureName, unCoord3) ERROR_ON_UNSUPPORTED_FUNCTION(LOAD_TEXTURE3D) +#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) ERROR_ON_UNSUPPORTED_FUNCTION(LOAD_TEXTURE3D_LOD) + +// Gather not supported. Fallback to regular texture sampling. +#define GATHER_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURE2D) +#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURE2D_ARRAY) +#define GATHER_TEXTURECUBE(textureName, samplerName, coord3) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURECUBE) +#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_TEXTURECUBE_ARRAY) +#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_RED_TEXTURE2D) +#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_GREEN_TEXTURE2D) +#define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_BLUE_TEXTURE2D) +#define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) ERROR_ON_UNSUPPORTED_FUNCTION(GATHER_ALPHA_TEXTURE2D) + +#else +#error unsupported shader api +#endif + +#endif // COMMON_TEXTURE_SAMPLING \ No newline at end of file diff --git a/filamented.cginc b/filamented.cginc index ebe17b8..1b53e2b 100644 --- a/filamented.cginc +++ b/filamented.cginc @@ -1,6 +1,9 @@ #ifndef __FILAMENTED_INC #define __FILAMENTED_INC +#include "SharedSamplingLib.hlsl" +#include "SharedFilteringLib.hlsl" + #include "UnityImageBasedLighting.cginc" #include "UnityStandardUtils.cginc" @@ -237,6 +240,609 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. UNITY_DECLARE_TEX2D_FLOAT(_DFG); +// Filamented defines for spherical harmonics +#define SPHERICAL_HARMONICS_DEFAULT 0 +#define SPHERICAL_HARMONICS_GEOMETRICS 1 +#define SPHERICAL_HARMONICS_ZH3 2 +#define SPHERICAL_HARMONICS SPHERICAL_HARMONICS_ZH3 +#define SPHERICAL_HARMONICS_USE_L2 0 + +// Light struct from filamented +struct Light { + float4 colorIntensity; + float3 l; + float attenuation; + float NoL; + float3 worldPosition; +}; + +// Helper functions +half getExposureOcclusionBias() +{ + return 1.0/(_ExposureOcclusion); +} + +bool getIsBakeryVertexMode() +{ +#if defined(USING_BAKERY_VERTEXLM) + #define BAKERYMODE_DEFAULT 0 + #define BAKERYMODE_VERTEXLM 1.0f + #define BAKERYMODE_RNM 2.0f + #define BAKERYMODE_SH 3.0f + return (bakeryLightmapMode == BAKERYMODE_VERTEXLM); +#endif + return false; +} + +half getLightVolumeSurfaceBias() +{ + #if defined(_VRCLV) + return _VRCLVSurfaceBias; + #else + return 0; + #endif +} + +// Geomerics spherical harmonics evaluation +float shEvaluateDiffuseL1Geomerics_local(float L0, float3 L1, float3 n) +{ + float R0 = max(L0, 0); + float3 R1 = 0.5f * L1; + float lenR1 = length(R1); + float q = dot(normalize(R1), n) * 0.5 + 0.5; + q = saturate(q); + float p = 1.0f + 2.0f * lenR1 / R0; + float a = (1.0f - lenR1 / R0) / (1.0f + lenR1 / R0); + return R0 * (a + (1.0f - a) * (p + 1.0f) * pow(q, p)); +} + +// ZH3 constants and functions +const static float L0IrradianceToRadiance = 2 * sqrt(UNITY_PI); +const static float L1IrradianceToRadiance = sqrt(3 * UNITY_PI); +const static float4 L0L1IrradianceToRadiance = float4(L0IrradianceToRadiance, L1IrradianceToRadiance, L1IrradianceToRadiance, L1IrradianceToRadiance); + +float SHEvalLinearL0L1_ZH3Hallucinate(float4 sh, float3 normal) +{ + float4 radiance = sh * L0L1IrradianceToRadiance; + float3 zonalAxis = float3(radiance.w, radiance.y, radiance.z); + float l1Length = length(zonalAxis); + zonalAxis /= l1Length; + float ratio = l1Length / radiance.x; + float zonalL2Coeff = radiance.x * ratio * (0.08 + 0.6 * ratio); + float fZ = dot(zonalAxis, normal); + float zhNormal = sqrt(5.0f / (16.0f * UNITY_PI)) * (3.0f * fZ * fZ - 1.0f); + float result = dot(sh, float4(1, float3(normal.y, normal.z, normal.x))); + result += 0.25f * zhNormal * zonalL2Coeff; + return result; +} + +float3 SHEvalLinearL0L1_ZH3Hallucinate(float3 normal) +{ + float3 shL0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w) + + float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z) / 3.0; + float3 shL1_1 = float3(unity_SHAr.y, unity_SHAg.y, unity_SHAb.y); + float3 shL1_2 = float3(unity_SHAr.z, unity_SHAg.z, unity_SHAb.z); + float3 shL1_3 = float3(unity_SHAr.x, unity_SHAg.x, unity_SHAb.x); + + float3 result = 0.0; + float4 a = float4(shL0.r, shL1_1.r, shL1_2.r, shL1_3.r); + float4 b = float4(shL0.g, shL1_1.g, shL1_2.g, shL1_3.g); + float4 c = float4(shL0.b, shL1_1.b, shL1_2.b, shL1_3.b); + result.r = SHEvalLinearL0L1_ZH3Hallucinate(a, normal); + result.g = SHEvalLinearL0L1_ZH3Hallucinate(b, normal); + result.b = SHEvalLinearL0L1_ZH3Hallucinate(c, normal); + return result; +} + +float3 Irradiance_SphericalHarmonics(const float3 n, const bool useL2) { + float3 finalSH = float3(0,0,0); + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_DEFAULT) + finalSH = SHEvalLinearL0L1(half4(n, 1.0)); + #endif + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_GEOMETRICS) + float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); + float3 L0L2 = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z) / 3.0; + L0 = (useL2) ? L0+L0L2 : L0-L0L2; + finalSH.r = shEvaluateDiffuseL1Geomerics_local(L0.r, unity_SHAr.xyz, n); + finalSH.g = shEvaluateDiffuseL1Geomerics_local(L0.g, unity_SHAg.xyz, n); + finalSH.b = shEvaluateDiffuseL1Geomerics_local(L0.b, unity_SHAb.xyz, n); + #endif + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3) + finalSH = SHEvalLinearL0L1_ZH3Hallucinate(half4(n, 1.0)); + #endif + + #if (SPHERICAL_HARMONICS_USE_L2 == 1) + if (useL2) finalSH += SHEvalLinearL2(half4(n, 1.0)); + #endif + + return finalSH; +} + +float3 Irradiance_SphericalHarmonics(const float3 n) { + return Irradiance_SphericalHarmonics(n, true); +} + +#if UNITY_LIGHT_PROBE_PROXY_VOLUME +half3 Irradiance_SampleProbeVolume (half4 normal, float3 worldPos) +{ + const float transformToLocal = unity_ProbeVolumeParams.y; + const float texelSizeX = unity_ProbeVolumeParams.z; + + float3 position = (transformToLocal == 1.0f) ? mul(unity_ProbeVolumeWorldToObject, float4(worldPos, 1.0)).xyz : worldPos; + float3 texCoord = (position - unity_ProbeVolumeMin.xyz) * unity_ProbeVolumeSizeInv.xyz; + texCoord.x = texCoord.x * 0.25f; + + float texCoordX = clamp(texCoord.x, 0.5f * texelSizeX, 0.25f - 0.5f * texelSizeX); + + texCoord.x = texCoordX; + half4 SHAr = UNITY_SAMPLE_TEX3D_SAMPLER(unity_ProbeVolumeSH, unity_ProbeVolumeSH, texCoord); + + texCoord.x = texCoordX + 0.25f; + half4 SHAg = UNITY_SAMPLE_TEX3D_SAMPLER(unity_ProbeVolumeSH, unity_ProbeVolumeSH, texCoord); + + texCoord.x = texCoordX + 0.5f; + half4 SHAb = UNITY_SAMPLE_TEX3D_SAMPLER(unity_ProbeVolumeSH, unity_ProbeVolumeSH, texCoord); + + half3 x1; + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_DEFAULT) + x1.r = dot(SHAr, normal); + x1.g = dot(SHAg, normal); + x1.b = dot(SHAb, normal); + #endif + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_GEOMETRICS) + x1.r = shEvaluateDiffuseL1Geomerics_local(SHAr.w, SHAr.rgb, normal); + x1.g = shEvaluateDiffuseL1Geomerics_local(SHAg.w, SHAg.rgb, normal); + x1.b = shEvaluateDiffuseL1Geomerics_local(SHAb.w, SHAb.rgb, normal); + #endif + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3) + x1.r = SHEvalLinearL0L1_ZH3Hallucinate(float4(SHAr.w, SHAr.rgb), normal); + x1.g = SHEvalLinearL0L1_ZH3Hallucinate(float4(SHAg.w, SHAg.rgb), normal); + x1.b = SHEvalLinearL0L1_ZH3Hallucinate(float4(SHAb.w, SHAb.rgb), normal); + #endif + + return x1; +} +#endif + +#if defined(_VRCLV) +half3 Irradiance_SampleVRCLightVolume(half3 normal, float3 worldPos, out Light derivedLight) +{ + derivedLight = (Light)0; + float3 samplePos = worldPos + normal * getLightVolumeSurfaceBias(); + + float3 L0, L1r, L1g, L1b; + LightVolumeSH(samplePos, L0, L1r, L1g, L1b); + + half3 irradiance = 0.0; + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_DEFAULT) + irradiance.r = dot(L1r, normal.xyz) + L0.r; + irradiance.g = dot(L1g, normal.xyz) + L0.g; + irradiance.b = dot(L1b, normal.xyz) + L0.b; + #endif + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_GEOMETRICS) + irradiance.r = shEvaluateDiffuseL1Geomerics_local(L0.r, L1r, normal.xyz); + irradiance.g = shEvaluateDiffuseL1Geomerics_local(L0.g, L1g, normal.xyz); + irradiance.b = shEvaluateDiffuseL1Geomerics_local(L0.b, L1b, normal.xyz); + #endif + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3) + irradiance.r = shEvaluateDiffuseL1Geomerics_local(L0.r, L1r, normal.xyz); + irradiance.g = shEvaluateDiffuseL1Geomerics_local(L0.g, L1g, normal.xyz); + irradiance.b = shEvaluateDiffuseL1Geomerics_local(L0.b, L1b, normal.xyz); + #endif + + #if defined(LIGHTMAP_SPECULAR) + float3 nL1x = float3(L1r[0], L1g[0], L1b[0]); + float3 nL1y = float3(L1r[1], L1g[1], L1b[1]); + float3 nL1z = float3(L1r[2], L1g[2], L1b[2]); + float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z)); + + derivedLight.l = dominantDir; + half directionality = max(FLT_EPS, length(derivedLight.l)); + derivedLight.l /= directionality; + + derivedLight.colorIntensity = float4(irradiance * directionality, 1.0); + derivedLight.attenuation = directionality; + derivedLight.NoL = saturate(dot(normal, derivedLight.l)); + #endif + + return irradiance; +} + +half3 Irradiance_SampleVRCLightVolumeAdditive(half3 normal, float3 worldPos, out Light derivedLight) +{ + derivedLight = (Light)0; + + if (!_UdonLightVolumeEnabled || _UdonLightVolumeAdditiveCount == 0) return 0; + + float3 L0, L1r, L1g, L1b; + LightVolumeAdditiveSH(worldPos, L0, L1r, L1g, L1b); + + half3 irradiance = 0.0; + irradiance.r = dot(L1r, normal.xyz) + L0.r; + irradiance.g = dot(L1g, normal.xyz) + L0.g; + irradiance.b = dot(L1b, normal.xyz) + L0.b; + + #if defined(LIGHTMAP_SPECULAR) + float3 nL1x = float3(L1r[0], L1g[0], L1b[0]); + float3 nL1y = float3(L1r[1], L1g[1], L1b[1]); + float3 nL1z = float3(L1r[2], L1g[2], L1b[2]); + float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z)); + + derivedLight.l = dominantDir; + half directionality = max(FLT_EPS, length(derivedLight.l)); + derivedLight.l /= directionality; + + derivedLight.colorIntensity = float4(irradiance * directionality, 1.0); + derivedLight.attenuation = directionality; + derivedLight.NoL = saturate(dot(normal, derivedLight.l)); + #endif + + return irradiance; +} +#endif + +half3 Irradiance_SphericalHarmonicsUnity (half3 normal, half3 ambient, float3 worldPos, out Light derivedLight) +{ + half3 ambient_contrib = 0.0; + derivedLight = (Light)0; + +#if defined(_VRCLV) + #if UNITY_LIGHT_PROBE_PROXY_VOLUME + if (unity_ProbeVolumeParams.x == 1.0) + ambient_contrib = Irradiance_SampleProbeVolume(half4(normal, 1.0), worldPos); + else + ambient_contrib = Irradiance_SampleVRCLightVolume(normal, worldPos, derivedLight); + #else + ambient_contrib = Irradiance_SampleVRCLightVolume(normal, worldPos, derivedLight); + #endif + + ambient += max(half3(0, 0, 0), ambient_contrib); + + #ifdef UNITY_COLORSPACE_GAMMA + ambient = LinearToGammaSpace (ambient); + #endif + + return ambient; +#else + + #if UNITY_SAMPLE_FULL_SH_PER_PIXEL + #if UNITY_LIGHT_PROBE_PROXY_VOLUME + if (unity_ProbeVolumeParams.x == 1.0) + ambient_contrib = Irradiance_SampleProbeVolume(half4(normal, 1.0), worldPos); + else + ambient_contrib = Irradiance_SphericalHarmonics(normal, true); + #else + ambient_contrib = Irradiance_SphericalHarmonics(normal, true); + #endif + + ambient += max(half3(0, 0, 0), ambient_contrib); + + #ifdef UNITY_COLORSPACE_GAMMA + ambient = LinearToGammaSpace(ambient); + #endif + #elif (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE + // Completely per-vertex + #else + #if UNITY_LIGHT_PROBE_PROXY_VOLUME + if (unity_ProbeVolumeParams.x == 1.0) + ambient_contrib = Irradiance_SampleProbeVolume (half4(normal, 1.0), worldPos); + else + ambient_contrib = Irradiance_SphericalHarmonics(normal, false); + #else + ambient_contrib = Irradiance_SphericalHarmonics(normal, false); + #endif + + ambient = max(half3(0, 0, 0), ambient+ambient_contrib); + #ifdef UNITY_COLORSPACE_GAMMA + ambient = LinearToGammaSpace (ambient); + #endif + #endif + + return ambient; +#endif +} + +float4 SampleLightmapBicubic(float2 uv) +{ + #if defined(SHADER_API_D3D11) + float width, height; + unity_Lightmap.GetDimensions(width, height); + float4 unity_Lightmap_TexelSize = float4(width, height, 1.0/width, 1.0/height); + return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), + uv, unity_Lightmap_TexelSize); + #else + return SAMPLE_TEXTURE2D(unity_Lightmap, samplerunity_Lightmap, uv); + #endif +} + +float4 SampleLightmapDirBicubic(float2 uv) +{ + #if defined(SHADER_API_D3D11) && false + float width, height; + unity_LightmapInd.GetDimensions(width, height); + float4 unity_LightmapInd_TexelSize = float4(width, height, 1.0/width, 1.0/height); + return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_LightmapInd, samplerunity_Lightmap), + uv, unity_LightmapInd_TexelSize); + #else + return SAMPLE_TEXTURE2D(unity_LightmapInd, samplerunity_Lightmap, uv); + #endif +} + +float4 SampleDynamicLightmapBicubic(float2 uv) +{ + #if defined(SHADER_API_D3D11) + float width, height; + unity_DynamicLightmap.GetDimensions(width, height); + float4 unity_DynamicLightmap_TexelSize = float4(width, height, 1.0/width, 1.0/height); + return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_DynamicLightmap, samplerunity_DynamicLightmap), + uv, unity_DynamicLightmap_TexelSize); + #else + return SAMPLE_TEXTURE2D(unity_DynamicLightmap, samplerunity_DynamicLightmap, uv); + #endif +} + +float4 SampleDynamicLightmapDirBicubic(float2 uv) +{ + #if defined(SHADER_API_D3D11) && false + float width, height; + unity_DynamicDirectionality.GetDimensions(width, height); + float4 unity_DynamicDirectionality_TexelSize = float4(width, height, 1.0/width, 1.0/height); + return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_DynamicDirectionality, samplerunity_DynamicLightmap), + uv, unity_DynamicDirectionality_TexelSize); + #else + return SAMPLE_TEXTURE2D(unity_DynamicDirectionality, samplerunity_DynamicLightmap, uv); + #endif +} + +inline float3 DecodeDirectionalLightmapSpecular(half3 color, half4 dirTex, half3 normalWorld, + const bool isRealtimeLightmap, fixed4 realtimeNormalTex, out Light o_light) +{ + o_light = (Light)0; + o_light.colorIntensity = float4(color, 1.0); + o_light.l = dirTex.xyz * 2 - 1; + + half directionality = max(0.001, length(o_light.l)); + o_light.l /= directionality; + + #ifdef DYNAMICLIGHTMAP_ON + if (isRealtimeLightmap) + { + half3 realtimeNormal = realtimeNormalTex.xyz * 2 - 1; + o_light.colorIntensity /= max(0.125, dot(realtimeNormal, o_light.l)); + } + #endif + + half3 ambient = o_light.colorIntensity * (1 - directionality); + o_light.colorIntensity = o_light.colorIntensity * directionality; + o_light.attenuation = directionality; + o_light.NoL = saturate(dot(normalWorld, o_light.l)); + + return color; +} + +#if defined(USING_BAKERY) && defined(LIGHTMAP_ON) +float3 DecodeRNMLightmap(half3 color, half2 lightmapUV, half3 normalTangent, float3x3 tangentToWorld, out Light o_light) +{ + const float rnmBasis0 = float3(0.816496580927726f, 0, 0.5773502691896258f); + const float rnmBasis1 = float3(-0.4082482904638631f, 0.7071067811865475f, 0.5773502691896258f); + const float rnmBasis2 = float3(-0.4082482904638631f, -0.7071067811865475f, 0.5773502691896258f); + + float3 irradiance; + o_light = (Light)0; + + #if defined(SHADER_API_D3D11) + float width, height; + _RNM0.GetDimensions(width, height); + float4 rnm_TexelSize = float4(width, height, 1.0/width, 1.0/height); + + float3 rnm0 = DecodeLightmap(SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM0, sampler_RNM0), lightmapUV, rnm_TexelSize)); + float3 rnm1 = DecodeLightmap(SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM1, sampler_RNM0), lightmapUV, rnm_TexelSize)); + float3 rnm2 = DecodeLightmap(SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM2, sampler_RNM0), lightmapUV, rnm_TexelSize)); + #else + float3 rnm0 = DecodeLightmap(SAMPLE_TEXTURE2D(_RNM0, sampler_RNM0, lightmapUV)); + float3 rnm1 = DecodeLightmap(SAMPLE_TEXTURE2D(_RNM1, sampler_RNM0, lightmapUV)); + float3 rnm2 = DecodeLightmap(SAMPLE_TEXTURE2D(_RNM2, sampler_RNM0, lightmapUV)); + #endif + + normalTangent.g *= -1; + + irradiance = saturate(dot(rnmBasis0, normalTangent)) * rnm0 + + saturate(dot(rnmBasis1, normalTangent)) * rnm1 + + saturate(dot(rnmBasis2, normalTangent)) * rnm2; + + #if defined(LIGHTMAP_SPECULAR) + float3 dominantDirT = rnmBasis0 * luminance(rnm0) + + rnmBasis1 * luminance(rnm1) + + rnmBasis2 * luminance(rnm2); + + float3 dominantDirTN = normalize(dominantDirT); + float3 specColor = saturate(dot(rnmBasis0, dominantDirTN)) * rnm0 + + saturate(dot(rnmBasis1, dominantDirTN)) * rnm1 + + saturate(dot(rnmBasis2, dominantDirTN)) * rnm2; + + o_light.l = normalize(mul(tangentToWorld, dominantDirT)); + half directionality = max(0.001, length(o_light.l)); + o_light.l /= directionality; + + o_light.colorIntensity = float4(specColor * directionality, 1.0); + o_light.attenuation = directionality; + o_light.NoL = saturate(dot(normalTangent, dominantDirTN)); + #endif + + return irradiance; +} + +float3 DecodeSHLightmap(half3 L0, half2 lightmapUV, half3 normalWorld, out Light o_light) +{ + float3 irradiance; + o_light = (Light)0; + + #if defined(SHADER_API_D3D11) + float width, height; + _RNM0.GetDimensions(width, height); + float4 rnm_TexelSize = float4(width, height, 1.0/width, 1.0/height); + + float3 nL1x = SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM0, sampler_RNM0), lightmapUV, rnm_TexelSize); + float3 nL1y = SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM1, sampler_RNM0), lightmapUV, rnm_TexelSize); + float3 nL1z = SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(_RNM2, sampler_RNM0), lightmapUV, rnm_TexelSize); + #else + float3 nL1x = SAMPLE_TEXTURE2D(_RNM0, sampler_RNM0, lightmapUV); + float3 nL1y = SAMPLE_TEXTURE2D(_RNM1, sampler_RNM0, lightmapUV); + float3 nL1z = SAMPLE_TEXTURE2D(_RNM2, sampler_RNM0, lightmapUV); + #endif + + nL1x = nL1x * 2 - 1; + nL1y = nL1y * 2 - 1; + nL1z = nL1z * 2 - 1; + float3 L1x = nL1x * L0 * 2; + float3 L1y = nL1y * L0 * 2; + float3 L1z = nL1z * L0 * 2; + + #ifdef BAKERY_SHNONLINEAR + float lumaL0 = dot(L0, float(1)); + float lumaL1x = dot(L1x, float(1)); + float lumaL1y = dot(L1y, float(1)); + float lumaL1z = dot(L1z, float(1)); + + float lumaSH = shEvaluateDiffuseL1Geomerics_local(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld); + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3) + lumaSH = SHEvalLinearL0L1_ZH3Hallucinate(float4(lumaL0, lumaL1y, lumaL1z, lumaL1x), normalWorld); + #endif + + irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + float regularLumaSH = dot(irradiance, 1); + irradiance *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16)); + #else + irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + #endif + + #if defined(LIGHTMAP_SPECULAR) + float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z)); + + o_light.l = dominantDir; + half directionality = max(0.001, length(o_light.l)); + o_light.l /= directionality; + + o_light.colorIntensity = float4(irradiance * directionality, 1.0); + o_light.attenuation = directionality; + o_light.NoL = saturate(dot(normalWorld, o_light.l)); + #endif + + return irradiance; +} + +float3 DecodeSHLightmapVertex(half3 L0, half3 ambientSH[3], half3 normalWorld, out Light o_light) +{ + float3 irradiance; + o_light = (Light)0; + + float3 nL1x = ambientSH[0]; + float3 nL1y = ambientSH[1]; + float3 nL1z = ambientSH[2]; + + nL1x = nL1x * 2 - 1; + nL1y = nL1y * 2 - 1; + nL1z = nL1z * 2 - 1; + float3 L1x = nL1x * L0 * 2; + float3 L1y = nL1y * L0 * 2; + float3 L1z = nL1z * L0 * 2; + + #ifdef BAKERY_SHNONLINEAR + float lumaL0 = dot(L0, float(1)); + float lumaL1x = dot(L1x, float(1)); + float lumaL1y = dot(L1y, float(1)); + float lumaL1z = dot(L1z, float(1)); + float lumaSH = shEvaluateDiffuseL1Geomerics_local(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld); + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3) + lumaSH = SHEvalLinearL0L1_ZH3Hallucinate(float4(lumaL0, lumaL1y, lumaL1z, lumaL1x), normalWorld); + #endif + + irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + float regularLumaSH = dot(irradiance, 1); + irradiance *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16)); + #else + irradiance = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + #endif + + #if defined(LIGHTMAP_SPECULAR) + float3 dominantDir = float3(luminance(nL1x), luminance(nL1y), luminance(nL1z)); + + o_light.l = dominantDir; + half directionality = max(0.001, length(o_light.l)); + o_light.l /= directionality; + + o_light.colorIntensity = float4(irradiance * directionality, 1.0); + o_light.attenuation = directionality; + o_light.NoL = saturate(dot(normalWorld, o_light.l)); + #endif + + return irradiance; +} +#endif + +#if defined(_BAKERY_MONOSH) +float3 DecodeMonoSHLightmap(half3 L0, half3 dominantDir, half3 normalWorld, out Light o_light, const bool remapDir = true) +{ + o_light = (Light)0; + + float3 nL1 = remapDir? dominantDir * 2 - 1 : dominantDir; + float3 L1x = nL1.x * L0 * 2; + float3 L1y = nL1.y * L0 * 2; + float3 L1z = nL1.z * L0 * 2; + + float3 sh; + + #if BAKERY_SHNONLINEAR + float lumaL0 = dot(L0, 1); + float lumaL1x = dot(L1x, 1); + float lumaL1y = dot(L1y, 1); + float lumaL1z = dot(L1z, 1); + float lumaSH = shEvaluateDiffuseL1Geomerics_local(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld); + + #if (SPHERICAL_HARMONICS == SPHERICAL_HARMONICS_ZH3) + lumaSH = SHEvalLinearL0L1_ZH3Hallucinate(float4(lumaL0, lumaL1y, lumaL1z, lumaL1x), normalWorld); + #endif + + sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + float regularLumaSH = dot(sh, 1); + + sh *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16)); + #else + sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + #endif + + #if defined(LIGHTMAP_SPECULAR) + dominantDir = nL1; + + o_light.l = dominantDir; + half directionality = max(0.001, length(o_light.l)); + o_light.l /= directionality; + + o_light.colorIntensity = float4(L0 * directionality, 1.0); + o_light.attenuation = directionality; + o_light.NoL = saturate(dot(normalWorld, o_light.l)); + #endif + + return sh; +} +#endif + +float IrradianceToExposureOcclusion(float3 irradiance) +{ + return saturate(length(irradiance + FLT_EPS) * getExposureOcclusionBias()); +} + float3 PrefilteredDFG_LUT(float lod, float NoV) { return UNITY_SAMPLE_TEX2D(_DFG, float2(NoV, lod)); } @@ -396,5 +1002,182 @@ float noiseR2(float2 pixel) { return frac(a1 * float(pixel.x) + a2 * float(pixel.y)); } +// Return light probes or lightmap. +// Port of UnityGI_Irradiance without ShadingParams +float3 UnityGI_Irradiance( + float3 worldNormal, + float3 worldPos, + float4 lightmapUV, + float3 ambient, + float attenuation, + float3 tangentNormal, + float3x3 tangentToWorld, + #if defined(USING_BAKERY_VERTEXLMSH) + float3 ambientSH[3], + #elif defined(USING_BAKERY_VERTEXLMDIR) + float3 ambientDir, + #endif + out float occlusion, + out Light derivedLight) +{ + float3 irradiance = ambient; + float3 irradianceForAO; + occlusion = 1.0; + derivedLight = (Light)0; + + #if UNITY_SHOULD_SAMPLE_SH + irradiance += Irradiance_SphericalHarmonicsUnity(worldNormal, ambient, worldPos, derivedLight); + #endif + + irradianceForAO = irradiance; + + // Should be stripped out at compile time if vertex LM mode is disabled. + if (getIsBakeryVertexMode() == false) + { + #if defined(LIGHTMAP_ON) + // Baked lightmaps + half4 bakedColorTex = SampleLightmapBicubic(lightmapUV.xy); + half3 bakedColor = DecodeLightmap(bakedColorTex); + + #ifdef DIRLIGHTMAP_COMBINED + fixed4 bakedDirTex = SampleLightmapDirBicubic(lightmapUV.xy); + + // Bakery's MonoSH mode replaces the regular directional lightmap + #if defined(_BAKERY_MONOSH) + irradiance = DecodeMonoSHLightmap(bakedColor, bakedDirTex, worldNormal, derivedLight); + + irradianceForAO = irradiance; + + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + #else + irradiance = DecodeDirectionalLightmap(bakedColor, bakedDirTex, worldNormal); + + irradianceForAO = irradiance; + + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + + #if defined(LIGHTMAP_SPECULAR) + irradiance = DecodeDirectionalLightmapSpecular(bakedColor, bakedDirTex, worldNormal, false, 0, derivedLight); + #endif + #endif + + #else // not directional lightmap + + #if defined(USING_BAKERY) + #if defined(_BAKERY_RNM) + // bakery rnm mode + irradiance = DecodeRNMLightmap(bakedColor, lightmapUV.xy, tangentNormal, tangentToWorld, derivedLight); + #endif + + #if defined(_BAKERY_SH) + // bakery sh mode + irradiance = DecodeSHLightmap(bakedColor, lightmapUV.xy, worldNormal, derivedLight); + #endif + + irradianceForAO = irradiance; + + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + + #else + + irradiance += bakedColor; + + irradianceForAO = irradiance; + + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + #endif + + #endif + #endif + } + #if defined(USING_BAKERY_VERTEXLM) + if (getIsBakeryVertexMode() == true) + { + // Lightmap colour is already stored in ambient. + // If directionality is on, then ambientDir contains directionality. + // If SH is on, then ambientSH[3] contains the SH data. + half4 bakedColorTex = float4(ambient, 1.0); + + #if defined(USING_BAKERY_VERTEXLMSH) + irradiance = DecodeSHLightmapVertex(ambient, ambientSH, worldNormal, derivedLight); + irradianceForAO = irradiance; + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + #else + #if defined(USING_BAKERY_VERTEXLMDIR) + #if defined(_BAKERY_MONOSH) + irradiance = DecodeMonoSHLightmap(ambient, ambientDir, worldNormal, derivedLight, false); + irradianceForAO = irradiance; + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + #else + irradiance = DecodeDirectionalLightmap(ambient, ambientDir, worldNormal); + irradianceForAO = irradiance; + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + #if defined(LIGHTMAP_SPECULAR) + irradiance = DecodeDirectionalLightmapSpecular(ambient, ambientDir, worldNormal, false, 0, derivedLight); + #endif + #endif + #else + // No directionality, just light colour. + // Irradiance and IrradianceForAO already contain the irradiance, so just handle subtractive lighting. + #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) + irradiance = SubtractMainLightWithRealtimeAttenuationFromLightmap(irradiance, attenuation, bakedColorTex, worldNormal); + #endif + #endif + #endif + } + #endif + + #if defined(DYNAMICLIGHTMAP_ON) + // Dynamic lightmaps + fixed4 realtimeColorTex = SampleDynamicLightmapBicubic(lightmapUV.zw); + half3 realtimeColor = DecodeRealtimeLightmap(realtimeColorTex); + + irradianceForAO += realtimeColor; + + #ifdef DIRLIGHTMAP_COMBINED + half4 realtimeDirTex = SampleDynamicLightmapDirBicubic(lightmapUV.zw); + irradiance += DecodeDirectionalLightmap(realtimeColor, realtimeDirTex, worldNormal); + #else + irradiance += realtimeColor; + #endif + #endif + + // VRC Light Volumes also have an additive component which can be added over lightmapping. + #if defined(_VRCLV) && !UNITY_SHOULD_SAMPLE_SH + Light volumeLight = (Light)0; + irradiance += Irradiance_SampleVRCLightVolumeAdditive(worldNormal, worldPos, volumeLight); + + // Merge lights, weighing each light's contribution by their intensity + float derivedLum = luminance(derivedLight.colorIntensity.rgb); + float volumeLum = luminance(volumeLight.colorIntensity.rgb); + float totalIntensity = derivedLum + volumeLum + FLT_EPS; + float derivedWeight = derivedLum / totalIntensity; + float volumeWeight = volumeLum / totalIntensity; + + derivedLight.l = normalize(derivedLight.l * derivedWeight + volumeLight.l * volumeWeight); + derivedLight.colorIntensity = derivedLight.colorIntensity * derivedWeight + volumeLight.colorIntensity * volumeWeight; + derivedLight.attenuation = derivedLight.attenuation * derivedWeight + volumeLight.attenuation * volumeWeight; + derivedLight.NoL = derivedLight.NoL * derivedWeight + volumeLight.NoL * volumeWeight; + #endif + + occlusion = IrradianceToExposureOcclusion(irradianceForAO); + + return irradiance; +} + #endif diff --git a/globals.cginc b/globals.cginc index cbc6dba..3688378 100644 --- a/globals.cginc +++ b/globals.cginc @@ -3,6 +3,23 @@ #include "features.cginc" +// Filamented global variables +half _ExposureOcclusion; +half _LightmapSpecularMaxSmoothness; + +#if defined(USING_BAKERY_VERTEXLM) +float bakeryLightmapMode; +#endif + +#if defined(_VRCLV) +half _VRCLVSurfaceBias; +float _UdonLightVolumeEnabled; +float _UdonLightVolumeAdditiveCount; +#endif + +// Math constants +#define FLT_EPS 1.192092896e-07 + #if defined(_SSAO) || defined(_RAYMARCHED_FOG) UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture); float4 _CameraDepthTexture_TexelSize; diff --git a/yum_brdf.cginc b/yum_brdf.cginc index 858f22d..0b4b3b1 100644 --- a/yum_brdf.cginc +++ b/yum_brdf.cginc @@ -1,157 +1,208 @@ -#ifndef __YUM_BRDF_INC -#define __YUM_BRDF_INC - -#include "UnityCG.cginc" -#include "UnityStandardConfig.cginc" -#include "UnityLightingCommon.cginc" - -#include "filamented.cginc" -#include "math.cginc" -#include "yum_pbr.cginc" -#include "yum_lighting.cginc" - -#if defined(_MATERIAL_TYPE_CLOTH) -float D_Charlie(float roughness, float NoH) { - // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" - float invAlpha = 1.0 / roughness; - float cos2h = NoH * NoH; - float sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16 - return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI); -} -#endif - -// Cloth visibility term from Neubelt and Pettineo -float V_Cloth(float NoV, float NoL) { - return 1.0 / (4.0 * (NoL + NoV - NoL * NoV)); -} - -float3 specularLobe(YumPbr pbr, float f0, - float3 h, float LoH, float NoH, float NoV, float NoL) -{ -#if defined(_MATERIAL_TYPE_CLOTH) - float D = D_Charlie(pbr.roughness, NoH); - float V = V_Cloth(NoV, NoL); - float3 F = _Cloth_Sheen_Color; - return (D * V) * F; -#else - // Fresnel - const float3 F = F_Schlick(f0, LoH); - // Normal distribution function - float D = D_GGX(pbr.roughness, NoH, h); - // Geometric shadowing - float V = V_SmithGGXCorrelated_Fast(pbr.roughness, NoV, NoL); - return (D * V) * F; -#endif -} - -float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { - const float3 h = normalize(light.view_dir + light.dir); - const float LoH = saturate(dot(light.dir, h)); - const float NoL = light.NoL; -#if defined(_WRAPPED_LIGHTING) - const float NoL_wrapped_s = light.NoL_wrapped_s; - const float NoL_wrapped_d = light.NoL_wrapped_d; -#else - const float NoL_wrapped_s = light.NoL; - const float NoL_wrapped_d = light.NoL; -#endif - const float NoV = max(1E-4, dot(pbr.normal, light.view_dir)); - const float NoH = saturate(dot(pbr.normal, h)); - const float VoL = saturate(dot(light.view_dir, light.dir)); - const float f90 = 0.5 + 2 * pbr.roughness * LoH * LoH; - -#if defined(_MATERIAL_TYPE_CLOTH) - // Cloth specific BRDF - float3 direct_cloth; - { - // Cloth diffuse BRDF - apply proper energy conservation - // Use a proper diffuse BRDF term instead of raw albedo - float3 Fd = pbr.albedo / PI; - Fd *= light.attenuation; - - #if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE) - // Energy conservative wrap diffuse for subsurface scattering - float wrap_diffuse = saturate((NoL + 0.5) / 2.25); - Fd *= wrap_diffuse; - // Apply subsurface color - Fd *= saturate(_Cloth_Subsurface_Color + NoL); - #endif - - // Cloth specular BRDF - float3 Fr = specularLobe(pbr, 0.04, h, LoH, NoH, NoV, NoL_wrapped_s); - - #if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE) - // No need to multiply by NoL when using subsurface scattering - direct_cloth = (Fd + Fr * NoL) * light.direct * _Cloth_Direct_Multiplier; - #else - direct_cloth = (Fd + Fr) * NoL * light.direct * _Cloth_Direct_Multiplier; - #endif - } -#endif - - float3 direct_standard; - { - // Typical values for different materials listed here: - // https://google.github.io/filament/Filament.html#toc4.8.3.2 - // TODO expose an enum for different types of materials - const float reflectance = _reflectance; - // f0 = amount of light reflected back when viewing surface at a right angle - // Change to match the design document - const float3 f0 = lerp(0.16 * reflectance * reflectance, pbr.albedo, pbr.metallic); - const float3 dfg = PrefilteredDFG_LUT(pbr.roughness_perceptual, NoV); - const float3 E = specularDFG(dfg, f0); - const float3 energy_compensation = energyCompensation(dfg, f0); - - float3 Fd = pbr.albedo / PI; - Fd *= (1.0 - pbr.metallic) * light.attenuation * pbr.ao; - float3 Fr = specularLobe(pbr, f0, h, LoH, NoH, NoV, NoL_wrapped_s) * pbr.ao; - - float3 color = Fd * NoL_wrapped_d + Fr * energy_compensation * NoL_wrapped_s; - direct_standard = color * light.direct; - } - -#if defined(_MATERIAL_TYPE_CLOTH) - float3 indirect_cloth; - { - // Simple indirect lighting for cloth - // Add additional corrective term to account for the fact that vrchat map - // makers suck shit and don't use enough reflection probes. - float3 Fr = _Cloth_Sheen_Color * light.specular * light.diffuse_luminance; - float3 Fd = pbr.albedo * light.diffuse * pbr.ao; - - #if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE) - // Apply subsurface color to indirect diffuse - Fd *= _Cloth_Subsurface_Color; - #endif - - indirect_cloth = (Fr + Fd) * _Cloth_Indirect_Multiplier; - } -#endif - - float3 indirect_standard; - { - const float reflectance = _reflectance; - const float3 f0 = reflectance * (1.0 - pbr.metallic) + pbr.albedo * pbr.metallic; - const float3 dfg = PrefilteredDFG_LUT(pbr.roughness_perceptual, NoV); - const float3 E = specularDFG(dfg, f0); - const float3 energy_compensation = energyCompensation(dfg, f0); - - float3 Fd = pbr.albedo * light.diffuse * (1.0 - E) * (1.0 - pbr.metallic) * pbr.ao * light.attenuation; - float3 Fr = E * light.specular * energy_compensation * pbr.ao; - - indirect_standard = Fr + Fd; - } - -#if defined(_MATERIAL_TYPE_CLOTH) - float cloth_mask = _Cloth_Mask.Sample(linear_repeat_s, i.uv01.xy); - float3 direct = lerp(direct_standard, direct_cloth, cloth_mask); - float3 indirect = lerp(indirect_standard, indirect_cloth, cloth_mask); -#else - float3 direct = direct_standard; - float3 indirect = indirect_standard; -#endif - - return float4(direct + indirect, pbr.albedo.a); -} - -#endif // __YUM_BRDF_INC +#ifndef __YUM_BRDF_INC +#define __YUM_BRDF_INC + +#include "UnityCG.cginc" +#include "UnityStandardConfig.cginc" +#include "UnityLightingCommon.cginc" + +#include "filamented.cginc" +#include "math.cginc" +#include "yum_pbr.cginc" +#include "yum_lighting.cginc" + +#if defined(_MATERIAL_TYPE_CLOTH) +float D_Charlie(float roughness, float NoH) { + // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" + float invAlpha = 1.0 / roughness; + float cos2h = NoH * NoH; + float sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16 + return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI); +} +#endif + +// Cloth visibility term from Neubelt and Pettineo +float V_Cloth(float NoV, float NoL) { + return 1.0 / (4.0 * (NoL + NoV - NoL * NoV)); +} + +float3 specularLobe(YumPbr pbr, float f0, + float3 h, float LoH, float NoH, float NoV, float NoL) +{ +#if defined(_MATERIAL_TYPE_CLOTH) + float D = D_Charlie(pbr.roughness, NoH); + float V = V_Cloth(NoV, NoL); + float3 F = _Cloth_Sheen_Color; + return (D * V) * F; +#else + // Fresnel + const float3 F = F_Schlick(f0, LoH); + // Normal distribution function + float D = D_GGX(pbr.roughness, NoH, h); + // Geometric shadowing + float V = V_SmithGGXCorrelated_Fast(pbr.roughness, NoV, NoL); + return (D * V) * F; +#endif +} + +float computeDielectricF0(float reflectance) { + return 0.16 * reflectance * reflectance; +} + +float computeSpecularAO(float NoV, float visibility, float roughness) { + // Lagarde and de Rousiers 2014, "Moving Frostbite to PBR" + return saturate(pow(NoV + visibility, exp2(-16.0 * roughness - 1.0)) - 1.0 + visibility); +} + +float singleBounceAO(float visibility) { + return visibility; // Simplified version +} + +float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { + const float3 h = normalize(light.view_dir + light.dir); + const float LoH = saturate(dot(light.dir, h)); + const float NoL = light.NoL; +#if defined(_WRAPPED_LIGHTING) + const float NoL_wrapped_s = light.NoL_wrapped_s; + const float NoL_wrapped_d = light.NoL_wrapped_d; +#else + const float NoL_wrapped_s = light.NoL; + const float NoL_wrapped_d = light.NoL; +#endif + const float NoV = max(1E-4, dot(pbr.normal, light.view_dir)); + const float NoH = saturate(dot(pbr.normal, h)); + const float VoL = saturate(dot(light.view_dir, light.dir)); + const float f90 = 0.5 + 2 * pbr.roughness * LoH * LoH; + +#if defined(_MATERIAL_TYPE_CLOTH) + // Cloth specific BRDF + float3 direct_cloth; + { + // Cloth diffuse BRDF - apply proper energy conservation + // Use a proper diffuse BRDF term instead of raw albedo + float3 Fd = pbr.albedo / PI; + Fd *= light.attenuation; + + #if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE) + // Energy conservative wrap diffuse for subsurface scattering + float wrap_diffuse = saturate((NoL + 0.5) / 2.25); + Fd *= wrap_diffuse; + // Apply subsurface color + Fd *= saturate(_Cloth_Subsurface_Color + NoL); + #endif + + // Cloth specular BRDF + float3 Fr = specularLobe(pbr, 0.04, h, LoH, NoH, NoV, NoL_wrapped_s); + + #if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE) + // No need to multiply by NoL when using subsurface scattering + direct_cloth = (Fd + Fr * NoL) * light.direct * _Cloth_Direct_Multiplier; + #else + direct_cloth = (Fd + Fr) * NoL * light.direct * _Cloth_Direct_Multiplier; + #endif + } +#endif + + float3 direct_standard; + { + // Typical values for different materials listed here: + // https://google.github.io/filament/Filament.html#toc4.8.3.2 + // TODO expose an enum for different types of materials + const float reflectance = computeDielectricF0(_reflectance); + // f0 = amount of light reflected back when viewing surface at a right angle + // Change to match the design document + const float3 f0 = lerp(reflectance, pbr.albedo, pbr.metallic); + const float3 dfg = PrefilteredDFG_LUT(pbr.roughness_perceptual, NoV); + const float3 E = specularDFG(dfg, f0); + const float3 energy_compensation = energyCompensation(dfg, f0); + + float3 Fd = pbr.albedo / PI; + Fd *= (1.0 - pbr.metallic) * light.attenuation * pbr.ao; + float3 Fr = specularLobe(pbr, f0, h, LoH, NoH, NoV, NoL_wrapped_s) * pbr.ao * PI; + + float3 color = Fd * NoL_wrapped_d + Fr * energy_compensation * NoL_wrapped_s; + direct_standard = color * light.direct; + } + +#if defined(_MATERIAL_TYPE_CLOTH) + float3 indirect_cloth; + { + // Simple indirect lighting for cloth + // Add additional corrective term to account for the fact that vrchat map + // makers suck shit and don't use enough reflection probes. + float3 Fr = _Cloth_Sheen_Color * light.specular * light.diffuse_luminance; + float3 Fd = pbr.albedo * light.diffuse * pbr.ao; + + #if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE) + // Apply subsurface color to indirect diffuse + Fd *= _Cloth_Subsurface_Color; + #endif + + indirect_cloth = (Fr + Fd) * _Cloth_Indirect_Multiplier; + } +#endif + + float3 indirect_standard; + { + const float reflectance = computeDielectricF0(_reflectance); + const float3 f0 = reflectance * (1.0 - pbr.metallic) + pbr.albedo * pbr.metallic; + const float3 dfg = PrefilteredDFG_LUT(pbr.roughness_perceptual, NoV); + const float3 E = specularDFG(dfg, f0); + const float3 energy_compensation = energyCompensation(dfg, f0); + + // Compute specular ambient occlusion + float diffuseAO = pbr.ao; + float specularAO = computeSpecularAO(NoV, diffuseAO, pbr.roughness); + float3 specularSingleBounceAO = singleBounceAO(specularAO) * energy_compensation; + + float3 Fd = pbr.albedo * light.diffuse * (1.0 - E) * (1.0 - pbr.metallic) * pbr.ao * light.attenuation; + float3 Fr = E * light.specular * specularSingleBounceAO; + + indirect_standard = Fr + Fd; + } + + // Apply lightmap-derived directional light for metallic surfaces + float3 derivedLightContribution = 0; +#if defined(_LIGHTMAP_SPECULAR) && defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED) + if (light.derivedLight.directionality > 0.001) { + // Calculate lighting vectors for derived light + const float3 h_derived = normalize(light.view_dir + light.derivedLight.direction); + const float LoH_derived = saturate(dot(light.derivedLight.direction, h_derived)); + const float NoH_derived = saturate(dot(pbr.normal, h_derived)); + const float NoL_derived = light.derivedLight.NoL; + + // Apply specular contribution from lightmap (similar to Filament's approach) + const float reflectance = computeDielectricF0(_reflectance); + const float3 f0 = lerp(reflectance, pbr.albedo, pbr.metallic); + + // Calculate specular lobe for the derived light + float3 Fr_derived = specularLobe(pbr, f0, h_derived, LoH_derived, NoH_derived, NoV, NoL_derived) * PI; + + // Apply AO and energy compensation + float specularAO = computeSpecularAO(NoV, pbr.ao, pbr.roughness); + const float3 dfg = PrefilteredDFG_LUT(pbr.roughness_perceptual, NoV); + const float3 energy_compensation = energyCompensation(dfg, f0); + + // The derived light contribution is weighted by metallic value + // This ensures metallic surfaces get shadowing from lightmaps via specular + derivedLightContribution = Fr_derived * light.derivedLight.color * + light.derivedLight.directionality * + specularAO * energy_compensation * NoL_derived; + + // For dielectrics, reduce the diffuse contribution to avoid double-counting + indirect_standard *= (1.0 - light.derivedLight.directionality * (1.0 - pbr.metallic)); + } +#endif + +#if defined(_MATERIAL_TYPE_CLOTH) + float cloth_mask = _Cloth_Mask.Sample(linear_repeat_s, i.uv01.xy); + float3 direct = lerp(direct_standard, direct_cloth, cloth_mask); + float3 indirect = lerp(indirect_standard, indirect_cloth, cloth_mask); +#else + float3 direct = direct_standard; + float3 indirect = indirect_standard; +#endif + + return float4(direct + indirect + derivedLightContribution, pbr.albedo.a); +} + +#endif // __YUM_BRDF_INC diff --git a/yum_lighting.cginc b/yum_lighting.cginc index dabc148..d1cf779 100644 --- a/yum_lighting.cginc +++ b/yum_lighting.cginc @@ -1,296 +1,330 @@ -#ifndef __YUM_LIGHTING_INC -#define __YUM_LIGHTING_INC - -#include "UnityCG.cginc" -#include "AutoLight.cginc" -#include "UnityPBSLighting.cginc" -#include "UnityLightingCommon.cginc" - -#include "features.cginc" -#include "LightVolumes.cginc" -#include "poi.cginc" -#include "yum_pbr.cginc" - -// fucking kill me -#ifndef __LTCGI_INC -#define __LTCGI_INC - -#include "features.cginc" - -#if defined(_LTCGI) -struct ltcgi_acc { - float3 diffuse; - float3 specular; -}; - -#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc" - -void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output); -void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output); - -#define LTCGI_V2_CUSTOM_INPUT ltcgi_acc -#define LTCGI_V2_DIFFUSE_CALLBACK ltcgi_cb_diffuse -#define LTCGI_V2_SPECULAR_CALLBACK ltcgi_cb_specular - -#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc" -void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output) { - acc.diffuse += output.intensity * output.color * _LTCGI_DiffuseColor; -} -void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output) { - acc.specular += output.intensity * output.color * _LTCGI_SpecularColor; -} -#endif // _LTCGI - -#endif // __LTCGI_INC - -struct YumLighting { - float3 view_dir; - float3 dir; - float3 direct; - float3 diffuse; - float diffuse_luminance; - float3 specular; - float NoL; -#if defined(_WRAPPED_LIGHTING) - float NoL_wrapped_s; // specular - float NoL_wrapped_d; // diffuse -#endif - float attenuation; - float3 L00; - float3 L01r; - float3 L01g; - float3 L01b; -}; - -float getShadowAttenuation(v2f i) -{ - float attenuation; - // This whole block is yoinked from AutoLight.cginc. I needed a way to - // control shadow strength so I had to duplicate the code. -#if defined(DIRECTIONAL_COOKIE) - DECLARE_LIGHT_COORD(i, i.worldPos); - float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); - attenuation = tex2D(_LightTexture0, lightCoord).w; -#elif defined(POINT_COOKIE) - DECLARE_LIGHT_COORD(i, i.worldPos); - float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); - attenuation = tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).r * - texCUBE(_LightTexture0, lightCoord).w; -#elif defined(DIRECTIONAL) - float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); - attenuation = 1; -#elif defined(SPOT) - DECLARE_LIGHT_COORD(i, i.worldPos); - float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); - attenuation = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) * - UnitySpotAttenuate(lightCoord.xyz); -#elif defined(POINT) - unityShadowCoord3 lightCoord = - mul(unity_WorldToLight, unityShadowCoord4(i.worldPos, 1)).xyz; - float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); - attenuation = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r; -#else - float shadow = 1; - attenuation = 1; -#endif - attenuation *= lerp(1, shadow, _Shadow_Strength); - return attenuation; -} - -float3 getDirectLightDirection(v2f i) { -#if defined(POINT) || defined(POINT_COOKIE) || defined(SPOT) - return normalize((_WorldSpaceLightPos0 - i.worldPos).xyz); -#else - return _WorldSpaceLightPos0; -#endif -} - -float GetLodRoughness(float roughness) { - return roughness * (1.7 - 0.7 * roughness); -} - -float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_luminance) { - float roughness = GetLodRoughness(pbr.roughness_perceptual); - float3 reflect_dir = reflect(-view_dir, pbr.normal); - - UnityGIInput data; - data.worldPos = i.worldPos; - data.worldViewDir = view_dir; - data.probeHDR[0] = unity_SpecCube0_HDR; - data.probeHDR[1] = unity_SpecCube1_HDR; -#if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) - data.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending -#endif -#ifdef UNITY_SPECCUBE_BOX_PROJECTION - data.boxMax[0] = unity_SpecCube0_BoxMax; - data.probePosition[0] = unity_SpecCube0_ProbePosition; - data.boxMax[1] = unity_SpecCube1_BoxMax; - data.boxMin[1] = unity_SpecCube1_BoxMin; - data.probePosition[1] = unity_SpecCube1_ProbePosition; -#endif - - const float3 env_refl = UnityGI_prefilteredRadiance(data, roughness, reflect_dir); - -#if defined(_FALLBACK_CUBEMAP) - // Check if there's no valid scene cubemap - float3 canned_refl = env_refl; - if (!SceneHasReflections() || _Fallback_Cubemap_Force) { - // Set up data for fallback sampling similar to Unity's system - half3 reflectVector = reflect(-view_dir, pbr.normal); - - #ifdef UNITY_SPECCUBE_BOX_PROJECTION - reflectVector = BoxProjectedCubemapDirection(reflectVector, data.worldPos, /*probe_position=*/0, /*box_min=*/-1, /*box_max=*/1); - #endif - - half mip = roughness * UNITY_SPECCUBE_LOD_STEPS; - float4 envSample = UNITY_SAMPLE_TEXCUBE_LOD(_Fallback_Cubemap, reflectVector, mip); - canned_refl = DecodeHDR(envSample, _Fallback_Cubemap_HDR) * _Fallback_Cubemap_Brightness * diffuse_luminance; - } -#endif - -#if defined(_FALLBACK_CUBEMAP_LIMIT_METALLIC) - return lerp(env_refl, canned_refl, pbr.metallic); -#elif defined(_FALLBACK_CUBEMAP) - return canned_refl; -#else - return env_refl; -#endif -} - -float3 yumSH9(float4 n, float3 worldPos, inout YumLighting light) { -#if defined(YUM_SH9_STANDARD) - // Unity gives us the first three bands (L0-L2) of SH coefficients as follows: - // unity_SHA*.w: L0 coefficients - // unity_SHA*.xyz: L1 coefficients - // unity_SHB*: first four of the L2 coefficients - // unity_SHC: last L2 coefficient - - // Parse out coefficients into a simpler but less efficient format. - float3 L00 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); - float3 L1_1 = float3(unity_SHAr.x, unity_SHAg.x, unity_SHAb.x); - float3 L10 = float3(unity_SHAr.y, unity_SHAg.y, unity_SHAb.y); - float3 L11 = float3(unity_SHAr.z, unity_SHAg.z, unity_SHAb.z); - float3 L2_2 = float3(unity_SHBr.x, unity_SHBg.x, unity_SHBb.x); - float3 L2_1 = float3(unity_SHBr.y, unity_SHBg.y, unity_SHBb.y); - float3 L20 = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z); - float3 L21 = float3(unity_SHBr.w, unity_SHBg.w, unity_SHBb.w); - float3 L22 = unity_SHC; - - // Equation 13 from "An Efficient Representation for Irradiance Environment - // Maps" by Ramamoorthi and Hanrahan. Note that the order of some - // coefficients is different, and normalization constants have been - // premultiplied by Unity. - float3 L0 = L00; - float3 L1 = L1_1 * n.x + L10 * n.y + L11 * n.z; - float3 L2 = - L2_2 * n.x * n.y + - L2_1 * n.y * n.z + - L20 * n.z * n.z + - L21 * n.x * n.z + - L22 * (n.x * n.x - n.y * n.y); - - light.L00 = L00; - light.L01r = unity_SHAr.xyz; - light.L01g = unity_SHAg.xyz; - light.L01b = unity_SHAb.xyz; - - return L0 + L1 + L2; -#elif 1 - // Light volumes. We omit the L01 contribution since flat shading looks - // better on avatars. - LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b); - return LightVolumeEvaluate(n.xyz, light.L00, - _UdonLightVolumeEnabled ? light.L01r : 0, - _UdonLightVolumeEnabled ? light.L01g : 0, - _UdonLightVolumeEnabled ? light.L01b : 0); -#else - // On non-photorealistic avatars, simply using the diffuse component looks - // better. *shruge* - float3 L00 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); - - light.L00 = L00; - light.L01r = unity_SHAr.xyz; - light.L01g = unity_SHAg.xyz; - light.L01b = unity_SHAb.xyz; - - return L00; -#endif -} - -float4 getIndirectDiffuse(v2f i, float4 vertexLightColor, - inout YumLighting light) { - float4 diffuse = vertexLightColor; -#if defined(FORWARD_BASE_PASS) -#if defined(LIGHTMAP_ON) - diffuse.xyz = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv01.zw)); -#else - diffuse.xyz += max(0, yumSH9(float4(i.normal, 0), i.worldPos, light)); -#endif -#endif - return diffuse; -} - -YumLighting GetYumLighting(v2f i, YumPbr pbr) { - YumLighting light = (YumLighting) 0; - - // normalize has no visibile impact in test scene - light.view_dir = -normalize(i.eyeVec.xyz); - - light.dir = getDirectLightDirection(i); - - light.direct = _LightColor0.rgb; - // TODO filament's spherical harmonics look nicer than this. - // See FilamentLightIndirect.cginc::UnityGI_Irradiance in filamented. - light.diffuse = getIndirectDiffuse(i, /*vertexLightColor=*/0, light); -#if defined(_MIN_BRIGHTNESS) - light.diffuse = max(_Min_Brightness, light.diffuse); -#endif - - light.diffuse_luminance = luminance(light.diffuse); - light.specular = getIndirectSpecular(i, pbr, light.view_dir, light.diffuse_luminance); - -#if defined(_LTCGI) - ltcgi_acc acc = (ltcgi_acc) 0; - LTCGI_Contribution( - acc, - i.worldPos, - pbr.normal, - light.view_dir, - pbr.roughness_perceptual, - 0); - light.diffuse += acc.diffuse * _LTCGI_Strength; - light.specular += acc.specular * _LTCGI_Strength; -#endif - -#if defined(_QUANTIZE_SPECULAR) - float specular_luminance = luminance(light.specular); - light.specular = light.specular * floor(specular_luminance * _Quantize_Specular_Steps) / _Quantize_Specular_Steps; -#endif -#if defined(_QUANTIZE_DIFFUSE) - light.diffuse = light.diffuse * floor(light.diffuse_luminance * _Quantize_Diffuse_Steps) / _Quantize_Diffuse_Steps; - light.diffuse_luminance = luminance(light.diffuse); -#endif - -#if defined(_BRIGHTNESS_CONTROL) - light.direct *= _Brightness_Multiplier; - light.diffuse *= _Brightness_Multiplier; - light.specular *= _Brightness_Multiplier; -#endif - - light.NoL = dot(pbr.normal, light.dir); -#if defined(_QUANTIZE_NOL) - light.NoL = floor(light.NoL * _Quantize_NoL_Steps) / _Quantize_NoL_Steps; -#endif -#if defined(_WRAPPED_LIGHTING) - light.NoL_wrapped_s = saturate(wrapNoL(light.NoL, _Wrap_NoL_Specular_Strength)); - light.NoL_wrapped_d = saturate(wrapNoL(light.NoL, _Wrap_NoL_Diffuse_Strength)); -#endif - light.NoL = saturate(light.NoL); - - light.attenuation = getShadowAttenuation(i); - - return light; -} - -#endif // __YUM_LIGHTING_INC - +#ifndef __YUM_LIGHTING_INC +#define __YUM_LIGHTING_INC + +#include "UnityCG.cginc" +#include "AutoLight.cginc" +#include "UnityPBSLighting.cginc" +#include "UnityLightingCommon.cginc" + +#include "features.cginc" +#include "LightVolumes.cginc" +#include "poi.cginc" +#include "yum_pbr.cginc" + +// fucking kill me +#ifndef __LTCGI_INC +#define __LTCGI_INC + +#include "features.cginc" + +#if defined(_LTCGI) +struct ltcgi_acc { + float3 diffuse; + float3 specular; +}; + +#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc" + +void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output); +void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output); + +#define LTCGI_V2_CUSTOM_INPUT ltcgi_acc +#define LTCGI_V2_DIFFUSE_CALLBACK ltcgi_cb_diffuse +#define LTCGI_V2_SPECULAR_CALLBACK ltcgi_cb_specular + +#include "Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc" +void ltcgi_cb_diffuse(inout ltcgi_acc acc, in ltcgi_output output) { + acc.diffuse += output.intensity * output.color * _LTCGI_DiffuseColor; +} +void ltcgi_cb_specular(inout ltcgi_acc acc, in ltcgi_output output) { + acc.specular += output.intensity * output.color * _LTCGI_SpecularColor; +} +#endif // _LTCGI + +#endif // __LTCGI_INC + +struct YumLighting { + float3 view_dir; + float3 dir; + float3 direct; + float3 diffuse; + float diffuse_luminance; + float3 specular; + float NoL; +#if defined(_WRAPPED_LIGHTING) + float NoL_wrapped_s; // specular + float NoL_wrapped_d; // diffuse +#endif + float attenuation; + float3 L00; + float3 L01r; + float3 L01g; + float3 L01b; + float occlusion; + Light derivedLight; +}; + +float getShadowAttenuation(v2f i) +{ + float attenuation; + // This whole block is yoinked from AutoLight.cginc. I needed a way to + // control shadow strength so I had to duplicate the code. +#if defined(DIRECTIONAL_COOKIE) + DECLARE_LIGHT_COORD(i, i.worldPos); + float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); + attenuation = tex2D(_LightTexture0, lightCoord).w; +#elif defined(POINT_COOKIE) + DECLARE_LIGHT_COORD(i, i.worldPos); + float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); + attenuation = tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).r * + texCUBE(_LightTexture0, lightCoord).w; +#elif defined(DIRECTIONAL) + float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); + attenuation = 1; +#elif defined(SPOT) + DECLARE_LIGHT_COORD(i, i.worldPos); + float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); + attenuation = (lightCoord.z > 0) * UnitySpotCookie(lightCoord) * + UnitySpotAttenuate(lightCoord.xyz); +#elif defined(POINT) + unityShadowCoord3 lightCoord = + mul(unity_WorldToLight, unityShadowCoord4(i.worldPos, 1)).xyz; + float shadow = UNITY_SHADOW_ATTENUATION(i, i.worldPos); + attenuation = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r; +#else + float shadow = 1; + attenuation = 1; +#endif + attenuation *= lerp(1, shadow, _Shadow_Strength); + return attenuation; +} + +float3 getDirectLightDirection(v2f i) { +#if defined(POINT) || defined(POINT_COOKIE) || defined(SPOT) + return normalize((_WorldSpaceLightPos0 - i.worldPos).xyz); +#else + return _WorldSpaceLightPos0; +#endif +} + +float GetLodRoughness(float roughness) { + return roughness * (1.7 - 0.7 * roughness); +} + +float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_luminance) { + float roughness = GetLodRoughness(pbr.roughness_perceptual); + float3 reflect_dir = reflect(-view_dir, pbr.normal); + + UnityGIInput data; + data.worldPos = i.worldPos; + data.worldViewDir = view_dir; + data.probeHDR[0] = unity_SpecCube0_HDR; + data.probeHDR[1] = unity_SpecCube1_HDR; +#if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) + data.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending +#endif +#ifdef UNITY_SPECCUBE_BOX_PROJECTION + data.boxMax[0] = unity_SpecCube0_BoxMax; + data.probePosition[0] = unity_SpecCube0_ProbePosition; + data.boxMax[1] = unity_SpecCube1_BoxMax; + data.boxMin[1] = unity_SpecCube1_BoxMin; + data.probePosition[1] = unity_SpecCube1_ProbePosition; +#endif + + const float3 env_refl = UnityGI_prefilteredRadiance(data, roughness, reflect_dir); + +#if defined(_FALLBACK_CUBEMAP) + // Check if there's no valid scene cubemap + float3 canned_refl = env_refl; + if (!SceneHasReflections() || _Fallback_Cubemap_Force) { + // Set up data for fallback sampling similar to Unity's system + half3 reflectVector = reflect(-view_dir, pbr.normal); + + #ifdef UNITY_SPECCUBE_BOX_PROJECTION + reflectVector = BoxProjectedCubemapDirection(reflectVector, data.worldPos, /*probe_position=*/0, /*box_min=*/-1, /*box_max=*/1); + #endif + + half mip = roughness * UNITY_SPECCUBE_LOD_STEPS; + float4 envSample = UNITY_SAMPLE_TEXCUBE_LOD(_Fallback_Cubemap, reflectVector, mip); + canned_refl = DecodeHDR(envSample, _Fallback_Cubemap_HDR) * _Fallback_Cubemap_Brightness * diffuse_luminance; + } +#endif + +#if defined(_FALLBACK_CUBEMAP_LIMIT_METALLIC) + return lerp(env_refl, canned_refl, pbr.metallic); +#elif defined(_FALLBACK_CUBEMAP) + return canned_refl; +#else + return env_refl; +#endif +} + +float3 yumSH9(float4 n, float3 worldPos, inout YumLighting light) { +#if defined(YUM_SH9_STANDARD) + // Unity gives us the first three bands (L0-L2) of SH coefficients as follows: + // unity_SHA*.w: L0 coefficients + // unity_SHA*.xyz: L1 coefficients + // unity_SHB*: first four of the L2 coefficients + // unity_SHC: last L2 coefficient + + // Parse out coefficients into a simpler but less efficient format. + float3 L00 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); + float3 L1_1 = float3(unity_SHAr.x, unity_SHAg.x, unity_SHAb.x); + float3 L10 = float3(unity_SHAr.y, unity_SHAg.y, unity_SHAb.y); + float3 L11 = float3(unity_SHAr.z, unity_SHAg.z, unity_SHAb.z); + float3 L2_2 = float3(unity_SHBr.x, unity_SHBg.x, unity_SHBb.x); + float3 L2_1 = float3(unity_SHBr.y, unity_SHBg.y, unity_SHBb.y); + float3 L20 = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z); + float3 L21 = float3(unity_SHBr.w, unity_SHBg.w, unity_SHBb.w); + float3 L22 = unity_SHC; + + // Equation 13 from "An Efficient Representation for Irradiance Environment + // Maps" by Ramamoorthi and Hanrahan. Note that the order of some + // coefficients is different, and normalization constants have been + // premultiplied by Unity. + float3 L0 = L00; + float3 L1 = L1_1 * n.x + L10 * n.y + L11 * n.z; + float3 L2 = + L2_2 * n.x * n.y + + L2_1 * n.y * n.z + + L20 * n.z * n.z + + L21 * n.x * n.z + + L22 * (n.x * n.x - n.y * n.y); + + light.L00 = L00; + light.L01r = unity_SHAr.xyz; + light.L01g = unity_SHAg.xyz; + light.L01b = unity_SHAb.xyz; + + return L0 + L1 + L2; +#elif 1 + // Light volumes. We omit the L01 contribution since flat shading looks + // better on avatars. + LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b); + return LightVolumeEvaluate(n.xyz, light.L00, + _UdonLightVolumeEnabled ? light.L01r : 0, + _UdonLightVolumeEnabled ? light.L01g : 0, + _UdonLightVolumeEnabled ? light.L01b : 0); +#else + // On non-photorealistic avatars, simply using the diffuse component looks + // better. *shruge* + float3 L00 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); + + light.L00 = L00; + light.L01r = unity_SHAr.xyz; + light.L01g = unity_SHAg.xyz; + light.L01b = unity_SHAb.xyz; + + return L00; +#endif +} + +float3 SubtractMainLightWithRealtimeAttenuationFromLightmap(float3 lightmap, float attenuation, float4 bakedColorTex, float3 normalWorld) { + float3 shadowColor = unity_ShadowColor.rgb; + float shadowStrength = _LightShadowData.x; + + // Calculate estimated light contribution that should be shadowed + float ndotl = saturate(dot(normalWorld, _WorldSpaceLightPos0.xyz)); + float3 estimatedLightContributionMaskedByInverseOfShadow = ndotl * (1.0 - attenuation) * _LightColor0.rgb; + float3 subtractedLightmap = lightmap - estimatedLightContributionMaskedByInverseOfShadow; + + // Apply shadow color and strength + float3 realtimeShadow = max(subtractedLightmap, shadowColor); + realtimeShadow = lerp(realtimeShadow, lightmap, shadowStrength); + + // Pick darkest color + return min(lightmap, realtimeShadow); +} + +YumLighting GetYumLighting(v2f i, YumPbr pbr) { + YumLighting light = (YumLighting) 0; + + // normalize has no visibile impact in test scene + light.view_dir = -normalize(i.eyeVec.xyz); + + light.dir = getDirectLightDirection(i); + + light.direct = _LightColor0.rgb; + + // Calculate attenuation first, before diffuse lighting +#if defined(LIGHTMAP_ON) + light.attenuation = 1; +#else + light.attenuation = getShadowAttenuation(i); +#endif + + // Use filamented's comprehensive irradiance calculation + float occlusion; + Light derivedLight; + float3 tangentNormal = mul(pbr.normal, transpose(float3x3(i.tangent, i.binormal, i.normal))); + float3x3 tangentToWorld = float3x3(i.tangent, i.binormal, i.normal); + + light.diffuse = UnityGI_Irradiance( + pbr.normal, // worldNormal + i.worldPos, // worldPos + float4(i.uv01.zw, 0, 0), // lightmapUV (xy = uv0, zw = uv1) + float3(0,0,0), // ambient (will be calculated internally) + light.attenuation, // attenuation + tangentNormal, // tangentNormal + tangentToWorld, // tangentToWorld + #if defined(USING_BAKERY_VERTEXLMSH) + // You'll need to add these to your v2f if using Bakery vertex SH + i.bakeryVertexSH, + #elif defined(USING_BAKERY_VERTEXLMDIR) + // You'll need to add this to your v2f if using Bakery vertex directional + i.bakeryVertexDir, + #endif + occlusion, // out occlusion + derivedLight // out Light + ); + +#if defined(_MIN_BRIGHTNESS) + light.diffuse = max(_Min_Brightness, light.diffuse); +#endif + + light.diffuse_luminance = luminance(light.diffuse); + light.specular = getIndirectSpecular(i, pbr, light.view_dir, light.diffuse_luminance); + +#if defined(_LTCGI) + ltcgi_acc acc = (ltcgi_acc) 0; + LTCGI_Contribution( + acc, + i.worldPos, + pbr.normal, + light.view_dir, + pbr.roughness_perceptual, + 0); + light.diffuse += acc.diffuse * _LTCGI_Strength; + light.specular += acc.specular * _LTCGI_Strength; +#endif + +#if defined(_QUANTIZE_SPECULAR) + float specular_luminance = luminance(light.specular); + light.specular = light.specular * floor(specular_luminance * _Quantize_Specular_Steps) / _Quantize_Specular_Steps; +#endif +#if defined(_QUANTIZE_DIFFUSE) + light.diffuse = light.diffuse * floor(light.diffuse_luminance * _Quantize_Diffuse_Steps) / _Quantize_Diffuse_Steps; + light.diffuse_luminance = luminance(light.diffuse); +#endif + +#if defined(_BRIGHTNESS_CONTROL) + light.direct *= _Brightness_Multiplier; + light.diffuse *= _Brightness_Multiplier; + light.specular *= _Brightness_Multiplier; +#endif + + light.NoL = dot(pbr.normal, light.dir); +#if defined(_QUANTIZE_NOL) + light.NoL = floor(light.NoL * _Quantize_NoL_Steps) / _Quantize_NoL_Steps; +#endif +#if defined(_WRAPPED_LIGHTING) + light.NoL_wrapped_s = saturate(wrapNoL(light.NoL, _Wrap_NoL_Specular_Strength)); + light.NoL_wrapped_d = saturate(wrapNoL(light.NoL, _Wrap_NoL_Diffuse_Strength)); +#endif + light.NoL = saturate(light.NoL); + + return light; +} + +#endif // __YUM_LIGHTING_INC + -- cgit v1.2.3