mirror of
https://github.com/muskit/H3VR-TNH-Quality-of-Life-Improvements.git
synced 2026-06-02 20:24:26 -07:00
649 lines
20 KiB
HLSL
649 lines
20 KiB
HLSL
|
|
// Alloy Physical Shader Framework
|
||
|
|
// Copyright 2013-2017 RUST LLC.
|
||
|
|
// http://www.alloy.rustltd.com/
|
||
|
|
|
||
|
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
/// @file Forward.cginc
|
||
|
|
/// @brief Forward passes uber-header.
|
||
|
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
#ifndef ALLOY_SHADERS_FRAMEWORK_FORWARD_CGINC
|
||
|
|
#define ALLOY_SHADERS_FRAMEWORK_FORWARD_CGINC
|
||
|
|
|
||
|
|
// Headers both for this file, and for all Definition and Feature modules.
|
||
|
|
#include "Assets/Alloy/Shaders/Framework/FeatureImpl.cginc"
|
||
|
|
#include "Assets/Alloy/Shaders/Framework/LightingImpl.cginc"
|
||
|
|
#include "Assets/Alloy/Shaders/Framework/TypeImpl.cginc"
|
||
|
|
#include "Assets/Alloy/Shaders/Framework/Unity.cginc"
|
||
|
|
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||
|
|
|
||
|
|
#include "AutoLight.cginc"
|
||
|
|
#include "HLSLSupport.cginc"
|
||
|
|
#include "UnityCG.cginc"
|
||
|
|
#include "UnityGlobalIllumination.cginc"
|
||
|
|
#include "UnityImageBasedLighting.cginc"
|
||
|
|
#include "UnityInstancing.cginc"
|
||
|
|
#include "UnityLightingCommon.cginc"
|
||
|
|
#include "UnityShaderUtilities.cginc"
|
||
|
|
#include "UnityShaderVariables.cginc"
|
||
|
|
#include "UnityShadowLibrary.cginc"
|
||
|
|
#include "UnityStandardUtils.cginc"
|
||
|
|
|
||
|
|
// Support for two-sided effects in a single pass.
|
||
|
|
#ifndef A_TWO_SIDED_SHADER
|
||
|
|
#define A_FACING_SIGN_PARAM
|
||
|
|
#define A_FACING_SIGN 1.0h
|
||
|
|
#else
|
||
|
|
#define A_FACING_SIGN_PARAM ,half facingSign : VFACE
|
||
|
|
#define A_FACING_SIGN facingSign
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Shadows.
|
||
|
|
#if defined(SHADOWS_SCREEN) && !defined(UNITY_NO_SCREENSPACE_SHADOWS)
|
||
|
|
#define A_SCREENSPACE_SHADOWS_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Lightmaps.
|
||
|
|
#if !defined(A_UV2_ON) && defined(DYNAMICLIGHTMAP_ON) && defined(A_INDIRECT_ON)
|
||
|
|
#define A_UV2_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(LIGHTMAP_ON) && defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
|
||
|
|
#define A_LIGHTMAP_SHADOW_MIXING_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Lighting vertex data.
|
||
|
|
#if defined(A_INDIRECT_ON) && defined(A_DIRECT_ON)
|
||
|
|
#define A_FORWARD_TEXCOORD0 half4 giData : TEXCOORD0;
|
||
|
|
#define A_FORWARD_TEXCOORD1 UNITY_SHADOW_COORDS(1)
|
||
|
|
#elif defined(A_INDIRECT_ON)
|
||
|
|
#define A_FORWARD_TEXCOORD0 half4 giData : TEXCOORD0;
|
||
|
|
|
||
|
|
#ifdef A_SHADOW_MASKS_BUFFER_ON
|
||
|
|
#define A_FORWARD_TEXCOORD1 UNITY_SHADOW_COORDS(1)
|
||
|
|
#endif
|
||
|
|
#elif defined(A_DIRECT_ON)
|
||
|
|
#define A_FORWARD_TEXCOORD0 UNITY_SHADOW_COORDS(0)
|
||
|
|
|
||
|
|
// Reduce v2f transfer cost for pure directional lights.
|
||
|
|
#if !defined(DIRECTIONAL) && !defined(A_LIGHTMAP_SHADOW_MIXING_ON)
|
||
|
|
#define A_FORWARD_TEXCOORD1 unityShadowCoord4 lightCoord : TEXCOORD1;
|
||
|
|
|
||
|
|
#ifndef USING_DIRECTIONAL_LIGHT
|
||
|
|
#define A_FORWARD_TEXCOORD2 float4 lightVectorRange : TEXCOORD2;
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Handle dependencies between vertex data.
|
||
|
|
#if !defined(A_TANGENT_ON) && defined(A_TANGENT_TO_WORLD_ON)
|
||
|
|
#define A_TANGENT_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(A_NORMAL_WORLD_ON) && (defined(A_TANGENT_TO_WORLD_ON) || defined(A_REFLECTION_VECTOR_WORLD_ON))
|
||
|
|
#define A_NORMAL_WORLD_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(A_VIEW_DIR_WORLD_ON) && (defined(A_VIEW_DIR_TANGENT_ON) || defined(A_REFLECTION_VECTOR_WORLD_ON))
|
||
|
|
#define A_VIEW_DIR_WORLD_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(A_POSITION_WORLD_ON) && defined(A_VIEW_DIR_WORLD_ON)
|
||
|
|
#define A_POSITION_WORLD_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(A_SCREEN_UV_ON) && defined(LOD_FADE_CROSSFADE)
|
||
|
|
#define A_SCREEN_UV_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Enable specific packed texcoord channels.
|
||
|
|
#if !defined(A_POSITION_TEXCOORD_ON) && (defined(A_POSITION_WORLD_ON) || defined(A_VIEW_DEPTH_ON))
|
||
|
|
#define A_POSITION_TEXCOORD_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(A_FOG_TEXCOORD_ON) && (defined(A_FOG_ON) || defined(A_SCREEN_UV_ON))
|
||
|
|
#define A_FOG_TEXCOORD_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(A_TRANSFER_INSTANCE_ID_ON) && defined(A_WORLD_TO_OBJECT_ON) && defined(A_INSTANCING_PASS)
|
||
|
|
#define A_TRANSFER_INSTANCE_ID_ON
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Split vertex data conditions to reduce combinations.
|
||
|
|
// UV0-1, TBN, N.
|
||
|
|
#if defined(A_TANGENT_TO_WORLD_ON)
|
||
|
|
#define A_INNER_VERTEX_DATA2(A, B, C, D) \
|
||
|
|
float4 texcoords : TEXCOORD##A; \
|
||
|
|
half3 tangentWorld : TEXCOORD##B; \
|
||
|
|
half3 bitangentWorld : TEXCOORD##C; \
|
||
|
|
half3 normalWorld : TEXCOORD##D;
|
||
|
|
#elif defined(A_NORMAL_WORLD_ON)
|
||
|
|
#define A_INNER_VERTEX_DATA2(A, B, C, D) \
|
||
|
|
float4 texcoords : TEXCOORD##A; \
|
||
|
|
half3 normalWorld : TEXCOORD##B;
|
||
|
|
#else
|
||
|
|
#define A_INNER_VERTEX_DATA2(A, B, C, D) \
|
||
|
|
float4 texcoords : TEXCOORD##A;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Vertex Color, Position, View Depth, Fog, and Screen UV.
|
||
|
|
#if defined(A_POSITION_TEXCOORD_ON) && defined(A_FOG_TEXCOORD_ON)
|
||
|
|
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||
|
|
half4 color : TEXCOORD##A; \
|
||
|
|
float4 positionWorldAndViewDepth : TEXCOORD##B; \
|
||
|
|
UNITY_FOG_COORDS_PACKED(C, half4) \
|
||
|
|
A_INNER_VERTEX_DATA2(D, E, F, G)
|
||
|
|
#elif defined(A_POSITION_TEXCOORD_ON)
|
||
|
|
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||
|
|
half4 color : TEXCOORD##A; \
|
||
|
|
float4 positionWorldAndViewDepth : TEXCOORD##B; \
|
||
|
|
A_INNER_VERTEX_DATA2(C, D, E, F)
|
||
|
|
#elif defined(A_FOG_TEXCOORD_ON)
|
||
|
|
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||
|
|
half4 color : TEXCOORD##A; \
|
||
|
|
UNITY_FOG_COORDS_PACKED(C, half4) \
|
||
|
|
A_INNER_VERTEX_DATA2(D, E, F, G)
|
||
|
|
#else
|
||
|
|
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||
|
|
half4 color : TEXCOORD##A; \
|
||
|
|
A_INNER_VERTEX_DATA2(B, C, D, E)
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Instancing.
|
||
|
|
#if defined(A_TRANSFER_INSTANCE_ID_ON) && defined(A_STEREO_INSTANCING_PASS)
|
||
|
|
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO
|
||
|
|
#elif defined(A_TRANSFER_INSTANCE_ID_ON)
|
||
|
|
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) UNITY_VERTEX_INPUT_INSTANCE_ID
|
||
|
|
#elif defined(A_STEREO_INSTANCING_PASS)
|
||
|
|
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) UNITY_VERTEX_OUTPUT_STEREO
|
||
|
|
#else
|
||
|
|
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G)
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Surface shader off.
|
||
|
|
#if defined(A_SURFACE_SHADER_OFF)
|
||
|
|
#define A_VERTEX_DATA(A, B, C, D, E, F, G)
|
||
|
|
#else
|
||
|
|
#define A_VERTEX_DATA(A, B, C, D, E, F, G) A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G)
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/// Configurable vertex input data from the application.
|
||
|
|
struct AVertexInput
|
||
|
|
{
|
||
|
|
float4 vertex : POSITION;
|
||
|
|
float4 uv0 : TEXCOORD0;
|
||
|
|
float4 uv1 : TEXCOORD1;
|
||
|
|
half3 normal : NORMAL;
|
||
|
|
#ifdef A_UV2_ON
|
||
|
|
float4 uv2 : TEXCOORD2;
|
||
|
|
#endif
|
||
|
|
#ifdef A_UV3_ON
|
||
|
|
float4 uv3 : TEXCOORD3;
|
||
|
|
#endif
|
||
|
|
#ifdef A_TANGENT_ON
|
||
|
|
half4 tangent : TANGENT;
|
||
|
|
#endif
|
||
|
|
half4 color : COLOR;
|
||
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||
|
|
};
|
||
|
|
|
||
|
|
/// Extensible fragment input data.
|
||
|
|
struct AFragmentInput {
|
||
|
|
#if defined(A_FORWARD_TEXCOORD0) && defined(A_FORWARD_TEXCOORD1) && defined(A_FORWARD_TEXCOORD2)
|
||
|
|
A_FORWARD_TEXCOORD0
|
||
|
|
A_FORWARD_TEXCOORD1
|
||
|
|
A_FORWARD_TEXCOORD2
|
||
|
|
A_VERTEX_DATA(3, 4, 5, 6, 7, 8, 9)
|
||
|
|
#elif defined(A_FORWARD_TEXCOORD0) && defined(A_FORWARD_TEXCOORD1)
|
||
|
|
A_FORWARD_TEXCOORD0
|
||
|
|
A_FORWARD_TEXCOORD1
|
||
|
|
A_VERTEX_DATA(2, 3, 4, 5, 6, 7, 8)
|
||
|
|
#elif defined(A_FORWARD_TEXCOORD0)
|
||
|
|
A_FORWARD_TEXCOORD0
|
||
|
|
A_VERTEX_DATA(1, 2, 3, 4, 5, 6, 7)
|
||
|
|
#else
|
||
|
|
A_VERTEX_DATA(0, 1, 2, 3, 4, 5, 6)
|
||
|
|
#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
// TODO: Find a way to move this dependency!
|
||
|
|
#include "Assets/Alloy/Shaders/Framework/Tessellation.cginc"
|
||
|
|
|
||
|
|
/// Transfers the per-vertex lightmapping or SH data to the fragment shader.
|
||
|
|
/// @param[in,out] i Vertex to fragment transfer data.
|
||
|
|
/// @param[in] v Vertex input data.
|
||
|
|
void aVertexGi(
|
||
|
|
inout AFragmentInput i,
|
||
|
|
AVertexInput v)
|
||
|
|
{
|
||
|
|
#ifdef A_INDIRECT_ON
|
||
|
|
#ifdef LIGHTMAP_ON
|
||
|
|
i.giData.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
|
||
|
|
i.giData.zw = 0.0h;
|
||
|
|
#elif UNITY_SHOULD_SAMPLE_SH
|
||
|
|
// Add approximated illumination from non-important point lights
|
||
|
|
half3 normalWorld = i.normalWorld.xyz;
|
||
|
|
|
||
|
|
#ifdef VERTEXLIGHT_ON
|
||
|
|
i.giData.rgb = aShade4PointLights(i.positionWorldAndViewDepth.xyz, normalWorld);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
i.giData.rgb = ShadeSHPerVertex(normalWorld, i.giData.rgb);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef DYNAMICLIGHTMAP_ON
|
||
|
|
i.giData.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Populates a UnityGI descriptor in the fragment shader.
|
||
|
|
/// @param i Vertex to fragment transfer data.
|
||
|
|
/// @param s Material surface data.
|
||
|
|
/// @param shadow Forward Base directional light shadow.
|
||
|
|
/// @return Initialized UnityGI descriptor.
|
||
|
|
UnityGI aFragmentGi(
|
||
|
|
AFragmentInput i,
|
||
|
|
ASurface s,
|
||
|
|
half shadow)
|
||
|
|
{
|
||
|
|
UnityGI gi;
|
||
|
|
UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
|
||
|
|
|
||
|
|
#ifdef A_INDIRECT_ON
|
||
|
|
UnityGIInput d;
|
||
|
|
|
||
|
|
UNITY_INITIALIZE_OUTPUT(UnityGIInput, d);
|
||
|
|
d.worldPos = s.positionWorld;
|
||
|
|
d.worldViewDir = s.viewDirWorld; // ???
|
||
|
|
d.atten = shadow;
|
||
|
|
|
||
|
|
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
|
||
|
|
d.ambient = 0;
|
||
|
|
d.lightmapUV = i.giData;
|
||
|
|
#else
|
||
|
|
d.ambient = i.giData.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
|
||
|
|
|
||
|
|
// So we can extract shadow with baked occlusion.
|
||
|
|
#ifdef HANDLE_SHADOWS_BLENDING_IN_GI
|
||
|
|
d.light.color = A_WHITE;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Pass 1.0 for occlusion so we can apply it later in indirect().
|
||
|
|
gi = UnityGI_Base(d, 1.0h, s.ambientNormalWorld);
|
||
|
|
|
||
|
|
#ifdef A_REFLECTION_PROBES_ON
|
||
|
|
Unity_GlossyEnvironmentData g;
|
||
|
|
|
||
|
|
g.reflUVW = s.reflectionVectorWorld;
|
||
|
|
g.roughness = s.roughness;
|
||
|
|
gi.indirect.specular = UnityGI_IndirectSpecular(d, 1.0h, s.normalWorld, g);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return gi;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Transforms the vertex data before transferring it to the pixel shader.
|
||
|
|
/// @param[in,out] v Vertex input data.
|
||
|
|
/// @param[out] o Vertex to fragment transfer data.
|
||
|
|
/// @param[out] opos Clip space position.
|
||
|
|
void aForwardVertexShader(
|
||
|
|
inout AVertexInput v,
|
||
|
|
out AFragmentInput o,
|
||
|
|
out float4 opos)
|
||
|
|
{
|
||
|
|
#ifdef A_SURFACE_SHADER_OFF
|
||
|
|
opos = 0.0h;
|
||
|
|
#else
|
||
|
|
UNITY_INITIALIZE_OUTPUT(AFragmentInput, o);
|
||
|
|
|
||
|
|
#ifdef A_INSTANCING_PASS
|
||
|
|
UNITY_SETUP_INSTANCE_ID(v);
|
||
|
|
|
||
|
|
#ifdef A_TRANSFER_INSTANCE_ID_ON
|
||
|
|
UNITY_TRANSFER_INSTANCE_ID(v, o);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_STEREO_INSTANCING_PASS
|
||
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Copy vertex data, and let shader type modify it.
|
||
|
|
AVertex vs = aNewVertex();
|
||
|
|
|
||
|
|
vs.positionObject = v.vertex;
|
||
|
|
vs.uv0 = v.uv0;
|
||
|
|
vs.uv1 = v.uv1;
|
||
|
|
vs.normalObject = v.normal;
|
||
|
|
|
||
|
|
#ifdef A_UV2_ON
|
||
|
|
vs.uv2 = v.uv2;
|
||
|
|
#endif
|
||
|
|
#ifdef A_UV3_ON
|
||
|
|
vs.uv3 = v.uv3;
|
||
|
|
#endif
|
||
|
|
#ifdef A_TANGENT_ON
|
||
|
|
vs.tangentObject = v.tangent;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
vs.color = v.color;
|
||
|
|
|
||
|
|
aVertexShader(vs);
|
||
|
|
|
||
|
|
// Copy data back into original, in case outer shader needs it.
|
||
|
|
v.vertex = vs.positionObject;
|
||
|
|
v.uv0 = vs.uv0;
|
||
|
|
v.uv1 = vs.uv1;
|
||
|
|
v.normal = vs.normalObject;
|
||
|
|
|
||
|
|
#ifdef A_UV2_ON
|
||
|
|
v.uv2 = vs.uv2;
|
||
|
|
#endif
|
||
|
|
#ifdef A_UV3_ON
|
||
|
|
v.uv3 = vs.uv3;
|
||
|
|
#endif
|
||
|
|
#ifdef A_TANGENT_ON
|
||
|
|
v.tangent = vs.tangentObject;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
v.color = vs.color;
|
||
|
|
|
||
|
|
// Fill V2F.
|
||
|
|
o.color = v.color; // Gamma-space vertex color, unless modified.
|
||
|
|
o.texcoords.xy = v.uv0.xy;
|
||
|
|
o.texcoords.zw = v.uv1.xy;
|
||
|
|
opos = UnityObjectToClipPos(v.vertex.xyz);
|
||
|
|
|
||
|
|
#ifdef A_POSITION_TEXCOORD_ON
|
||
|
|
#ifdef A_POSITION_WORLD_ON
|
||
|
|
o.positionWorldAndViewDepth.xyz = mul(unity_ObjectToWorld, v.vertex).xyz;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_VIEW_DEPTH_ON
|
||
|
|
COMPUTE_EYEDEPTH(o.positionWorldAndViewDepth.w);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_NORMAL_WORLD_ON
|
||
|
|
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifndef A_TANGENT_TO_WORLD_ON
|
||
|
|
#ifdef A_NORMAL_WORLD_ON
|
||
|
|
o.normalWorld = normalWorld;
|
||
|
|
#endif
|
||
|
|
#else
|
||
|
|
float3 tangentWorld = UnityObjectToWorldDir(v.tangent.xyz);
|
||
|
|
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld, v.tangent.w);
|
||
|
|
|
||
|
|
o.tangentWorld = tangentToWorld[0];
|
||
|
|
o.bitangentWorld = tangentToWorld[1];
|
||
|
|
o.normalWorld = tangentToWorld[2];
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(A_SCREEN_UV_ON) || (defined(A_DIRECT_ON) && defined(A_SCREENSPACE_SHADOWS_ON))
|
||
|
|
float4 screenPos = ComputeScreenPos(opos);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Fog and Screen UV.
|
||
|
|
#ifdef A_FOG_TEXCOORD_ON
|
||
|
|
#ifdef A_SCREEN_UV_ON
|
||
|
|
o.fogCoord.yzw = screenPos.xyw;
|
||
|
|
#else
|
||
|
|
o.fogCoord.yzw = A_AXIS_Z;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_FOG_ON
|
||
|
|
UNITY_TRANSFER_FOG(o, opos);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Lighting data.
|
||
|
|
aVertexGi(o, v);
|
||
|
|
|
||
|
|
#ifdef A_DIRECT_ON
|
||
|
|
// NOTE: Custom macro to skip calculations and remove dependency on o.pos!
|
||
|
|
#ifdef A_SCREENSPACE_SHADOWS_ON
|
||
|
|
o._ShadowCoord = screenPos;
|
||
|
|
#else
|
||
|
|
UNITY_TRANSFER_SHADOW(o, v.uv1);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(DIRECTIONAL) && !defined(A_LIGHTMAP_SHADOW_MIXING_ON)
|
||
|
|
o.lightCoord = mul(unity_WorldToLight, unityShadowCoord4(o.positionWorldAndViewDepth.xyz, 1.0f));
|
||
|
|
|
||
|
|
#ifndef USING_DIRECTIONAL_LIGHT
|
||
|
|
o.lightVectorRange = UnityWorldSpaceLightDir(o.positionWorldAndViewDepth.xyz).xyzz;
|
||
|
|
aLightRange(o.lightVectorRange, o.lightCoord);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Create a surface populated with material data.
|
||
|
|
/// @param i Vertex to fragment transfer data.
|
||
|
|
/// @param facingSign Sign of front/back facing direction.
|
||
|
|
/// @return Initialized surface data object.
|
||
|
|
ASurface aForwardSurface(
|
||
|
|
AFragmentInput i,
|
||
|
|
half facingSign)
|
||
|
|
{
|
||
|
|
ASurface s = aNewSurface();
|
||
|
|
|
||
|
|
#ifndef A_SURFACE_SHADER_OFF
|
||
|
|
#ifdef A_TRANSFER_INSTANCE_ID_ON
|
||
|
|
UNITY_SETUP_INSTANCE_ID(i);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
s.uv01 = i.texcoords;
|
||
|
|
s.vertexColor = i.color;
|
||
|
|
s.facingSign = facingSign;
|
||
|
|
|
||
|
|
#ifdef A_POSITION_TEXCOORD_ON
|
||
|
|
#ifdef A_POSITION_WORLD_ON
|
||
|
|
s.positionWorld = i.positionWorldAndViewDepth.xyz;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_VIEW_DEPTH_ON
|
||
|
|
s.viewDepth = i.positionWorldAndViewDepth.w;
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_NORMAL_WORLD_ON
|
||
|
|
#ifdef A_TWO_SIDED_SHADER
|
||
|
|
i.normalWorld.xyz *= facingSign;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Give these sane defaults in case the surface shader doesn't set them.
|
||
|
|
s.vertexNormalWorld = normalize(i.normalWorld);
|
||
|
|
s.normalWorld = s.vertexNormalWorld;
|
||
|
|
s.ambientNormalWorld = s.vertexNormalWorld;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_VIEW_DIR_WORLD_ON
|
||
|
|
// Cheaper to calculate in PS than to unpack from vertex, while also
|
||
|
|
// preventing distortion in POM and area light specular highlights.
|
||
|
|
s.viewDirWorld = normalize(UnityWorldSpaceViewDir(s.positionWorld));
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_TANGENT_TO_WORLD_ON
|
||
|
|
half3 t = i.tangentWorld;
|
||
|
|
half3 b = i.bitangentWorld;
|
||
|
|
half3 n = i.normalWorld;
|
||
|
|
|
||
|
|
#if UNITY_TANGENT_ORTHONORMALIZE
|
||
|
|
n = normalize(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
|
||
|
|
|
||
|
|
s.tangentToWorld = half3x3(t, b, n);
|
||
|
|
|
||
|
|
#if defined(A_VIEW_DIR_WORLD_ON) && defined(A_VIEW_DIR_TANGENT_ON)
|
||
|
|
s.viewDirTangent = normalize(mul(s.tangentToWorld, s.viewDirWorld));
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_FOG_TEXCOORD_ON
|
||
|
|
#ifdef A_FOG_ON
|
||
|
|
s.fogCoord = i.fogCoord;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_SCREEN_UV_ON
|
||
|
|
s.screenPosition.xyw = i.fogCoord.yzw;
|
||
|
|
s.screenPosition.z = 0.0h;
|
||
|
|
s.screenUv.xy = s.screenPosition.xy / s.screenPosition.w;
|
||
|
|
|
||
|
|
#ifdef LOD_FADE_CROSSFADE
|
||
|
|
half2 projUV = s.screenUv.xy * _ScreenParams.xy * 0.25h;
|
||
|
|
|
||
|
|
projUV.y = frac(projUV.y) * 0.0625h /* 1/16 */ + unity_LODFade.y; // quantized lod fade by 16 levels
|
||
|
|
clip(tex2D(_DitherMaskLOD2D, projUV).a - 0.5f);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Runs the shader and lighting type's surface code.
|
||
|
|
aBaseUvInit(s);
|
||
|
|
aUpdateViewData(s);
|
||
|
|
aSurfaceShader(s);
|
||
|
|
aPreLighting(s);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return s;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Final processing of the forward color before output.
|
||
|
|
/// @param s Material surface data.
|
||
|
|
/// @param color Lighting + Emission + Fog + etc.
|
||
|
|
/// @return Final HDR output color with alpha opacity.
|
||
|
|
half4 aForwardColor(
|
||
|
|
ASurface s,
|
||
|
|
half3 color)
|
||
|
|
{
|
||
|
|
half4 output;
|
||
|
|
|
||
|
|
#if defined(A_ALPHA_BLENDING_PASS) && defined(A_ALPHA_BLENDING_ON)
|
||
|
|
output.a = s.opacity;
|
||
|
|
#else
|
||
|
|
UNITY_OPAQUE_ALPHA(output.a);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
output.rgb = color;
|
||
|
|
aColorShader(output, s);
|
||
|
|
return aHdrClamp(output);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Calculates forward lighting from surface and vertex data.
|
||
|
|
/// @param i Vertex to fragment transfer data.
|
||
|
|
/// @param facingSign Sign of front/back facing direction.
|
||
|
|
/// @return Forward direct and indirect lighting.
|
||
|
|
half4 aForwardLitColorShader(
|
||
|
|
AFragmentInput i,
|
||
|
|
half facingSign)
|
||
|
|
{
|
||
|
|
half3 illum = 0.0h;
|
||
|
|
ASurface s = aForwardSurface(i, facingSign);
|
||
|
|
|
||
|
|
#ifdef A_LIGHTING_ON
|
||
|
|
half shadow = UNITY_SHADOW_ATTENUATION(i, s.positionWorld);
|
||
|
|
|
||
|
|
#ifdef A_INDIRECT_ON
|
||
|
|
UnityGI gi = aFragmentGi(i, s, shadow);
|
||
|
|
|
||
|
|
illum = aUnityIndirectLighting(gi, s);
|
||
|
|
|
||
|
|
// Extract shadow with combined baked occlusion.
|
||
|
|
#ifdef HANDLE_SHADOWS_BLENDING_IN_GI
|
||
|
|
shadow = gi.light.color.g;
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// Do lightmap shadow mixing guard here, since we need direct vertex data.
|
||
|
|
#if defined(A_DIRECT_ON) && !defined(A_LIGHTMAP_SHADOW_MIXING_ON)
|
||
|
|
// Reduce v2f transfer cost for pure directional lights.
|
||
|
|
#if defined(DIRECTIONAL)
|
||
|
|
illum += aUnityDirectLighting(s, shadow, _WorldSpaceLightPos0, A_ZERO4);
|
||
|
|
#elif defined(DIRECTIONAL_COOKIE)
|
||
|
|
illum += aUnityDirectLighting(s, shadow, _WorldSpaceLightPos0, i.lightCoord);
|
||
|
|
#else
|
||
|
|
illum += aUnityDirectLighting(s, shadow, i.lightVectorRange, i.lightCoord);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(A_BASE_PASS) && defined(A_EMISSIVE_COLOR_ON)
|
||
|
|
illum += s.emissiveColor;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return aForwardColor(s, illum);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Creates a G-Buffer from the provided surface data.
|
||
|
|
/// @param i Vertex to fragment transfer data.
|
||
|
|
/// @param facingSign Sign of front/back facing direction.
|
||
|
|
/// @return G-buffer with surface data and ambient illumination.
|
||
|
|
AGbuffer aForwardLitGbufferShader(
|
||
|
|
AFragmentInput i,
|
||
|
|
half facingSign)
|
||
|
|
{
|
||
|
|
half3 illum = 0.0h;
|
||
|
|
AGbuffer gb = aNewGbuffer();
|
||
|
|
ASurface s = aForwardSurface(i, facingSign);
|
||
|
|
|
||
|
|
#ifdef A_INDIRECT_ON
|
||
|
|
illum += aUnityIndirectLighting(aFragmentGi(i, s, 1.0h), s);
|
||
|
|
|
||
|
|
// Baked direct lighting occlusion if any.
|
||
|
|
#ifdef A_SHADOW_MASKS_BUFFER_ON
|
||
|
|
gb.shadowMasks = UnityGetRawBakedOcclusions(i.giData.xy, s.positionWorld);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef A_EMISSIVE_COLOR_ON
|
||
|
|
illum += s.emissiveColor;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(A_INDIRECT_ON) || defined(A_EMISSIVE_COLOR_ON)
|
||
|
|
illum = aHdrClamp(illum);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifndef UNITY_HDR_ON
|
||
|
|
illum = exp2(-illum);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
gb.diffuseOcclusion = half4(s.albedo, s.specularOcclusion);
|
||
|
|
gb.specularSmoothness = half4(s.f0, 1.0h - s.roughness);
|
||
|
|
gb.normalType = half4(s.normalWorld * 0.5h + 0.5h, s.materialType);
|
||
|
|
gb.emissionSubsurface = half4(illum, s.subsurface);
|
||
|
|
aGbufferShader(gb, s);
|
||
|
|
return gb;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif // ALLOY_SHADERS_FRAMEWORK_FORWARD_CGINC
|