天津23维预案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
16 KiB

2 years ago
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
#include "UnityStandardCore.cginc"
#ifdef UNITY_5_2_PLUS
#define FLUVIO_FRAGMENTGI(s, occlusion, i_ambientOrLightmapUV, atten, light) FragmentGI(s, occlusion, i_ambientOrLightmapUV, atten, light)
#else
#define FLUVIO_FRAGMENTGI(s, occlusion, i_ambientOrLightmapUV, atten, light) FragmentGI(s.posWorld, occlusion, i_ambientOrLightmapUV, atten, s.oneMinusRoughness, s.normalWorld, s.eyeVec, light)
#endif
#define FLUVIO_FRAGMENT_SETUP(x) FragmentCommonData x = \
FluvioFragmentSetup(i.tex, i.eyeVec, WorldNormal(i.tangentToWorldAndColor), ExtractTangentToWorldPerPixel(i.tangentToWorldAndColor), IN_WORLDPOS(i), vertex_color);
#define FLUVIO_FRAGMENT_SETUP_FWDADD(x) FragmentCommonData x = \
FluvioFragmentSetup(i.tex, i.eyeVec, WorldNormal(i.tangentToWorldAndLightDir), ExtractTangentToWorldPerPixel(i.tangentToWorldAndLightDir), half3(0,0,0), half3(0,0,0));
#ifndef FLUVIO_SETUP_BRDF_INPUT
#define FLUVIO_SETUP_BRDF_INPUT FluvioSpecularSetup
#endif
// ------------------------------------------------------------------
// Custom structs
struct FluvioVertexInput
{
float4 vertex : POSITION;
half3 normal : NORMAL;
float4 color : COLOR;
float2 uv0 : TEXCOORD0;
#ifdef _TANGENT_TO_WORLD
half4 tangent : TANGENT;
#endif
};
// ------------------------------------------------------------------
// Fluvio-specific helper functions
float _Fluvio_DepthPassCount;
float _Fluvio_DepthPassIndex;
float _Fluvio_DepthPassCellSpace;
#define FLUVIO_DEPTHPASS_BUCKET_SIZE 1.0f
int _Fluvio_OverrideNormals = 1;
float _CullFluid;
float4x4 _Fluvio_FluidToObject;
float3 FluvioGetWorldNormal(float3 norm)
{
if (_Fluvio_OverrideNormals)
norm = mul((float3x3)_Fluvio_FluidToObject, float3(0,0,-1));
return UnityObjectToWorldNormal(norm);
}
float4 FluvioGetWorldTangent(float4 dir)
{
if (_Fluvio_OverrideNormals)
dir = float4(mul((float3x3)_Fluvio_FluidToObject, float3(1,0,0)), -1);
return float4(UnityObjectToWorldDir(dir.xyz), dir.w);
}
half FluvioAlpha(float2 texcoords)
{
return tex2D(_MainTex, texcoords).a;
}
half3 FluvioEmission(float2 uv, float3 color)
{
#ifndef _EMISSION
return 0;
#else
return tex2D(_EmissionMap, uv).rgb * _EmissionColor.rgb * color;
#endif
}
half3 FluvioAlbedo(float2 texcoords, float3 color)
{
return _Color.rgb * tex2D (_MainTex, texcoords).rgb * color;
}
float2 FluvioTexCoords(FluvioVertexInput v)
{
return TRANSFORM_TEX(v.uv0, _MainTex); // Always source from uv0
}
half4 FluvioOutputForward (half3 color, half alpha)
{
return half4(color, alpha);
}
inline FragmentCommonData FluvioSpecularSetup (float2 i_tex, half3 vertex_color)
{
#ifdef _VERTEXCOLORMODE_ALBEDO
half3 albedo = FluvioAlbedo(i_tex, vertex_color);
#else
half3 albedo = FluvioAlbedo(i_tex, float3(1,1,1));
#endif
half4 specGloss = SpecularGloss(i_tex);
#ifdef _VERTEXCOLORMODE_SPECULAR
half3 specColor = specGloss.rgb * vertex_color;
#else
half3 specColor = specGloss.rgb;
#endif
half oneMinusRoughness = specGloss.a;
half oneMinusReflectivity;
half3 diffColor = EnergyConservationBetweenDiffuseAndSpecular (albedo, specColor, /*out*/ oneMinusReflectivity);
FragmentCommonData o = (FragmentCommonData)0;
o.diffColor = diffColor;
o.specColor = specColor;
o.oneMinusReflectivity = oneMinusReflectivity;
o.oneMinusRoughness = oneMinusRoughness;
return o;
}
inline FragmentCommonData FluvioMetallicSetup(float2 i_tex, half3 vertex_color)
{
#ifdef _VERTEXCOLORMODE_ALBEDO
half3 albedo = FluvioAlbedo(i_tex, vertex_color);
#else
half3 albedo = FluvioAlbedo(i_tex, float3(1, 1, 1));
#endif
half2 metallicGloss = MetallicGloss(i_tex);
half metallic = metallicGloss.x;
half oneMinusRoughness = metallicGloss.y;
half oneMinusReflectivity;
half3 specColor;
half3 diffColor = DiffuseAndSpecularFromMetallic(albedo, metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
#ifdef _VERTEXCOLORMODE_SPECULAR
specColor *= vertex_color;
#endif
FragmentCommonData o = (FragmentCommonData)0;
o.diffColor = diffColor;
o.specColor = specColor;
o.oneMinusReflectivity = oneMinusReflectivity;
o.oneMinusRoughness = oneMinusRoughness;
return o;
}
#ifdef _NORMALMAP
half3 FluvioNormalInTangentSpace(float2 texcoords)
{
return UnpackScaleNormal(tex2D (_BumpMap, texcoords), _BumpScale);
}
#endif
inline FragmentCommonData FluvioFragmentSetup (float2 i_tex, half3 i_eyeVec, half3 i_normalWorld, half3x3 i_tanToWorld, half3 i_posWorld, half3 vertex_color)
{
half alpha = FluvioAlpha(i_tex);
#ifdef _NORMALMAP
half3 normalWorld = NormalizePerPixelNormal(mul(FluvioNormalInTangentSpace(i_tex), i_tanToWorld));
#else
// Should get compiled out, isn't being used in the end.
half3 normalWorld = i_normalWorld;
#endif
half3 eyeVec = i_eyeVec;
eyeVec = NormalizePerPixelNormal(eyeVec);
FragmentCommonData o = FLUVIO_SETUP_BRDF_INPUT(i_tex, vertex_color);
o.normalWorld = normalWorld;
o.eyeVec = eyeVec;
o.posWorld = i_posWorld;
o.alpha = alpha;
return o;
}
inline float invlerp(float from, float to, float value)
{
return (value - from) / (to - from);
}
// ------------------------------------------------------------------
// Forward base
struct FluvioVertexOutputForwardBase
{
float4 pos : SV_POSITION;
float2 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndColor[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:color]
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+
#if UNITY_SPECCUBE_BOX_PROJECTION
float3 posWorld : TEXCOORD8;
#endif
};
FluvioVertexOutputForwardBase FluvioVertForwardBase (FluvioVertexInput v)
{
FluvioVertexOutputForwardBase o;
UNITY_INITIALIZE_OUTPUT(FluvioVertexOutputForwardBase, o);
if (_CullFluid < 0)
{
o.pos = 0;
}
else
{
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
#if UNITY_SPECCUBE_BOX_PROJECTION
o.posWorld = posWorld.xyz;
#endif
// FLUVIO - DEPTH CLIP
float3 objPosWorld = mul(unity_ObjectToWorld, float4(0,0,0,1));
float3 dir = normalize(objPosWorld - _WorldSpaceCameraPos) * _Fluvio_DepthPassCellSpace;
float3 nearPoint = objPosWorld + dir;
float3 farPoint = objPosWorld - dir;
float nearDepth = -mul(UNITY_MATRIX_VP, float4(nearPoint, 1)).z;
float farDepth = -mul(UNITY_MATRIX_VP, float4(farPoint,1)).z;
float depth = abs(invlerp(nearDepth, farDepth, -UnityObjectToClipPos(v.vertex).z)) * _Fluvio_DepthPassCellSpace;
if (((depth / _Fluvio_DepthPassCellSpace % _Fluvio_DepthPassCount) - _Fluvio_DepthPassIndex) > FLUVIO_DEPTHPASS_BUCKET_SIZE)
{
o.pos = 0;
}
else
{
o.pos = UnityObjectToClipPos(v.vertex);
o.tex = FluvioTexCoords(v);
o.eyeVec = NormalizePerVertexNormal(posWorld - _WorldSpaceCameraPos);
float3 normalWorld = FluvioGetWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = FluvioGetWorldTangent(v.tangent);
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangentToWorldAndColor[0].xyz = tangentToWorld[0];
o.tangentToWorldAndColor[1].xyz = tangentToWorld[1];
o.tangentToWorldAndColor[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndColor[0].xyz = 0;
o.tangentToWorldAndColor[1].xyz = 0;
o.tangentToWorldAndColor[2].xyz = normalWorld;
#endif
#ifdef _VERTEXCOLORMODE_NONE
o.tangentToWorldAndColor[0].w = 1;
o.tangentToWorldAndColor[1].w = 1;
o.tangentToWorldAndColor[2].w = 1;
#else
o.tangentToWorldAndColor[0].w = v.color.r;
o.tangentToWorldAndColor[1].w = v.color.g;
o.tangentToWorldAndColor[2].w = v.color.b;
#endif
// Sample light probe for Dynamic objects only (no static or dynamic lightmaps)
#if UNITY_SHOULD_SAMPLE_SH
#if UNITY_SAMPLE_FULL_SH_PER_PIXEL
o.ambientOrLightmapUV.rgb = 0;
#elif (SHADER_TARGET < 30)
o.ambientOrLightmapUV.rgb = ShadeSH9(half4(normalWorld, 1.0));
#else
// Optimization: L2 per-vertex, L0..L1 per-pixel
o.ambientOrLightmapUV.rgb = ShadeSH3Order(half4(normalWorld, 1.0));
#endif
// Add approximated illumination from non-important point lights
#ifdef VERTEXLIGHT_ON
o.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
#endif
//We need this for shadow receving
TRANSFER_SHADOW(o);
UNITY_TRANSFER_FOG(o,o.pos);
}
}
return o;
}
half4 FluvioFragForwardBase (FluvioVertexOutputForwardBase i) : SV_Target
{
// FLUVIO - VERTEX COLORS
half3 vertex_color = half3(i.tangentToWorldAndColor[0].w, i.tangentToWorldAndColor[1].w, i.tangentToWorldAndColor[2].w);
FLUVIO_FRAGMENT_SETUP(s)
UnityLight mainLight = MainLight (s.normalWorld);
half atten = SHADOW_ATTENUATION(i);
half occlusion = 1;
UnityGI gi = FLUVIO_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);
#ifdef _VERTEXCOLORMODE_EMISSION
c.rgb += FluvioEmission(i.tex, vertex_color);
#else
c.rgb += FluvioEmission(i.tex, float3(1,1,1));
#endif
UNITY_APPLY_FOG(i.fogCoord, c.rgb);
return FluvioOutputForward (c, s.alpha);
}
// ------------------------------------------------------------------
// Forward add
struct FluvioVertexOutputForwardAdd
{
float4 pos : SV_POSITION;
float2 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndLightDir[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:lightDir]
LIGHTING_COORDS(5,6)
UNITY_FOG_COORDS(7)
};
FluvioVertexOutputForwardAdd FluvioVertForwardAdd (FluvioVertexInput v)
{
FluvioVertexOutputForwardAdd o;
UNITY_INITIALIZE_OUTPUT(FluvioVertexOutputForwardAdd, o);
if (_CullFluid < 0)
{
o.pos = 0;
}
else
{
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
o.pos = UnityObjectToClipPos(v.vertex);
o.tex = FluvioTexCoords(v);
o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
float3 normalWorld = FluvioGetWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = FluvioGetWorldTangent(v.tangent);
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
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;
UNITY_TRANSFER_FOG(o,o.pos);
}
return o;
}
half4 FluvioFragForwardAdd (FluvioVertexOutputForwardAdd i) : SV_Target
{
FLUVIO_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 FluvioOutputForward (c, s.alpha);
}
// ------------------------------------------------------------------
// Deferred
struct FluvioVertexOutputDeferred
{
float4 pos : SV_POSITION;
float2 tex : TEXCOORD0;
half3 eyeVec : TEXCOORD1;
half4 tangentToWorldAndColor[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:color]
half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UVs
#if UNITY_SPECCUBE_BOX_PROJECTION
float3 posWorld : TEXCOORD6;
#endif
};
FluvioVertexOutputDeferred FluvioVertDeferred (FluvioVertexInput v)
{
FluvioVertexOutputDeferred o;
UNITY_INITIALIZE_OUTPUT(FluvioVertexOutputDeferred, o);
if (_CullFluid < 0)
{
o.pos = 0;
}
else
{
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
#if UNITY_SPECCUBE_BOX_PROJECTION
o.posWorld = posWorld;
#endif
o.pos = UnityObjectToClipPos(v.vertex);
// FLUVIO - DEPTH CLIP
float3 objPosWorld = mul(unity_ObjectToWorld, float4(0, 0, 0, 1));
float3 dir = normalize(objPosWorld - _WorldSpaceCameraPos) * _Fluvio_DepthPassCellSpace;
float3 nearPoint = objPosWorld + dir;
float3 farPoint = objPosWorld - dir;
float nearDepth = -mul(UNITY_MATRIX_VP, float4(nearPoint, 1)).z;
float farDepth = -mul(UNITY_MATRIX_VP, float4(farPoint, 1)).z;
float depth = abs(invlerp(nearDepth, farDepth, -UnityObjectToClipPos(v.vertex).z)) * _Fluvio_DepthPassCellSpace;
if (((depth / _Fluvio_DepthPassCellSpace % _Fluvio_DepthPassCount) - _Fluvio_DepthPassIndex) > FLUVIO_DEPTHPASS_BUCKET_SIZE)
{
o.pos = 0;
}
else
{
o.tex = FluvioTexCoords(v);
o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
float3 normalWorld = FluvioGetWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = FluvioGetWorldTangent(v.tangent);
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangentToWorldAndColor[0].xyz = tangentToWorld[0];
o.tangentToWorldAndColor[1].xyz = tangentToWorld[1];
o.tangentToWorldAndColor[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndColor[0].xyz = 0;
o.tangentToWorldAndColor[1].xyz = 0;
o.tangentToWorldAndColor[2].xyz = normalWorld;
#endif
#ifdef _VERTEXCOLORMODE_NONE
o.tangentToWorldAndColor[0].w = 1;
o.tangentToWorldAndColor[1].w = 1;
o.tangentToWorldAndColor[2].w = 1;
#else
o.tangentToWorldAndColor[0].w = v.color.r;
o.tangentToWorldAndColor[1].w = v.color.g;
o.tangentToWorldAndColor[2].w = v.color.b;
#endif
#if UNITY_SHOULD_SAMPLE_SH
#if (SHADER_TARGET < 30)
o.ambientOrLightmapUV.rgb = ShadeSH9(half4(normalWorld, 1.0));
#else
// Optimization: L2 per-vertex, L0..L1 per-pixel
o.ambientOrLightmapUV.rgb = ShadeSH3Order(half4(normalWorld, 1.0));
#endif
#endif
}
}
return o;
}
void FluvioFragDeferred (
FluvioVertexOutputDeferred i,
out half4 outDiffuse : SV_Target0, // RT0: diffuse color (rgb), --unused-- (a)
out half4 outSpecSmoothness : SV_Target1, // RT1: spec color (rgb), smoothness (a)
out half4 outNormal : SV_Target2, // RT2: normal (rgb), --unused-- (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
// FLUVIO - VERTEX COLORS
half3 vertex_color = half3(i.tangentToWorldAndColor[0].w, i.tangentToWorldAndColor[1].w, i.tangentToWorldAndColor[2].w);
FLUVIO_FRAGMENT_SETUP(s)
half alpha = FluvioAlpha(i.tex);
clip(alpha - _Cutoff);
// no analytic lights in this pass
UnityLight dummyLight = DummyLight (s.normalWorld);
half atten = 1;
// only GI
half occlusion = 1;
UnityGI gi = FLUVIO_FRAGMENTGI(s, occlusion, i.ambientOrLightmapUV, atten, dummyLight);
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 _VERTEXCOLORMODE_EMISSION
color += FluvioEmission(i.tex, vertex_color);
#else
color += FluvioEmission(i.tex, float3(1,1,1));
#endif
#ifndef UNITY_HDR_ON
color.rgb = exp2(-color.rgb);
#endif
outDiffuse = half4(s.diffColor * alpha, 1);
outSpecSmoothness = half4(s.specColor * alpha, s.oneMinusRoughness);
outNormal = half4(s.normalWorld,1);
outEmission = half4(color, 1);
}