diff options
Diffstat (limited to '')
-rw-r--r-- | VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc | 1240 | ||||
-rw-r--r-- | VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc.meta | 9 |
2 files changed, 1249 insertions, 0 deletions
diff --git a/VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc b/VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc new file mode 100644 index 00000000..8a6bd3ca --- /dev/null +++ b/VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc @@ -0,0 +1,1240 @@ +#ifndef BAKERY_INCLUDED +#define BAKERY_INCLUDED + +float bakeryLightmapMode; +//float2 bakeryLightmapSize; +#define BAKERYMODE_DEFAULT 0 +#define BAKERYMODE_VERTEXLM 1.0f +#define BAKERYMODE_RNM 2.0f +#define BAKERYMODE_SH 3.0f + +//#define BAKERY_SSBUMP + +//#define BAKERY_COMPRESSED_VOLUME_RGBM + +// can't fit vertexLM SH to sm3_0 interpolators +#ifndef SHADER_API_D3D11 + #undef BAKERY_VERTEXLMSH +#endif + +// can't do stuff on sm2_0 due to standard shader alrady taking up all instructions +#if SHADER_TARGET < 30 + #undef BAKERY_BICUBIC + #undef BAKERY_LMSPEC + + #undef BAKERY_RNM + #undef BAKERY_SH + #undef BAKERY_VERTEXLM +#endif + +#ifndef _NORMALMAP + #undef BAKERY_RNM + //#undef BAKERY_SH +#endif + +#ifndef UNITY_SHOULD_SAMPLE_SH + #undef BAKERY_PROBESHNONLINEAR +#endif + +#if defined(BAKERY_RNM) && defined(BAKERY_LMSPEC) +#define BAKERY_RNMSPEC +#endif + +#ifndef BAKERY_VERTEXLM + #undef BAKERY_VERTEXLMDIR + #undef BAKERY_VERTEXLMSH + #undef BAKERY_VERTEXLMMASK +#endif + +#define lumaConv float3(0.2125f, 0.7154f, 0.0721f) + +#if defined(BAKERY_SH) || defined(BAKERY_VERTEXLMSH) || defined(BAKERY_PROBESHNONLINEAR) || defined(BAKERY_VOLUME) +float shEvaluateDiffuseL1Geomerics(float L0, float3 L1, float3 n) +{ + // average energy + float R0 = L0; + + // avg direction of incoming light + float3 R1 = 0.5f * L1; + + // directional brightness + float lenR1 = length(R1); + + // linear angle between normal and direction 0-1 + //float q = 0.5f * (1.0f + dot(R1 / lenR1, n)); + //float q = dot(R1 / lenR1, n) * 0.5 + 0.5; + float q = dot(normalize(R1), n) * 0.5 + 0.5; + + // power for q + // lerps from 1 (linear) to 3 (cubic) based on directionality + float p = 1.0f + 2.0f * lenR1 / R0; + + // dynamic range constant + // should vary between 4 (highly directional) and 0 (ambient) + float a = (1.0f - lenR1 / R0) / (1.0f + lenR1 / R0); + + return R0 * (a + (1.0f - a) * (p + 1.0f) * pow(q, p)); +} +#endif + +#ifdef BAKERY_VERTEXLM + float4 unpack4NFloats(float src) { + //return fmod(float4(src / 262144.0, src / 4096.0, src / 64.0, src), 64.0)/64.0; + return frac(float4(src / (262144.0*64), src / (4096.0*64), src / (64.0*64), src)); + } + float3 unpack3NFloats(float src) { + float r = frac(src); + float g = frac(src * 256.0); + float b = frac(src * 65536.0); + return float3(r, g, b); + } +#if defined(BAKERY_VERTEXLMDIR) + void BakeryVertexLMDirection(inout float3 diffuseColor, inout float3 specularColor, float3 lightDirection, float3 vertexNormalWorld, float3 normalWorld, float3 viewDir, float smoothness) + { + float3 dominantDir = Unity_SafeNormalize(lightDirection); + half halfLambert = dot(normalWorld, dominantDir) * 0.5 + 0.5; + half flatNormalHalfLambert = dot(vertexNormalWorld, dominantDir) * 0.5 + 0.5; + + #ifdef BAKERY_LMSPEC + half3 halfDir = Unity_SafeNormalize(normalize(dominantDir) - viewDir); + half nh = saturate(dot(normalWorld, halfDir)); + half perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness); + half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); + half spec = GGXTerm(nh, roughness); + specularColor = spec * diffuseColor; + #endif + + diffuseColor *= halfLambert / max(1e-4h, flatNormalHalfLambert); + } +#elif defined(BAKERY_VERTEXLMSH) + void BakeryVertexLMSH(inout float3 diffuseColor, inout float3 specularColor, float3 shL1x, float3 shL1y, float3 shL1z, float3 normalWorld, float3 viewDir, float smoothness) + { + float3 L0 = diffuseColor; + float3 nL1x = shL1x; + float3 nL1y = shL1y; + float3 nL1z = shL1z; + float3 L1x = nL1x * L0 * 2; + float3 L1y = nL1y * L0 * 2; + float3 L1z = nL1z * L0 * 2; + + float3 sh; + #if BAKERY_SHNONLINEAR + //sh.r = shEvaluateDiffuseL1Geomerics(L0.r, float3(L1x.r, L1y.r, L1z.r), normalWorld); + //sh.g = shEvaluateDiffuseL1Geomerics(L0.g, float3(L1x.g, L1y.g, L1z.g), normalWorld); + //sh.b = shEvaluateDiffuseL1Geomerics(L0.b, float3(L1x.b, L1y.b, L1z.b), normalWorld); + + float lumaL0 = dot(L0, 1); + float lumaL1x = dot(L1x, 1); + float lumaL1y = dot(L1y, 1); + float lumaL1z = dot(L1z, 1); + float lumaSH = shEvaluateDiffuseL1Geomerics(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld); + + sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + float regularLumaSH = dot(sh, 1); + //sh *= regularLumaSH < 0.001 ? 1 : (lumaSH / regularLumaSH); + sh *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16)); + + #else + sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + #endif + + diffuseColor = max(sh, 0.0); + + #ifdef BAKERY_LMSPEC + float3 dominantDir = float3(dot(nL1x, lumaConv), dot(nL1y, lumaConv), dot(nL1z, lumaConv)); + float focus = saturate(length(dominantDir)); + half3 halfDir = Unity_SafeNormalize(normalize(dominantDir) - viewDir); + half nh = saturate(dot(normalWorld, halfDir)); + half perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness );//* sqrt(focus)); + half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); + half spec = GGXTerm(nh, roughness); + specularColor = max(spec * sh, 0.0); + #endif + } +#endif +#endif + +#ifdef BAKERY_BICUBIC +float BakeryBicubic_w0(float a) +{ + return (1.0f/6.0f)*(a*(a*(-a + 3.0f) - 3.0f) + 1.0f); +} + +float BakeryBicubic_w1(float a) +{ + return (1.0f/6.0f)*(a*a*(3.0f*a - 6.0f) + 4.0f); +} + +float BakeryBicubic_w2(float a) +{ + return (1.0f/6.0f)*(a*(a*(-3.0f*a + 3.0f) + 3.0f) + 1.0f); +} + +float BakeryBicubic_w3(float a) +{ + return (1.0f/6.0f)*(a*a*a); +} + +float BakeryBicubic_g0(float a) +{ + return BakeryBicubic_w0(a) + BakeryBicubic_w1(a); +} + +float BakeryBicubic_g1(float a) +{ + return BakeryBicubic_w2(a) + BakeryBicubic_w3(a); +} + +float BakeryBicubic_h0(float a) +{ + return -1.0f + BakeryBicubic_w1(a) / (BakeryBicubic_w0(a) + BakeryBicubic_w1(a)) + 0.5f; +} + +float BakeryBicubic_h1(float a) +{ + return 1.0f + BakeryBicubic_w3(a) / (BakeryBicubic_w2(a) + BakeryBicubic_w3(a)) + 0.5f; +} +#endif + +struct BakeryVertexInput +{ + float4 vertex : POSITION; +#ifdef BAKERY_VERTEXLM + fixed4 color : COLOR; + #ifdef BAKERY_VERTEXLMSH + float2 uv3 : TEXCOORD3; + #endif +#endif + half3 normal : NORMAL; + float2 uv0 : TEXCOORD0; + float2 uv1 : TEXCOORD1; +#if defined(DYNAMICLIGHTMAP_ON) || defined(UNITY_PASS_META) + float2 uv2 : TEXCOORD2; +#endif +#if defined(_TANGENT_TO_WORLD) || defined(BAKERY_RNMSPEC) + half4 tangent : TANGENT; +#endif + UNITY_VERTEX_INPUT_INSTANCE_ID +}; + +float4 BakeryTexCoords(BakeryVertexInput v) +{ + float4 texcoord; + texcoord.xy = TRANSFORM_TEX(v.uv0, _MainTex); // Always source from uv0 + texcoord.zw = TRANSFORM_TEX(((_UVSec == 0) ? v.uv0 : v.uv1), _DetailAlbedoMap); + return texcoord; +} + +inline half4 BakeryVertexGIForward(BakeryVertexInput v, float3 posWorld, half3 normalWorld) +{ + half4 ambientOrLightmapUV = 0; + // Static lightmaps +#ifndef LIGHTMAP_OFF + ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; + ambientOrLightmapUV.zw = 0; + // Sample light probe for Dynamic objects only (no static or dynamic lightmaps) +#elif UNITY_SHOULD_SAMPLE_SH +#ifdef VERTEXLIGHT_ON + // Approximated illumination from non-important point lights + ambientOrLightmapUV.rgb = Shade4PointLights( + unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, + unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, + unity_4LightAtten0, posWorld, normalWorld); +#endif + + ambientOrLightmapUV.rgb = ShadeSHPerVertex(normalWorld, ambientOrLightmapUV.rgb); +#endif + +#ifdef DYNAMICLIGHTMAP_ON + ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; +#endif + +#ifdef BAKERY_VERTEXLM + if (bakeryLightmapMode == BAKERYMODE_VERTEXLM) + { + #ifdef BAKERY_VERTEXLMMASK + ambientOrLightmapUV = unpack4NFloats(v.uv1.x); + #endif + } +#endif + + return ambientOrLightmapUV; +} + +//Forward Pass +struct BakeryVertexOutputForwardBase +{ + float4 pos : SV_POSITION; + float4 tex : TEXCOORD0; + half3 eyeVec : TEXCOORD1; + +#if UNITY_VERSION >= 201740 + float4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax] +#else + half4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax] +#endif + +#if defined(BAKERY_RNMSPEC) + half3 viewDirForParallax : TEXCOORD13; +#endif + + half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UV + UNITY_SHADOW_COORDS(6) + UNITY_FOG_COORDS(7) + +#ifdef BAKERY_VERTEXLM + float4 color : COLOR_centroid; + #if defined(BAKERY_VERTEXLMDIR) + float3 lightDirection : TEXCOORD10_centroid; // is this even legal + #elif defined(BAKERY_VERTEXLMSH) + float3 shL1x : TEXCOORD10_centroid; + float3 shL1y : TEXCOORD11_centroid; + float3 shL1z : TEXCOORD12_centroid; + #endif +#endif + + // next ones would not fit into SM2.0 limits, but they are always for SM3.0+ +#if UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME || (UNITY_REQUIRE_FRAG_WORLDPOS && !UNITY_PACK_WORLDPOS_WITH_TANGENT) + float3 posWorld : TEXCOORD8; +#endif + +#if UNITY_OPTIMIZE_TEXCUBELOD + #if UNITY_SPECCUBE_BOX_PROJECTION + half3 reflUVW : TEXCOORD9; + #else + half3 reflUVW : TEXCOORD8; + #endif +#endif + + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO +}; + +BakeryVertexOutputForwardBase bakeryVertForwardBase(BakeryVertexInput v) +{ + UNITY_SETUP_INSTANCE_ID(v); + BakeryVertexOutputForwardBase o; + UNITY_INITIALIZE_OUTPUT(BakeryVertexOutputForwardBase, o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + float4 posWorld = mul(unity_ObjectToWorld, v.vertex); + #if UNITY_REQUIRE_FRAG_WORLDPOS + #if UNITY_PACK_WORLDPOS_WITH_TANGENT + o.tangentToWorldAndPackedData[0].w = posWorld.x; + o.tangentToWorldAndPackedData[1].w = posWorld.y; + o.tangentToWorldAndPackedData[2].w = posWorld.z; + #else + o.posWorld = posWorld.xyz; + #endif + #endif + o.pos = UnityObjectToClipPos(v.vertex); + + float3 normalWorld = UnityObjectToWorldNormal(v.normal); + o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); + + o.tex = BakeryTexCoords(v); +#ifdef _TANGENT_TO_WORLD + float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); + + float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w); + o.tangentToWorldAndPackedData[0].xyz = tangentToWorld[0]; + o.tangentToWorldAndPackedData[1].xyz = tangentToWorld[1]; + o.tangentToWorldAndPackedData[2].xyz = tangentToWorld[2]; +#else + o.tangentToWorldAndPackedData[0].xyz = 0; + o.tangentToWorldAndPackedData[1].xyz = 0; + o.tangentToWorldAndPackedData[2].xyz = normalWorld; +#endif + //We need this for shadow receving + UNITY_TRANSFER_SHADOW(o, v.uv1); + + o.ambientOrLightmapUV = BakeryVertexGIForward(v, posWorld, normalWorld); + +#if defined(_PARALLAXMAP) || defined(BAKERY_RNMSPEC) + TANGENT_SPACE_ROTATION; +#endif + +#if defined(_PARALLAXMAP) + half3 viewDirForParallax = mul(rotation, ObjSpaceViewDir(v.vertex)); + o.tangentToWorldAndPackedData[0].w = viewDirForParallax.x; + o.tangentToWorldAndPackedData[1].w = viewDirForParallax.y; + o.tangentToWorldAndPackedData[2].w = viewDirForParallax.z; +#endif + +#if defined(BAKERY_RNMSPEC) + o.viewDirForParallax = mul(rotation, ObjSpaceViewDir(v.vertex)); +#endif + +#if UNITY_OPTIMIZE_TEXCUBELOD + o.reflUVW = reflect(o.eyeVec, normalWorld); +#endif + +#ifdef BAKERY_VERTEXLM + // Unpack from RGBM + o.color = v.color; + o.color.rgb *= o.color.a * 8.0f; + o.color.rgb *= o.color.rgb; + + #if defined(BAKERY_VERTEXLMDIR) + o.lightDirection = unpack3NFloats(v.uv1.y) * 2 - 1; + #elif defined(BAKERY_VERTEXLMSH) + o.shL1x = unpack3NFloats(v.uv1.y) * 2 - 1; + o.shL1y = unpack3NFloats(v.uv3.x) * 2 - 1; + o.shL1z = unpack3NFloats(v.uv3.y) * 2 - 1; + #endif +#endif + + UNITY_TRANSFER_FOG(o, o.pos); + return o; +} + +/* +inline UnityGI BakeryFragmentGI (FragmentCommonData s, half occlusion, half4 i_ambientOrLightmapUV, half atten, UnityLight light, bool reflections) +{ + UnityGIInput d; + d.light = light; + d.worldPos = s.posWorld; + d.worldViewDir = -s.eyeVec; + d.atten = atten; + #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) + d.ambient = 0; + d.lightmapUV = i_ambientOrLightmapUV; + #else + d.ambient = i_ambientOrLightmapUV.rgb; + d.lightmapUV = 0; + #endif + + d.probeHDR[0] = unity_SpecCube0_HDR; + d.probeHDR[1] = unity_SpecCube1_HDR; + #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) + d.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending + #endif + #ifdef UNITY_SPECCUBE_BOX_PROJECTION + d.boxMax[0] = unity_SpecCube0_BoxMax; + d.probePosition[0] = unity_SpecCube0_ProbePosition; + d.boxMax[1] = unity_SpecCube1_BoxMax; + d.boxMin[1] = unity_SpecCube1_BoxMin; + d.probePosition[1] = unity_SpecCube1_ProbePosition; + #endif + + if(reflections) + { + Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(s.smoothness, -s.eyeVec, s.normalWorld, s.specColor); + // Replace the reflUVW if it has been compute in Vertex shader. Note: the compiler will optimize the calcul in UnityGlossyEnvironmentSetup itself + #if UNITY_STANDARD_SIMPLE + g.reflUVW = s.reflUVW; + #endif + + return UnityGlobalIllumination (d, occlusion, s.normalWorld, g); + } + else + { + return UnityGlobalIllumination (d, occlusion, s.normalWorld); + } +} +*/ + +#if defined(BAKERY_RNM) || defined(BAKERY_SH) +sampler2D _RNM0, _RNM1, _RNM2; +float4 _RNM0_TexelSize; +#endif + +#ifdef BAKERY_VOLUME +Texture3D _Volume0, _Volume1, _Volume2, _VolumeMask; +SamplerState sampler_Volume0; +float3 _VolumeMin, _VolumeInvSize; +float3 _GlobalVolumeMin, _GlobalVolumeInvSize; + #ifdef BAKERY_COMPRESSED_VOLUME + Texture3D _Volume3; + #endif + #ifdef BAKERY_VOLROTATION + float4x4 _GlobalVolumeMatrix, _VolumeMatrix; + #endif +#endif + +#ifdef BAKERY_BICUBIC + // Bicubic + float4 BakeryTex2D(sampler2D tex, float2 uv, float4 texelSize) + { + float x = uv.x * texelSize.z; + float y = uv.y * texelSize.z; + + x -= 0.5f; + y -= 0.5f; + + float px = floor(x); + float py = floor(y); + + float fx = x - px; + float fy = y - py; + + float g0x = BakeryBicubic_g0(fx); + float g1x = BakeryBicubic_g1(fx); + float h0x = BakeryBicubic_h0(fx); + float h1x = BakeryBicubic_h1(fx); + float h0y = BakeryBicubic_h0(fy); + float h1y = BakeryBicubic_h1(fy); + + return BakeryBicubic_g0(fy) * ( g0x * tex2D(tex, (float2(px + h0x, py + h0y) * texelSize.x)) + + g1x * tex2D(tex, (float2(px + h1x, py + h0y) * texelSize.x))) + + + BakeryBicubic_g1(fy) * ( g0x * tex2D(tex, (float2(px + h0x, py + h1y) * texelSize.x)) + + g1x * tex2D(tex, (float2(px + h1x, py + h1y) * texelSize.x))); + } + float4 BakeryTex2D(Texture2D tex, SamplerState s, float2 uv, float4 texelSize) + { + float x = uv.x * texelSize.z; + float y = uv.y * texelSize.z; + + x -= 0.5f; + y -= 0.5f; + + float px = floor(x); + float py = floor(y); + + float fx = x - px; + float fy = y - py; + + float g0x = BakeryBicubic_g0(fx); + float g1x = BakeryBicubic_g1(fx); + float h0x = BakeryBicubic_h0(fx); + float h1x = BakeryBicubic_h1(fx); + float h0y = BakeryBicubic_h0(fy); + float h1y = BakeryBicubic_h1(fy); + + return BakeryBicubic_g0(fy) * ( g0x * tex.Sample(s, (float2(px + h0x, py + h0y) * texelSize.x)) + + g1x * tex.Sample(s, (float2(px + h1x, py + h0y) * texelSize.x))) + + + BakeryBicubic_g1(fy) * ( g0x * tex.Sample(s, (float2(px + h0x, py + h1y) * texelSize.x)) + + g1x * tex.Sample(s, (float2(px + h1x, py + h1y) * texelSize.x))); + } +#else + // Bilinear + float4 BakeryTex2D(sampler2D tex, float2 uv, float4 texelSize) + { + return tex2D(tex, uv); + } + float4 BakeryTex2D(Texture2D tex, SamplerState s, float2 uv, float4 texelSize) + { + return tex.Sample(s, uv); + } +#endif + +#ifdef DIRLIGHTMAP_COMBINED +#ifdef BAKERY_LMSPEC +float BakeryDirectionalLightmapSpecular(float2 lmUV, float3 normalWorld, float3 viewDir, float smoothness) +{ + float3 dominantDir = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, lmUV).xyz * 2 - 1; + half3 halfDir = Unity_SafeNormalize(normalize(dominantDir) - viewDir); + half nh = saturate(dot(normalWorld, halfDir)); + half perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness); + half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); + half spec = GGXTerm(nh, roughness); + return spec; +} +#endif +#endif + +#ifdef BAKERY_RNM +void BakeryRNM(inout float3 diffuseColor, inout float3 specularColor, float2 lmUV, float3 normalMap, float smoothness, float3 viewDirT) +{ + const float3 rnmBasis0 = float3(0.816496580927726f, 0, 0.5773502691896258f); + const float3 rnmBasis1 = float3(-0.4082482904638631f, 0.7071067811865475f, 0.5773502691896258f); + const float3 rnmBasis2 = float3(-0.4082482904638631f, -0.7071067811865475f, 0.5773502691896258f); + + float3 rnm0 = DecodeLightmap(BakeryTex2D(_RNM0, lmUV, _RNM0_TexelSize)); + float3 rnm1 = DecodeLightmap(BakeryTex2D(_RNM1, lmUV, _RNM0_TexelSize)); + float3 rnm2 = DecodeLightmap(BakeryTex2D(_RNM2, lmUV, _RNM0_TexelSize)); + + #ifdef BAKERY_SSBUMP + diffuseColor = normalMap.x * rnm0 + + normalMap.z * rnm1 + + normalMap.y * rnm2; + diffuseColor *= 2; + #else + diffuseColor = saturate(dot(rnmBasis0, normalMap)) * rnm0 + + saturate(dot(rnmBasis1, normalMap)) * rnm1 + + saturate(dot(rnmBasis2, normalMap)) * rnm2; + #endif + + #ifdef BAKERY_LMSPEC + float3 dominantDirT = rnmBasis0 * dot(rnm0, lumaConv) + + rnmBasis1 * dot(rnm1, lumaConv) + + rnmBasis2 * dot(rnm2, lumaConv); + + float3 dominantDirTN = NormalizePerPixelNormal(dominantDirT); + float3 specColor = saturate(dot(rnmBasis0, dominantDirTN)) * rnm0 + + saturate(dot(rnmBasis1, dominantDirTN)) * rnm1 + + saturate(dot(rnmBasis2, dominantDirTN)) * rnm2; + + half3 halfDir = Unity_SafeNormalize(dominantDirTN - viewDirT); + half nh = saturate(dot(normalMap, halfDir)); + half perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness); + half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); + half spec = GGXTerm(nh, roughness); + specularColor = spec * specColor; + #endif +} +#endif + +#ifdef BAKERY_SH +void BakerySH(inout float3 diffuseColor, inout float3 specularColor, float2 lmUV, float3 normalWorld, float3 viewDir, float smoothness) +{ +#ifdef SHADER_API_D3D11 + float3 L0 = DecodeLightmap(BakeryTex2D(unity_Lightmap, samplerunity_Lightmap, lmUV, _RNM0_TexelSize)); +#else + float3 L0 = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, lmUV)); +#endif + float3 nL1x = BakeryTex2D(_RNM0, lmUV, _RNM0_TexelSize) * 2 - 1; + float3 nL1y = BakeryTex2D(_RNM1, lmUV, _RNM0_TexelSize) * 2 - 1; + float3 nL1z = BakeryTex2D(_RNM2, lmUV, _RNM0_TexelSize) * 2 - 1; + float3 L1x = nL1x * L0 * 2; + float3 L1y = nL1y * L0 * 2; + float3 L1z = nL1z * 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(lumaL0, float3(lumaL1x, lumaL1y, lumaL1z), normalWorld); + + sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; + float regularLumaSH = dot(sh, 1); + //sh *= regularLumaSH < 0.001 ? 1 : (lumaSH / regularLumaSH); + sh *= lerp(1, lumaSH / regularLumaSH, saturate(regularLumaSH*16)); + + //sh.r = shEvaluateDiffuseL1Geomerics(L0.r, float3(L1x.r, L1y.r, L1z.r), normalWorld); + //sh.g = shEvaluateDiffuseL1Geomerics(L0.g, float3(L1x.g, L1y.g, L1z.g), normalWorld); + //sh.b = shEvaluateDiffuseL1Geomerics(L0.b, float3(L1x.b, L1y.b, L1z.b), normalWorld); + +#else + sh = L0 + normalWorld.x * L1x + normalWorld.y * L1y + normalWorld.z * L1z; +#endif + + diffuseColor = max(sh, 0.0); + + #ifdef BAKERY_LMSPEC + float3 dominantDir = float3(dot(nL1x, lumaConv), dot(nL1y, lumaConv), dot(nL1z, lumaConv)); + float focus = saturate(length(dominantDir)); + half3 halfDir = Unity_SafeNormalize(normalize(dominantDir) - viewDir); + half nh = saturate(dot(normalWorld, halfDir)); + half perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness );//* sqrt(focus)); + half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); + half spec = GGXTerm(nh, roughness); + + sh = L0 + dominantDir.x * L1x + dominantDir.y * L1y + dominantDir.z * L1z; + + specularColor = max(spec * sh, 0.0); + #endif +} +#endif + +half4 bakeryFragForwardBase(BakeryVertexOutputForwardBase i) : SV_Target +{ + FRAGMENT_SETUP(s) +#if UNITY_OPTIMIZE_TEXCUBELOD + s.reflUVW = i.reflUVW; +#endif + + UnityLight mainLight = MainLight (); + UNITY_LIGHT_ATTENUATION(atten, i, s.posWorld); + +#ifdef BAKERY_VOLUME + bool isGlobal = _VolumeInvSize.x > 1000000; // ~inf + float3 volViewDir = s.eyeVec; + #ifdef BAKERY_VOLROTATION + float4x4 volMatrix = (isGlobal ? _GlobalVolumeMatrix : _VolumeMatrix); + float3 volInvSize = (isGlobal ? _GlobalVolumeInvSize : _VolumeInvSize); + float3 lpUV = mul(volMatrix, float4(s.posWorld,1)).xyz * volInvSize + 0.5f; + float3 volNormal = mul((float3x3)volMatrix, s.normalWorld); + #ifdef BAKERY_LMSPEC + volViewDir = mul((float3x3)volMatrix, volViewDir); + #endif + #else + float3 lpUV = (s.posWorld - (isGlobal ? _GlobalVolumeMin : _VolumeMin)) * (isGlobal ? _GlobalVolumeInvSize : _VolumeInvSize); + float3 volNormal = s.normalWorld; + #endif +#endif + +#ifdef BAKERY_VOLUME + mainLight.color *= saturate(dot(_VolumeMask.Sample(sampler_Volume0, lpUV), unity_OcclusionMaskSelector)); +#elif BAKERY_VERTEXLMMASK + if (bakeryLightmapMode == BAKERYMODE_VERTEXLM) + { + mainLight.color *= saturate(dot(i.ambientOrLightmapUV, unity_OcclusionMaskSelector)); + } +#endif + + half occlusion = Occlusion(i.tex.xy); + UnityGI gi = FragmentGI(s, occlusion, i.ambientOrLightmapUV, atten, mainLight); + +#ifdef BAKERY_VOLUME + + #ifdef BAKERY_COMPRESSED_VOLUME + float4 tex0, tex1, tex2, tex3; + float3 L0, L1x, L1y, L1z; + tex0 = _Volume0.Sample(sampler_Volume0, lpUV); + tex1 = _Volume1.Sample(sampler_Volume0, lpUV) * 2 - 1; + tex2 = _Volume2.Sample(sampler_Volume0, lpUV) * 2 - 1; + tex3 = _Volume3.Sample(sampler_Volume0, lpUV) * 2 - 1; + #ifdef BAKERY_COMPRESSED_VOLUME_RGBM + L0 = tex0.xyz * (tex0.w * 8.0f); + L0 *= L0; + #else + L0 = tex0.xyz; + #endif + L1x = tex1.xyz * L0; + L1y = tex2.xyz * L0; + L1z = tex3.xyz * L0; + #else + float4 tex0, tex1, tex2; + float3 L0, L1x, L1y, L1z; + tex0 = _Volume0.Sample(sampler_Volume0, lpUV); + tex1 = _Volume1.Sample(sampler_Volume0, lpUV); + tex2 = _Volume2.Sample(sampler_Volume0, lpUV); + L0 = tex0.xyz; + L1x = tex1.xyz; + L1y = tex2.xyz; + L1z = float3(tex0.w, tex1.w, tex2.w); + #endif + gi.indirect.diffuse.r = shEvaluateDiffuseL1Geomerics(L0.r, float3(L1x.r, L1y.r, L1z.r), volNormal); + gi.indirect.diffuse.g = shEvaluateDiffuseL1Geomerics(L0.g, float3(L1x.g, L1y.g, L1z.g), volNormal); + gi.indirect.diffuse.b = shEvaluateDiffuseL1Geomerics(L0.b, float3(L1x.b, L1y.b, L1z.b), volNormal); + + #ifdef UNITY_COLORSPACE_GAMMA + gi.indirect.diffuse = pow(gi.indirect.diffuse, 1.0f / 2.2f); + #endif + + #ifdef BAKERY_LMSPEC + float3 nL1x = L1x / L0; + float3 nL1y = L1y / L0; + float3 nL1z = L1z / L0; + float3 dominantDir = float3(dot(nL1x, lumaConv), dot(nL1y, lumaConv), dot(nL1z, lumaConv)); + half3 halfDir = Unity_SafeNormalize(normalize(dominantDir) - volViewDir); + half nh = saturate(dot(volNormal, halfDir)); + half perceptualRoughness = SmoothnessToPerceptualRoughness(s.smoothness); + half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); + half spec = GGXTerm(nh, roughness); + float3 sh = L0 + dominantDir.x * L1x + dominantDir.y * L1y + dominantDir.z * L1z; + gi.indirect.specular += max(spec * sh, 0.0); + #endif + +#elif BAKERY_PROBESHNONLINEAR + float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); + gi.indirect.diffuse.r = shEvaluateDiffuseL1Geomerics(L0.r, unity_SHAr.xyz, s.normalWorld); + gi.indirect.diffuse.g = shEvaluateDiffuseL1Geomerics(L0.g, unity_SHAg.xyz, s.normalWorld); + gi.indirect.diffuse.b = shEvaluateDiffuseL1Geomerics(L0.b, unity_SHAb.xyz, s.normalWorld); +#endif + +#ifdef DIRLIGHTMAP_COMBINED +#ifdef BAKERY_LMSPEC + if (bakeryLightmapMode == BAKERYMODE_DEFAULT) + { + gi.indirect.specular += BakeryDirectionalLightmapSpecular(i.ambientOrLightmapUV.xy, s.normalWorld, s.eyeVec, s.smoothness) * gi.indirect.diffuse; + } +#endif +#endif + +#ifdef BAKERY_VERTEXLM + if (bakeryLightmapMode == BAKERYMODE_VERTEXLM) + { + gi.indirect.diffuse = i.color.rgb; + float3 prevSpec = gi.indirect.specular; + + #if defined(BAKERY_VERTEXLMDIR) + BakeryVertexLMDirection(gi.indirect.diffuse, gi.indirect.specular, i.lightDirection, i.tangentToWorldAndPackedData[2].xyz, s.normalWorld, s.eyeVec, s.smoothness); + gi.indirect.specular += prevSpec; + #elif defined (BAKERY_VERTEXLMSH) + BakeryVertexLMSH(gi.indirect.diffuse, gi.indirect.specular, i.shL1x, i.shL1y, i.shL1z, s.normalWorld, s.eyeVec, s.smoothness); + gi.indirect.specular += prevSpec; + #endif + } +#endif + +#ifdef BAKERY_RNM + if (bakeryLightmapMode == BAKERYMODE_RNM) + { + #ifdef BAKERY_SSBUMP + float3 normalMap = tex2D(_BumpMap, i.tex.xy).xyz; + #else + float3 normalMap = NormalInTangentSpace(i.tex); + #endif + + float3 eyeVecT = 0; + #ifdef BAKERY_LMSPEC + eyeVecT = -NormalizePerPixelNormal(i.viewDirForParallax); + #endif + + float3 prevSpec = gi.indirect.specular; + BakeryRNM(gi.indirect.diffuse, gi.indirect.specular, i.ambientOrLightmapUV.xy, normalMap, s.smoothness, eyeVecT); + gi.indirect.specular += prevSpec; + } +#endif + +#ifdef BAKERY_SH + #if SHADER_TARGET >= 30 + if (bakeryLightmapMode == BAKERYMODE_SH) + #endif + { + float3 prevSpec = gi.indirect.specular; + BakerySH(gi.indirect.diffuse, gi.indirect.specular, i.ambientOrLightmapUV.xy, s.normalWorld, s.eyeVec, s.smoothness); + gi.indirect.specular += prevSpec; + } +#endif + + half4 c = UNITY_BRDF_PBS(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect); + + c.rgb += UNITY_BRDF_GI(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, occlusion, gi); + c.rgb += Emission(i.tex.xy); + + UNITY_APPLY_FOG(i.fogCoord, c.rgb); + + return OutputForward(c, s.alpha); +} + + +// Additive forward pass (one light per pass) +struct BakeryVertexOutputForwardAdd +{ + float4 pos : SV_POSITION; + float4 tex : TEXCOORD0; + half3 eyeVec : TEXCOORD1; +#if UNITY_VERSION >= 201740 + float4 tangentToWorldAndLightDir[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax] +#else + half4 tangentToWorldAndLightDir[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax] +#endif + float3 posWorld : TEXCOORD5; + UNITY_SHADOW_COORDS(6) + UNITY_FOG_COORDS(7) + + // next ones would not fit into SM2.0 limits, but they are always for SM3.0+ +#if defined(_PARALLAXMAP) + half3 viewDirForParallax : TEXCOORD8; +#endif + +#ifdef BAKERY_VERTEXLMMASK + fixed4 shadowMask : COLOR; +#endif + + UNITY_VERTEX_OUTPUT_STEREO +}; + +BakeryVertexOutputForwardAdd bakeryVertForwardAdd(BakeryVertexInput v) +{ + UNITY_SETUP_INSTANCE_ID(v); + BakeryVertexOutputForwardAdd o; + UNITY_INITIALIZE_OUTPUT(BakeryVertexOutputForwardAdd, o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + float4 posWorld = mul(unity_ObjectToWorld, v.vertex); + o.pos = UnityObjectToClipPos(v.vertex); + + o.tex = BakeryTexCoords(v); + o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); + o.posWorld = posWorld.xyz; + float3 normalWorld = UnityObjectToWorldNormal(v.normal); +#ifdef _TANGENT_TO_WORLD + float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); + + float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w); + o.tangentToWorldAndLightDir[0].xyz = tangentToWorld[0]; + o.tangentToWorldAndLightDir[1].xyz = tangentToWorld[1]; + o.tangentToWorldAndLightDir[2].xyz = tangentToWorld[2]; +#else + o.tangentToWorldAndLightDir[0].xyz = 0; + o.tangentToWorldAndLightDir[1].xyz = 0; + o.tangentToWorldAndLightDir[2].xyz = normalWorld; +#endif + //We need this for shadow receving + UNITY_TRANSFER_SHADOW(o, v.uv1); + + float3 lightDir = _WorldSpaceLightPos0.xyz - posWorld.xyz * _WorldSpaceLightPos0.w; +#ifndef USING_DIRECTIONAL_LIGHT + lightDir = NormalizePerVertexNormal(lightDir); +#endif + o.tangentToWorldAndLightDir[0].w = lightDir.x; + o.tangentToWorldAndLightDir[1].w = lightDir.y; + o.tangentToWorldAndLightDir[2].w = lightDir.z; + +#ifdef _PARALLAXMAP + TANGENT_SPACE_ROTATION; + o.viewDirForParallax = mul(rotation, ObjSpaceViewDir(v.vertex)); +#endif + +#ifdef BAKERY_VERTEXLMMASK + o.shadowMask = unpack4NFloats(v.uv1.x); +#endif + + UNITY_TRANSFER_FOG(o, o.pos); + return o; +} + +half4 bakeryFragForwardAdd(BakeryVertexOutputForwardAdd i) : SV_Target +{ + FRAGMENT_SETUP_FWDADD(s) + + UNITY_LIGHT_ATTENUATION(atten, i, s.posWorld) + UnityLight light = AdditiveLight (IN_LIGHTDIR_FWDADD(i), atten); + UnityIndirect noIndirect = ZeroIndirect (); + + half4 c = UNITY_BRDF_PBS(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, light, noIndirect); + +#ifdef BAKERY_VOLUME + bool isGlobal = _VolumeInvSize.x > 1000000; // ~inf + + #ifdef BAKERY_VOLROTATION + float4x4 volMatrix = (isGlobal ? _GlobalVolumeMatrix : _VolumeMatrix); + float3 volInvSize = (isGlobal ? _GlobalVolumeInvSize : _VolumeInvSize); + float3 lpUV = mul(volMatrix, float4(s.posWorld,1)).xyz * volInvSize + 0.5f; + #else + float3 lpUV = (s.posWorld - (isGlobal ? _GlobalVolumeMin : _VolumeMin)) * (isGlobal ? _GlobalVolumeInvSize : _VolumeInvSize); + #endif + + c *= saturate(dot(_VolumeMask.Sample(sampler_Volume0, lpUV), unity_OcclusionMaskSelector)); + +#elif BAKERY_VERTEXLMMASK + if (bakeryLightmapMode == BAKERYMODE_VERTEXLM) + { + c *= saturate(dot(i.shadowMask, unity_OcclusionMaskSelector)); + } +#endif + + UNITY_APPLY_FOG_COLOR(i.fogCoord, c.rgb, half4(0,0,0,0)); // fog towards black in additive pass + + return OutputForward(c, s.alpha); +} + + +//Deferred Pass +struct BakeryVertexOutputDeferred +{ + float4 pos : SV_POSITION; + float4 tex : TEXCOORD0; + half3 eyeVec : TEXCOORD1; + +#if UNITY_VERSION >= 201740 + float4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax] +#else + half4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax] +#endif + +#if defined(BAKERY_RNMSPEC) + half3 viewDirForParallax : TEXCOORD9; +#endif + + half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UVs + +#ifdef BAKERY_VERTEXLM + fixed4 color : COLOR; + #if defined(BAKERY_VERTEXLMDIR) + float3 lightDirection : TEXCOORD8; + #elif defined(BAKERY_VERTEXLMSH) + float3 shL1x : TEXCOORD8_centroid; + float3 shL1y : TEXCOORD10_centroid; + float3 shL1z : TEXCOORD11_centroid; + #endif +#endif + +#if UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME || (UNITY_REQUIRE_FRAG_WORLDPOS && !UNITY_PACK_WORLDPOS_WITH_TANGENT) || BAKERY_VOLUME + float3 posWorld : TEXCOORD6; +#endif + +#if UNITY_OPTIMIZE_TEXCUBELOD +#if UNITY_SPECCUBE_BOX_PROJECTION + half3 reflUVW : TEXCOORD7; +#else + half3 reflUVW : TEXCOORD6; +#endif +#endif + + UNITY_VERTEX_OUTPUT_STEREO +}; + +BakeryVertexOutputDeferred bakeryVertDeferred(BakeryVertexInput v) +{ + UNITY_SETUP_INSTANCE_ID(v); + BakeryVertexOutputDeferred o; + UNITY_INITIALIZE_OUTPUT(BakeryVertexOutputDeferred, o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + float4 posWorld = mul(unity_ObjectToWorld, v.vertex); +#if UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME || BAKERY_VOLUME + o.posWorld = posWorld; +#endif + o.pos = UnityObjectToClipPos(v.vertex); + + o.tex = BakeryTexCoords(v); + o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); + float3 normalWorld = UnityObjectToWorldNormal(v.normal); +#ifdef _TANGENT_TO_WORLD + float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); + + float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w); + o.tangentToWorldAndPackedData[0].xyz = tangentToWorld[0]; + o.tangentToWorldAndPackedData[1].xyz = tangentToWorld[1]; + o.tangentToWorldAndPackedData[2].xyz = tangentToWorld[2]; +#else + o.tangentToWorldAndPackedData[0].xyz = 0; + o.tangentToWorldAndPackedData[1].xyz = 0; + o.tangentToWorldAndPackedData[2].xyz = normalWorld; +#endif + + o.ambientOrLightmapUV = 0; + +#ifndef LIGHTMAP_OFF + o.ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; +#elif UNITY_SHOULD_SAMPLE_SH + o.ambientOrLightmapUV.rgb = ShadeSHPerVertex(normalWorld, o.ambientOrLightmapUV.rgb); +#endif +#ifdef DYNAMICLIGHTMAP_ON + o.ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; +#endif + +#ifdef BAKERY_VERTEXLMMASK + if (bakeryLightmapMode == BAKERYMODE_VERTEXLM) + { + o.ambientOrLightmapUV = unpack4NFloats(v.uv1); + } +#endif + +#if defined(_PARALLAXMAP) || defined(BAKERY_RNMSPEC) + TANGENT_SPACE_ROTATION; +#endif + +#if defined(_PARALLAXMAP) + half3 viewDirForParallax = mul(rotation, ObjSpaceViewDir(v.vertex)); + o.tangentToWorldAndPackedData[0].w = viewDirForParallax.x; + o.tangentToWorldAndPackedData[1].w = viewDirForParallax.y; + o.tangentToWorldAndPackedData[2].w = viewDirForParallax.z; +#endif + +#if defined(BAKERY_RNMSPEC) + o.viewDirForParallax = mul(rotation, ObjSpaceViewDir(v.vertex)); +#endif + +#ifdef BAKERY_VERTEXLM + // Unpack from RGBM + o.color = v.color; + o.color.rgb *= o.color.a * 8.0f; + o.color.rgb *= o.color.rgb; + + #if defined(BAKERY_VERTEXLMDIR) + o.lightDirection = unpack3NFloats(v.uv1.y) * 2 - 1; + #elif defined(BAKERY_VERTEXLMSH) + o.shL1x = unpack3NFloats(v.uv1.y) * 2 - 1; + o.shL1y = unpack3NFloats(v.uv3.x) * 2 - 1; + o.shL1z = unpack3NFloats(v.uv3.y) * 2 - 1; + #endif +#endif + +#if UNITY_OPTIMIZE_TEXCUBELOD + o.reflUVW = reflect(o.eyeVec, normalWorld); +#endif + + return o; +} + +void bakeryFragDeferred( + BakeryVertexOutputDeferred i, + out half4 outDiffuse : SV_Target0, // RT0: diffuse color (rgb), occlusion (a) + out half4 outSpecSmoothness : SV_Target1, // RT1: spec color (rgb), smoothness (a) + out half4 outNormal : SV_Target2, // RT2: normal (rgb), --unused, very low precision-- (a) + out half4 outEmission : SV_Target3 // RT3: emission (rgb), --unused-- (a) +#if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) + ,out half4 outShadowMask : SV_Target4 // RT4: shadowmask (rgba) +#endif +) +{ +#if (SHADER_TARGET < 30) + outDiffuse = 1; + outSpecSmoothness = 1; + outNormal = 0; + outEmission = 0; + #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) + outShadowMask = 1; + #endif + return; +#endif + + FRAGMENT_SETUP(s) +#if UNITY_OPTIMIZE_TEXCUBELOD + s.reflUVW = i.reflUVW; +#endif + + // no analytic lights in this pass + UnityLight dummyLight = DummyLight(); + half atten = 1; + + // only GI + half occlusion = Occlusion(i.tex.xy); +#if UNITY_ENABLE_REFLECTION_BUFFERS + bool sampleReflectionsInDeferred = false; +#else + bool sampleReflectionsInDeferred = true; +#endif + + UnityGI gi = FragmentGI(s, occlusion, i.ambientOrLightmapUV, atten, dummyLight, sampleReflectionsInDeferred); + +#ifdef BAKERY_VOLUME + bool isGlobal = _VolumeInvSize.x > 1000000; // ~inf + float3 volViewDir = s.eyeVec; + + #ifdef BAKERY_VOLROTATION + float4x4 volMatrix = (isGlobal ? _GlobalVolumeMatrix : _VolumeMatrix); + float3 volInvSize = (isGlobal ? _GlobalVolumeInvSize : _VolumeInvSize); + float3 lpUV = mul(volMatrix, float4(i.posWorld,1)).xyz * volInvSize + 0.5f; + float3 volNormal = mul((float3x3)volMatrix, s.normalWorld); + #ifdef BAKERY_LMSPEC + volViewDir = mul((float3x3)volMatrix, volViewDir); + #endif + #else + float3 lpUV = (i.posWorld - (isGlobal ? _GlobalVolumeMin : _VolumeMin)) * (isGlobal ? _GlobalVolumeInvSize : _VolumeInvSize); + float3 volNormal = s.normalWorld; + #endif + + #ifdef BAKERY_COMPRESSED_VOLUME + float4 tex0, tex1, tex2, tex3; + float3 L0, L1x, L1y, L1z; + tex0 = _Volume0.Sample(sampler_Volume0, lpUV); + tex1 = _Volume1.Sample(sampler_Volume0, lpUV) * 2 - 1; + tex2 = _Volume2.Sample(sampler_Volume0, lpUV) * 2 - 1; + tex3 = _Volume3.Sample(sampler_Volume0, lpUV) * 2 - 1; + #ifdef BAKERY_COMPRESSED_VOLUME_RGBM + L0 = tex0.xyz * (tex0.w * 8.0f); + L0 *= L0; + #else + L0 = tex0.xyz; + #endif + L1x = tex1.xyz * L0; + L1y = tex2.xyz * L0; + L1z = tex3.xyz * L0; + #else + float4 tex0, tex1, tex2; + float3 L0, L1x, L1y, L1z; + tex0 = _Volume0.Sample(sampler_Volume0, lpUV); + tex1 = _Volume1.Sample(sampler_Volume0, lpUV); + tex2 = _Volume2.Sample(sampler_Volume0, lpUV); + L0 = tex0.xyz; + L1x = tex1.xyz; + L1y = tex2.xyz; + L1z = float3(tex0.w, tex1.w, tex2.w); + #endif + + gi.indirect.diffuse.r = shEvaluateDiffuseL1Geomerics(L0.r, float3(L1x.r, L1y.r, L1z.r), volNormal); + gi.indirect.diffuse.g = shEvaluateDiffuseL1Geomerics(L0.g, float3(L1x.g, L1y.g, L1z.g), volNormal); + gi.indirect.diffuse.b = shEvaluateDiffuseL1Geomerics(L0.b, float3(L1x.b, L1y.b, L1z.b), volNormal); + #ifdef UNITY_COLORSPACE_GAMMA + gi.indirect.diffuse = pow(gi.indirect.diffuse, 1.0f / 2.2f); + #endif + + #ifdef BAKERY_LMSPEC + float3 nL1x = L1x / L0; + float3 nL1y = L1y / L0; + float3 nL1z = L1z / L0; + float3 dominantDir = float3(dot(nL1x, lumaConv), dot(nL1y, lumaConv), dot(nL1z, lumaConv)); + half3 halfDir = Unity_SafeNormalize(normalize(dominantDir) - volViewDir); + half nh = saturate(dot(volNormal, halfDir)); + half perceptualRoughness = SmoothnessToPerceptualRoughness(s.smoothness); + half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); + half spec = GGXTerm(nh, roughness); + float3 sh = L0 + dominantDir.x * L1x + dominantDir.y * L1y + dominantDir.z * L1z; + gi.indirect.specular += max(spec * sh, 0.0); + #endif + +#elif BAKERY_PROBESHNONLINEAR + float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); + gi.indirect.diffuse.r = shEvaluateDiffuseL1Geomerics(L0.r, unity_SHAr.xyz, s.normalWorld); + gi.indirect.diffuse.g = shEvaluateDiffuseL1Geomerics(L0.g, unity_SHAg.xyz, s.normalWorld); + gi.indirect.diffuse.b = shEvaluateDiffuseL1Geomerics(L0.b, unity_SHAb.xyz, s.normalWorld); +#endif + +#ifdef DIRLIGHTMAP_COMBINED +#ifdef BAKERY_LMSPEC + if (bakeryLightmapMode == BAKERYMODE_DEFAULT) + { + gi.indirect.specular += BakeryDirectionalLightmapSpecular(i.ambientOrLightmapUV.xy, s.normalWorld, s.eyeVec, s.smoothness) * gi.indirect.diffuse; + } +#endif +#endif + +#ifdef BAKERY_VERTEXLM + if (bakeryLightmapMode == BAKERYMODE_VERTEXLM) + { + gi.indirect.diffuse = i.color.rgb; + float3 prevSpec = gi.indirect.specular; + + #if defined(BAKERY_VERTEXLMDIR) + BakeryVertexLMDirection(gi.indirect.diffuse, gi.indirect.specular, i.lightDirection, i.tangentToWorldAndPackedData[2].xyz, s.normalWorld, s.eyeVec, s.smoothness); + gi.indirect.specular += prevSpec; + #elif defined (BAKERY_VERTEXLMSH) + BakeryVertexLMSH(gi.indirect.diffuse, gi.indirect.specular, i.shL1x, i.shL1y, i.shL1z, s.normalWorld, s.eyeVec, s.smoothness); + gi.indirect.specular += prevSpec; + #endif + } +#endif + +#ifdef BAKERY_RNM + if (bakeryLightmapMode == BAKERYMODE_RNM) + { + #ifdef BAKERY_SSBUMP + float3 normalMap = tex2D(_BumpMap, i.tex.xy).xyz; + #else + float3 normalMap = NormalInTangentSpace(i.tex); + #endif + + float3 eyeVecT = 0; + #ifdef BAKERY_LMSPEC + eyeVecT = -NormalizePerPixelNormal(i.viewDirForParallax); + #endif + + float3 prevSpec = gi.indirect.specular; + BakeryRNM(gi.indirect.diffuse, gi.indirect.specular, i.ambientOrLightmapUV.xy, normalMap, s.smoothness, eyeVecT); + gi.indirect.specular += prevSpec; + } +#endif + +#ifdef BAKERY_SH + #if SHADER_TARGET >= 30 + if (bakeryLightmapMode == BAKERYMODE_SH) + #endif + { + float3 prevSpec = gi.indirect.specular; + BakerySH(gi.indirect.diffuse, gi.indirect.specular, i.ambientOrLightmapUV.xy, s.normalWorld, s.eyeVec, s.smoothness); + gi.indirect.specular += prevSpec; + } +#endif + + half3 color = UNITY_BRDF_PBS(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect).rgb; + + color += UNITY_BRDF_GI(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, occlusion, gi); + +#ifdef _EMISSION + color += Emission(i.tex.xy); +#endif + +#ifndef UNITY_HDR_ON + color.rgb = exp2(-color.rgb); +#endif + + outDiffuse = half4(s.diffColor, occlusion); + outSpecSmoothness = half4(s.specColor, s.smoothness); + outNormal = half4(s.normalWorld*0.5 + 0.5, 1); + outEmission = half4(color, 1); + +// Baked direct lighting occlusion if any +#if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) + #ifdef BAKERY_VOLUME + outShadowMask = _VolumeMask.Sample(sampler_Volume0, lpUV); + #elif BAKERY_VERTEXLMMASK + outShadowMask = i.ambientOrLightmapUV; + #else + outShadowMask = UnityGetRawBakedOcclusions(i.ambientOrLightmapUV.xy, IN_WORLDPOS(i)); + #endif +#endif +} + +#endif diff --git a/VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc.meta b/VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc.meta new file mode 100644 index 00000000..2dca2546 --- /dev/null +++ b/VRCSDK3Worlds/Assets/Bakery/shader/Bakery.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1f45fcc349188584095300fd024e8f8b +timeCreated: 1538411299 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: |