gutterball-3/Gutterball 3/Assets/AdamPlaneReflection/Shared/UnityStandardCore.cginc
SkunkStudios 0b195a0fc1 Custom Balls and Cosmic Alleys
Strike it big with amazing bowling action! Everything that made Gutterball 3D a hit is here - incredible 3D graphics, cool ball-rolling controls, hilarious characters - and more! Eight all-new alleys are waxed and ready for you to toss your choice of 85 unique bowling balls. As you play, earn points and cash and unlock alleys and balls. Even customize a ball with your own settings and images! Addictive bowling fun that will bowl you over!
2025-01-16 16:07:45 +07:00

734 lines
22 KiB
HLSL

#ifndef UNITY_STANDARD_CORE_INCLUDED
#define UNITY_STANDARD_CORE_INCLUDED
#include "UnityCG.cginc"
#include "UnityShaderVariables.cginc"
#include "UnityInstancing.cginc"
#include "UnityStandardConfig.cginc"
#include "UnityStandardInput.cginc"
#include "UnityPBSLighting.cginc"
#include "UnityStandardUtils.cginc"
#include "UnityStandardBRDF.cginc"
#include "AutoLight.cginc"
//-------------------------------------------------------------------------------------
// counterpart for NormalizePerPixelNormal
// skips normalization per-vertex and expects normalization to happen per-pixel
half3 NormalizePerVertexNormal (float3 n) // takes float to avoid overflow
{
#if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE
return normalize(n);
#else
return n; // will normalize per-pixel instead
#endif
}
half3 NormalizePerPixelNormal (half3 n)
{
#if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE
return n;
#else
return normalize(n);
#endif
}
//-------------------------------------------------------------------------------------
UnityLight MainLight (half3 normalWorld)
{
UnityLight l;
#ifdef LIGHTMAP_OFF
l.color = _LightColor0.rgb;
l.dir = _WorldSpaceLightPos0.xyz;
l.ndotl = LambertTerm (normalWorld, l.dir);
#else
// no light specified by the engine
// analytical light might be extracted from Lightmap data later on in the shader depending on the Lightmap type
l.color = half3(0.f, 0.f, 0.f);
l.ndotl = 0.f;
l.dir = half3(0.f, 0.f, 0.f);
#endif
return l;
}
UnityLight AdditiveLight (half3 normalWorld, half3 lightDir, half atten)
{
UnityLight l;
l.color = _LightColor0.rgb;
l.dir = lightDir;
#ifndef USING_DIRECTIONAL_LIGHT
l.dir = NormalizePerPixelNormal(l.dir);
#endif
l.ndotl = LambertTerm (normalWorld, l.dir);
// shadow the light
l.color *= atten;
return l;
}
UnityLight DummyLight (half3 normalWorld)
{
UnityLight l;
l.color = 0;
l.dir = half3 (0,1,0);
l.ndotl = LambertTerm (normalWorld, l.dir);
return l;
}
UnityIndirect ZeroIndirect ()
{
UnityIndirect ind;
ind.diffuse = 0;
ind.specular = 0;
return ind;
}
//-------------------------------------------------------------------------------------
// Common fragment setup
// deprecated
half3 WorldNormal(half4 tan2world[3])
{
return normalize(tan2world[2].xyz);
}
// deprecated
#ifdef _TANGENT_TO_WORLD
half3x3 ExtractTangentToWorldPerPixel(half4 tan2world[3])
{
half3 t = tan2world[0].xyz;
half3 b = tan2world[1].xyz;
half3 n = tan2world[2].xyz;
#if UNITY_TANGENT_ORTHONORMALIZE
n = NormalizePerPixelNormal(n);
// ortho-normalize Tangent
t = normalize (t - n * dot(t, n));
// recalculate Binormal
half3 newB = cross(n, t);
b = newB * sign (dot (newB, b));
#endif
return half3x3(t, b, n);
}
#else
half3x3 ExtractTangentToWorldPerPixel(half4 tan2world[3])
{
return half3x3(0,0,0,0,0,0,0,0,0);
}
#endif
half3 PerPixelWorldNormal(float4 i_tex, half4 tangentToWorld[3])
{
#ifdef _NORMALMAP
half3 tangent = tangentToWorld[0].xyz;
half3 binormal = tangentToWorld[1].xyz;
half3 normal = tangentToWorld[2].xyz;
#if UNITY_TANGENT_ORTHONORMALIZE
normal = NormalizePerPixelNormal(normal);
// ortho-normalize Tangent
tangent = normalize (tangent - normal * dot(tangent, normal));
// recalculate Binormal
half3 newB = cross(normal, tangent);
binormal = newB * sign (dot (newB, binormal));
#endif
half3 normalTangent = NormalInTangentSpace(i_tex);
half3 normalWorld = NormalizePerPixelNormal(tangent * normalTangent.x + binormal * normalTangent.y + normal * normalTangent.z); // @TODO: see if we can squeeze this normalize on SM2.0 as well
#else
half3 normalWorld = normalize(tangentToWorld[2].xyz);
#endif
return normalWorld;
}
#ifdef _PARALLAXMAP
#define IN_VIEWDIR4PARALLAX(i) NormalizePerPixelNormal(half3(i.tangentToWorldAndParallax[0].w,i.tangentToWorldAndParallax[1].w,i.tangentToWorldAndParallax[2].w))
#define IN_VIEWDIR4PARALLAX_FWDADD(i) NormalizePerPixelNormal(i.viewDirForParallax.xyz)
#else
#define IN_VIEWDIR4PARALLAX(i) half3(0,0,0)
#define IN_VIEWDIR4PARALLAX_FWDADD(i) half3(0,0,0)
#endif
//adam-begin:
#if 1 //UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME || defined(_SKINNED_MESH)
//adam-end:
#define IN_WORLDPOS(i) i.posWorld
#else
#define IN_WORLDPOS(i) half3(0,0,0)
#endif
#define IN_LIGHTDIR_FWDADD(i) half3(i.tangentToWorldAndLightDir[0].w, i.tangentToWorldAndLightDir[1].w, i.tangentToWorldAndLightDir[2].w)
#define FRAGMENT_SETUP(x) FragmentCommonData x = \
FragmentSetup(i.tex, i.eyeVec, IN_VIEWDIR4PARALLAX(i), i.tangentToWorldAndParallax, IN_WORLDPOS(i));
#define FRAGMENT_SETUP_FWDADD(x) FragmentCommonData x = \
FragmentSetup(i.tex, i.eyeVec, IN_VIEWDIR4PARALLAX_FWDADD(i), i.tangentToWorldAndLightDir, half3(0,0,0));
struct FragmentCommonData
{
half3 diffColor, specColor;
// Note: oneMinusRoughness & oneMinusReflectivity for optimization purposes, mostly for DX9 SM2.0 level.
// Most of the math is being done on these (1-x) values, and that saves a few precious ALU slots.
half oneMinusReflectivity, oneMinusRoughness;
half3 normalWorld, eyeVec, posWorld;
half alpha;
#if UNITY_OPTIMIZE_TEXCUBELOD || UNITY_STANDARD_SIMPLE
half3 reflUVW;
#endif
#if UNITY_STANDARD_SIMPLE
half3 tangentSpaceNormal;
#endif
};
#ifndef UNITY_SETUP_BRDF_INPUT
#define UNITY_SETUP_BRDF_INPUT SpecularSetup
#endif
inline FragmentCommonData SpecularSetup (float4 i_tex)
{
half4 specGloss = SpecularGloss(i_tex.xy);
half3 specColor = specGloss.rgb;
half oneMinusRoughness = specGloss.a;
half oneMinusReflectivity;
half3 diffColor = EnergyConservationBetweenDiffuseAndSpecular (Albedo(i_tex), specColor, /*out*/ oneMinusReflectivity);
FragmentCommonData o = (FragmentCommonData)0;
o.diffColor = diffColor;
o.specColor = specColor;
o.oneMinusReflectivity = oneMinusReflectivity;
o.oneMinusRoughness = oneMinusRoughness;
return o;
}
//inline FragmentCommonData MetallicSetup (float4 i_tex)
//{
// half2 metallicGloss = MetallicGloss(i_tex.xy);
// half metallic = metallicGloss.x;
// half oneMinusRoughness = metallicGloss.y; // this is 1 minus the square root of real roughness m.
//
// half oneMinusReflectivity;
// half3 specColor;
// half3 diffColor = DiffuseAndSpecularFromMetallic (Albedo(i_tex), metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
//
// FragmentCommonData o = (FragmentCommonData)0;
// o.diffColor = diffColor;
// o.specColor = specColor;
// o.oneMinusReflectivity = oneMinusReflectivity;
// o.oneMinusRoughness = oneMinusRoughness;
// return o;
//}
inline FragmentCommonData FragmentSetup (float4 i_tex, half3 i_eyeVec, half3 i_viewDirForParallax, half4 tangentToWorld[3], half3 i_posWorld)
{
i_tex = Parallax(i_tex, i_viewDirForParallax);
half alpha = Alpha(i_tex.xy);
#if defined(_ALPHATEST_ON)
clip (alpha - _Cutoff);
#endif
FragmentCommonData o = UNITY_SETUP_BRDF_INPUT (i_tex);
o.normalWorld = PerPixelWorldNormal(i_tex, tangentToWorld);
o.eyeVec = NormalizePerPixelNormal(i_eyeVec);
o.posWorld = i_posWorld;
// NOTE: shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
o.diffColor = PreMultiplyAlpha (o.diffColor, alpha, o.oneMinusReflectivity, /*out*/ o.alpha);
return o;
}
inline UnityGI FragmentGI (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.boxMax[0] = unity_SpecCube0_BoxMax;
d.boxMin[0] = unity_SpecCube0_BoxMin;
d.probePosition[0] = unity_SpecCube0_ProbePosition;
d.probeHDR[0] = unity_SpecCube0_HDR;
d.boxMax[1] = unity_SpecCube1_BoxMax;
d.boxMin[1] = unity_SpecCube1_BoxMin;
d.probePosition[1] = unity_SpecCube1_ProbePosition;
d.probeHDR[1] = unity_SpecCube1_HDR;
if(reflections)
{
Unity_GlossyEnvironmentData g;
g.roughness = 1 - s.oneMinusRoughness;
#if UNITY_OPTIMIZE_TEXCUBELOD || UNITY_STANDARD_SIMPLE
g.reflUVW = s.reflUVW;
#else
g.reflUVW = reflect(s.eyeVec, s.normalWorld);
#endif
return UnityGlobalIllumination (d, occlusion, s.normalWorld, g);
}
else
{
return UnityGlobalIllumination (d, occlusion, s.normalWorld);
}
}
inline UnityGI FragmentGI (FragmentCommonData s, half occlusion, half4 i_ambientOrLightmapUV, half atten, UnityLight light)
{
return FragmentGI(s, occlusion, i_ambientOrLightmapUV, atten, light, true);
}
//-------------------------------------------------------------------------------------
half4 OutputForward (half4 output, half alphaFromSurface)
{
#if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
output.a = alphaFromSurface;
#else
UNITY_OPAQUE_ALPHA(output.a);
#endif
return output;
}
inline half4 VertexGIForward(VertexInput 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
return ambientOrLightmapUV;
}
// ------------------------------------------------------------------
// Base forward pass (directional light, emission, lightmaps, ...)
struct VertexOutputForwardBase
{
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndParallax[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax]
half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UV
SHADOW_COORDS(6)
UNITY_FOG_COORDS(7)
// next ones would not fit into SM2.0 limits, but they are always for SM3.0+
//adam-begin:
#if 1 //UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME
//adam-end:
float3 posWorld : TEXCOORD8;
#endif
#if UNITY_OPTIMIZE_TEXCUBELOD
#if UNITY_SPECCUBE_BOX_PROJECTION
half3 reflUVW : TEXCOORD9;
#else
half3 reflUVW : TEXCOORD8;
#endif
#endif
//adam-begin: shader additions
half vertexOcclusion : TEXCOORD10;
#if PLANE_REFLECTION_USER_CLIPPLANE
float clipDistance : SV_ClipDistance;
#endif
//adam-end:
};
VertexOutputForwardBase vertForwardBase (VertexInput v)
{
UNITY_SETUP_INSTANCE_ID(v);
VertexOutputForwardBase o;
UNITY_INITIALIZE_OUTPUT(VertexOutputForwardBase, o);
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
//adam-begin:
#if 1 //UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME
o.posWorld = posWorld.xyz;
#endif
//adam-end:
o.pos = UnityObjectToClipPos(v.vertex);
o.tex = TexCoords(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.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndParallax[0].xyz = 0;
o.tangentToWorldAndParallax[1].xyz = 0;
o.tangentToWorldAndParallax[2].xyz = normalWorld;
#endif
//We need this for shadow receving
TRANSFER_SHADOW(o);
o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld);
#ifdef _PARALLAXMAP
TANGENT_SPACE_ROTATION;
half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
o.tangentToWorldAndParallax[0].w = viewDirForParallax.x;
o.tangentToWorldAndParallax[1].w = viewDirForParallax.y;
o.tangentToWorldAndParallax[2].w = viewDirForParallax.z;
#endif
#if UNITY_OPTIMIZE_TEXCUBELOD
o.reflUVW = reflect(o.eyeVec, normalWorld);
#endif
//adam-begin: shader additions
o.vertexOcclusion = v.color.a;
#if PLANE_REFLECTION_USER_CLIPPLANE
o.clipDistance = dot(posWorld, _PlaneReflectionClipPlane);
#endif
//adam-end:
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 fragForwardBaseInternal (VertexOutputForwardBase i)
{
FRAGMENT_SETUP(s)
#if UNITY_OPTIMIZE_TEXCUBELOD
s.reflUVW = i.reflUVW;
#endif
UnityLight mainLight = MainLight (s.normalWorld);
half atten = SHADOW_ATTENUATION(i);
//adam-begin: pass vertex occlusion to occlusion input function
half occlusion = Occlusion(i.tex.xy, i.vertexOcclusion);
//adam-end:
UnityGI gi = FragmentGI (s, occlusion, i.ambientOrLightmapUV, atten, mainLight);
half4 c = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect);
c.rgb += UNITY_BRDF_GI (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, occlusion, gi);
c.rgb += Emission(i.tex.xy);
UNITY_APPLY_FOG(i.fogCoord, c.rgb);
return OutputForward (c, s.alpha);
}
half4 fragForwardBase (VertexOutputForwardBase i) : SV_Target // backward compatibility (this used to be the fragment entry function)
{
return fragForwardBaseInternal(i);
}
// ------------------------------------------------------------------
// Additive forward pass (one light per pass)
struct VertexOutputForwardAdd
{
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndLightDir[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:lightDir]
LIGHTING_COORDS(5,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
//adam-begin:
#if PLANE_REFLECTION_USER_CLIPPLANE
float clipDistance : SV_ClipDistance;
#endif
//adam-end:
};
VertexOutputForwardAdd vertForwardAdd (VertexInput v)
{
VertexOutputForwardAdd o;
UNITY_INITIALIZE_OUTPUT(VertexOutputForwardAdd, o);
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
o.pos = UnityObjectToClipPos(v.vertex);
o.tex = TexCoords(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.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 receiving
TRANSFER_VERTEX_TO_FRAGMENT(o);
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
//adam-begin:
#if PLANE_REFLECTION_USER_CLIPPLANE
o.clipDistance = dot(posWorld, _PlaneReflectionClipPlane);
#endif
//adam-end:
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
half4 fragForwardAddInternal (VertexOutputForwardAdd i)
{
FRAGMENT_SETUP_FWDADD(s)
UnityLight light = AdditiveLight (s.normalWorld, IN_LIGHTDIR_FWDADD(i), LIGHT_ATTENUATION(i));
UnityIndirect noIndirect = ZeroIndirect ();
half4 c = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, light, noIndirect);
UNITY_APPLY_FOG_COLOR(i.fogCoord, c.rgb, half4(0,0,0,0)); // fog towards black in additive pass
return OutputForward (c, s.alpha);
}
half4 fragForwardAdd (VertexOutputForwardAdd i) : SV_Target // backward compatibility (this used to be the fragment entry function)
{
return fragForwardAddInternal(i);
}
// ------------------------------------------------------------------
// Deferred pass
struct VertexOutputDeferred
{
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndParallax[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax]
half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UVs
//adam-begin:
#if 1 //UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME
//adam-end:
float3 posWorld : TEXCOORD6;
#endif
#if UNITY_OPTIMIZE_TEXCUBELOD
#if UNITY_SPECCUBE_BOX_PROJECTION
half3 reflUVW : TEXCOORD7;
#else
half3 reflUVW : TEXCOORD6;
#endif
#endif
//adam-begin:
half vertexOcclusion : TEXCOORD10;
#if PLANE_REFLECTION_USER_CLIPPLANE
float clipDistance : SV_ClipDistance;
#endif
//adam-end:
};
VertexOutputDeferred vertDeferred(VertexInput v)
{
VertexOutputDeferred o;
UNITY_INITIALIZE_OUTPUT(VertexOutputDeferred, o);
//adam-begin:
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
//adam-begin:
#if 1 //UNITY_SPECCUBE_BOX_PROJECTION || UNITY_LIGHT_PROBE_PROXY_VOLUME || defined(_SKINNED_MESH)
//adam-end:
o.posWorld = posWorld;
#endif
//adam-begin:
o.pos = mul(UNITY_MATRIX_VP, posWorld);
//adam-end:
o.tex = TexCoords(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.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndParallax[0].xyz = 0;
o.tangentToWorldAndParallax[1].xyz = 0;
o.tangentToWorldAndParallax[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 _PARALLAXMAP
TANGENT_SPACE_ROTATION;
half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
o.tangentToWorldAndParallax[0].w = viewDirForParallax.x;
o.tangentToWorldAndParallax[1].w = viewDirForParallax.y;
o.tangentToWorldAndParallax[2].w = viewDirForParallax.z;
#endif
#if UNITY_OPTIMIZE_TEXCUBELOD
o.reflUVW = reflect(o.eyeVec, normalWorld);
#endif
//adam-begin:
o.vertexOcclusion = v.color.a;
#if PLANE_REFLECTION_USER_CLIPPLANE
o.clipDistance = dot(posWorld, _PlaneReflectionClipPlane);
#endif
//adam-end:
return o;
}
void fragDeferred (
VertexOutputDeferred 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 (SHADER_TARGET < 30)
outDiffuse = 1;
outSpecSmoothness = 1;
outNormal = 0;
outEmission = 0;
return;
#endif
FRAGMENT_SETUP(s)
#if UNITY_OPTIMIZE_TEXCUBELOD
s.reflUVW = i.reflUVW;
#endif
// no analytic lights in this pass
UnityLight dummyLight = DummyLight (s.normalWorld);
half atten = 1;
// only GI
//adam-begin: pass vertex occlusion to occlusion input function
half occlusion = Occlusion(i.tex.xy, i.vertexOcclusion);
//adam-end:
#if UNITY_ENABLE_REFLECTION_BUFFERS
bool sampleReflectionsInDeferred = false;
#else
bool sampleReflectionsInDeferred = true;
#endif
UnityGI gi = FragmentGI (s, occlusion, i.ambientOrLightmapUV, atten, dummyLight, sampleReflectionsInDeferred);
half3 color = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect).rgb;
color += UNITY_BRDF_GI (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, 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.oneMinusRoughness);
outNormal = half4(s.normalWorld*0.5+0.5,1);
outEmission = half4(color, 1);
}
//
// Old FragmentGI signature. Kept only for backward compatibility and will be removed soon
//
inline UnityGI FragmentGI(
float3 posWorld,
half occlusion, half4 i_ambientOrLightmapUV, half atten, half oneMinusRoughness, half3 normalWorld, half3 eyeVec,
UnityLight light,
bool reflections)
{
// we init only fields actually used
FragmentCommonData s = (FragmentCommonData)0;
s.oneMinusRoughness = oneMinusRoughness;
s.normalWorld = normalWorld;
s.eyeVec = eyeVec;
s.posWorld = posWorld;
#if UNITY_OPTIMIZE_TEXCUBELOD
s.reflUVW = reflect(eyeVec, normalWorld);
#endif
return FragmentGI(s, occlusion, i_ambientOrLightmapUV, atten, light, reflections);
}
inline UnityGI FragmentGI (
float3 posWorld,
half occlusion, half4 i_ambientOrLightmapUV, half atten, half oneMinusRoughness, half3 normalWorld, half3 eyeVec,
UnityLight light)
{
return FragmentGI (posWorld, occlusion, i_ambientOrLightmapUV, atten, oneMinusRoughness, normalWorld, eyeVec, light, true);
}
#endif // UNITY_STANDARD_CORE_INCLUDED