Files

413 lines
14 KiB
HLSL

#ifndef SGAME_UNITY_STANDARD_INPUT_INCLUDED
#define SGAME_UNITY_STANDARD_INPUT_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
//--------------------------------------------------------------------------------
#if defined(UNITY_PASS_FORWARDBASE)
#define SGAME_ENV_MAP_STRENGTH 1
#define SGAME_TONEMAPPING_ACES 1
#define SGAME_LINEAR_DIFFUSE_COLOR 1
#define SGAME_TONEMAPPING_LIGHT_BOOST 1
#define SGAME_STYLIZED_ATTEN 1
#define SGAME_VLIGHT_DIFFUSE 1
#define SGAME_VLIGHT_SPECULAR 1
#define SGAME_TONEMAPPING_GI_DIFFUSE_ATTEN 1
#endif
#if defined(UNITY_PASS_FORWARDADD)
#define SGAME_LINEAR_DIFFUSE_COLOR 1
#endif
#define SGAME_VLIGHT 1
#define SGAME_VLIGHT_DIFFUSE 1
#if !defined(SGAME_QUALITY_PERFECT) && !defined(SGAME_QUALITY_HIGH)
#define _NORMALMAP_ON 0
#define _EMISSION_ON 0
#endif
#if defined(_SKIN_CALCULATION)
#define SGAME_ENV_MAP 0
#endif
// Directional lightmaps & Parallax require tangent space too
#if (_NORMALMAP_ON || DIRLIGHTMAP_COMBINED || _PARALLAXMAP)
#define _TANGENT_TO_WORLD 1
#endif
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
TEXTURE2D(_NrmMap); SAMPLER(sampler_NrmMap);
TEXTURE2D(_MetallicGlossMap); SAMPLER(sampler_MetallicGlossMap);
TEXTURE2D(_SkinMask); SAMPLER(sampler_SkinMask);
#if defined(_SKIN_CALCULATION)
TEXTURE2D(_BeckmannTex); SAMPLER(sampler_BeckmannTex);
#endif
#if defined(_BLINNING_PHONG)
TEXTURECUBE(_IBLCubeMap); SAMPLER(sampler_IBLCubeMap);
#endif
#if defined(_ANISOGGX_ON)
TEXTURE2D(_AnisotrophicMask); SAMPLER(sampler_AnisotrophicMask);
#endif
CBUFFER_START(UnityPerMaterial)
half4 _Color; half _Cutoff;
half _SpecularBloomAdd;
float4 _MainTex_ST; half4 _NrmMap_ST; half _BumpScale;
half _MetallicMapScale; half _GlossMapScale; half _OcclusionScale;
#if defined(_SKIN_CALCULATION)
half _SkinSpecIntensity; half _SkinRoughness; half4 _SkinColor;
#endif
#if defined(_BLINNING_PHONG)
half _CubeMapIntensity; half _CubeMapRot;
#endif
#if defined(_ANISOGGX_ON)
half _AnisotrophicScale; half _AnisotrophicMetallic; half _AnisotrophicSmooth;
#endif
half _EmissiveMapScale; half4 _EmissiveColor;
half _IBLInensity; half _DiffuseWrap;
half _ColorLerpMask; half4 _LerpMaskColor;
half _HighLightLerp; half4 _HighLightLerpColor;
half _BlinnphongIntensity;
CBUFFER_END
// Input functions//------------------------------------------------------------------
struct VertexInput
{
float4 vertex : POSITION;
half3 normal : NORMAL;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
#if defined(DYNAMICLIGHTMAP_ON) || defined(UNITY_PASS_META)
float2 uv2 : TEXCOORD2;
#endif
half4 tangent : TANGENT;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct FragmentCommonData
{
// Note: smoothness & 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.
half4 albedo;
half3 diffColor, specColor, emissive;
half4 mainColor;
half oneMinusReflectivity, smoothness;
half3 normalWorld, eyeVec;
half alpha;
float3 posWorld;
half skinDepth;
half metallic;
half isSkin;
half anisotrophic;
half occlusion;
};
struct UnityLight
{
half3 color;
half3 dir;
half ndotl; // Deprecated: Ndotl is now calculated on the fly and is no longer stored. Do not used it.
};
struct UnityIndirect
{
half3 diffuse;
half3 specular;
};
struct UnityGI
{
UnityLight light;
UnityIndirect indirect;
};
struct UnityGIInput
{
UnityLight light; // pixel light, sent from the engine
float3 worldPos;
half3 worldViewDir;
half atten;
half3 ambient;
float4 lightmapUV; // .xy = static lightmap UV, .zw = dynamic lightmap UV
#if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) || defined(UNITY_ENABLE_REFLECTION_BUFFERS)
float4 boxMin[2];
#endif
#ifdef UNITY_SPECCUBE_BOX_PROJECTION
float4 boxMax[2];
float4 probePosition[2];
#endif
// HDR cubemap properties, use to decompress HDR texture
float4 probeHDR[2];
};
struct Unity_GlossyEnvironmentData
{
half roughness; // CAUTION: This is perceptualRoughness but because of compatibility this name can't be change :(
half3 reflUVW;
};
half3 WorldNormal(half4 tan2world[3])
{
return normalize(tan2world[2].xyz);
}
// 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
}
inline half3 RgbToHsv_SGame(half3 c)
{
half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
half4 p = lerp(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g));
half4 q = lerp(half4(p.xyw, c.r), half4(c.r, p.yzx), step(p.x, c.r));
half d = q.x - min(q.w, q.y);
half e = 1.0e-4;
return half3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
inline half3 HsvToRgb_SGame(half3 c)
{
half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
half3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y);
}
//-------------------------------------------------------------------------------------
UnityLight MainLight ()
{
UnityLight l;
l.color = GetMainLight().color.rgb;
l.dir = GetMainLight().direction;
return l;
}
UnityLight AdditiveLight (half3 lightDir, half atten)
{
UnityLight l;
l.color = GetMainLight().color.rgb;
l.dir = lightDir;
#ifndef USING_DIRECTIONAL_LIGHT
l.dir = NormalizePerPixelNormal(l.dir);
#endif
// shadow the light
l.color *= atten;
return l;
}
UnityLight DummyLight ()
{
UnityLight l;
l.color = 0;
l.dir = half3 (0,1,0);
return l;
}
UnityIndirect ZeroIndirect ()
{
UnityIndirect ind;
ind.diffuse = 0;
ind.specular = 0;
return ind;
}
Unity_GlossyEnvironmentData UnityGlossyEnvironmentSetup(half Smoothness, half3 worldViewDir, half3 Normal, half3 fresnel0)
{
Unity_GlossyEnvironmentData g;
g.roughness /* perceptualRoughness */ = PerceptualSmoothnessToPerceptualRoughness(Smoothness);
g.reflUVW = reflect(-worldViewDir, Normal);
return g;
}
inline void ResetUnityLight(out UnityLight outLight)
{
outLight.color = half3(0, 0, 0);
outLight.dir = half3(0, 1, 0); // Irrelevant direction, just not null
outLight.ndotl = 0; // Not used
}
inline void ResetUnityGI(out UnityGI outGI)
{
ResetUnityLight(outGI.light);
outGI.indirect.diffuse = 0;
outGI.indirect.specular = 0;
}
inline half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
{
half3 specular;
specular = unity_IndirectSpecColor.rgb;
return specular * occlusion;
}
inline half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
{
return UnityGI_IndirectSpecular(data, occlusion, glossIn);
}
inline UnityGI UnityGI_Base(UnityGIInput data, half occlusion, half3 normalWorld)
{
UnityGI o_gi;
ResetUnityGI(o_gi);
o_gi.light = data.light;
o_gi.light.color *= data.atten;
o_gi.indirect.diffuse *= occlusion;
return o_gi;
}
inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld)
{
return UnityGI_Base(data, occlusion, normalWorld);
}
inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
{
UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
o_gi.indirect.specular = UnityGI_IndirectSpecular(data, occlusion, glossIn);
return o_gi;
}
inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld, bool reflections)
{
Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(smoothness, data.worldViewDir, normalWorld, float3(0, 0, 0));
return UnityGlobalIllumination(data, occlusion, normalWorld, g);
}
inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld)
{
bool sampleReflections = true;
return UnityGlobalIllumination (data, occlusion, smoothness, normalWorld, sampleReflections);
}
half3x3 CreateTangentToWorldPerVertex(half3 normal, half3 tangent, half tangentSign)
{
// For odd-negative scale transforms we need to flip the sign
half sign = tangentSign * unity_WorldTransformParams.w;
half3 binormal = cross(normal, tangent) * sign;
return half3x3(tangent, binormal, normal);
}
//-------------------------------------------------------------------------------------
float4 TexCoords(VertexInput v)
{
float4 texcoord;
texcoord.xy = TRANSFORM_TEX(v.uv0, _MainTex); // Always source from uv0
#ifdef _INVERT_UV
texcoord.y = 1 - texcoord.y;
#endif
return texcoord;
}
inline half3 SGameSkinAlbedo(half isSkin, half3 albedo, half3 diffColor )
{
half3 skinDiffColor = lerp(diffColor, albedo, isSkin);
return skinDiffColor;
}
inline half IsSkin(half skinParam)
{
return step(0.5, skinParam);
}
//-------------------------------------------------------------------------------------
// Common fragment setup
#ifdef _PARALLAXMAP
#define IN_VIEWDIR4PARALLAX(i) NormalizePerPixelNormal(half3(i.tangentToWorldAndPackedData[0].w,i.tangentToWorldAndPackedData[1].w,i.tangentToWorldAndPackedData[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
#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);
t = normalize (t - n * dot(t, n));
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
#ifdef _NORMALMAP_ON
half3 NormalInTangentSpace(float4 texcoords)
{
half3 normalTangent = SAMPLE_TEXTURE2D(_NrmMap, sampler_NrmMap, texcoords.xy).rgb * 2 - 1;
normalTangent.xy *= _BumpScale;
return normalTangent;
}
#endif
half3 PerPixelWorldNormal(float4 i_tex, half4 tangentToWorld[3])
{
#ifdef _NORMALMAP_ON
half3 tangent = tangentToWorld[0].xyz;
half3 binormal = tangentToWorld[1].xyz;
half3 normal = tangentToWorld[2].xyz;
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;
}
half4 Albedo(float4 texcoords)
{
half4 main_color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, texcoords.xy).rgba;
#if defined(_SKIN_CALCULATION)
half3 colorAddLerp = lerp(1, _LerpMaskColor.rgb * 0.8, main_color.a);
#else
half3 colorAddLerp = lerp(_Color.rgb, _LerpMaskColor.rgb * 0.8, main_color.a);
#endif
half3 albedo = main_color.rgb * colorAddLerp;
return half4(albedo, main_color.a);
}
half Alpha(float2 uv)
{
return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv).a * _Color.a;
}
half4 MetallicGloss(float2 uv)
{
half4 mg_skin;
mg_skin = SAMPLE_TEXTURE2D(_MetallicGlossMap, sampler_MetallicGlossMap, uv).ragb;
mg_skin.r *= _MetallicMapScale + 0.03;
mg_skin.g *= _GlossMapScale;
#if defined(_ANISOGGX_ON)
mg_skin.b *= _AnisotrophicScale;
#endif
mg_skin.a = pow(mg_skin.a, _OcclusionScale);
mg_skin = saturate(mg_skin);
return mg_skin;
}
float4 Parallax (float4 texcoords, half3 viewDir)
{
return texcoords;
}
float4 GetMask2(float2 texcoord)
{
return SAMPLE_TEXTURE2D(_SkinMask, sampler_SkinMask, texcoord);
}
#if defined(_SKIN_CALCULATION)
float4 BeckmannTexCol (float2 texcoord)
{
return SAMPLE_TEXTURE2D(_BeckmannTex, sampler_BeckmannTex, texcoord);
}
#endif
inline half3 RotationY(half3 pointP, half angle)
{
half radY = radians(angle);
half sinY = sin(radY);
half cosY = cos(radY);
return half3(pointP.x * cosY - pointP.z * sinY,
pointP.y,
pointP.x * sinY + pointP.z * cosY);
}
#endif