您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
264 行
9.6 KiB
264 行
9.6 KiB
#ifndef UNIVERSAL_PIPELINE_CORE_INCLUDED
|
|
#define UNIVERSAL_PIPELINE_CORE_INCLUDED
|
|
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Version.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
|
|
|
|
#if !defined(SHADER_HINT_NICE_QUALITY)
|
|
#if defined(SHADER_API_MOBILE) || defined(SHADER_API_SWITCH)
|
|
#define SHADER_HINT_NICE_QUALITY 0
|
|
#else
|
|
#define SHADER_HINT_NICE_QUALITY 1
|
|
#endif
|
|
#endif
|
|
|
|
// Shader Quality Tiers in Universal.
|
|
// SRP doesn't use Graphics Settings Quality Tiers.
|
|
// We should expose shader quality tiers in the pipeline asset.
|
|
// Meanwhile, it's forced to be:
|
|
// High Quality: Non-mobile platforms or shader explicit defined SHADER_HINT_NICE_QUALITY
|
|
// Medium: Mobile aside from GLES2
|
|
// Low: GLES2
|
|
#if SHADER_HINT_NICE_QUALITY
|
|
#define SHADER_QUALITY_HIGH
|
|
#elif defined(SHADER_API_GLES)
|
|
#define SHADER_QUALITY_LOW
|
|
#else
|
|
#define SHADER_QUALITY_MEDIUM
|
|
#endif
|
|
|
|
#ifndef BUMP_SCALE_NOT_SUPPORTED
|
|
#define BUMP_SCALE_NOT_SUPPORTED !SHADER_HINT_NICE_QUALITY
|
|
#endif
|
|
|
|
struct VertexPositionInputs
|
|
{
|
|
float3 positionWS; // World space position
|
|
float3 positionVS; // View space position
|
|
float4 positionCS; // Homogeneous clip space position
|
|
float4 positionNDC;// Homogeneous normalized device coordinates
|
|
};
|
|
|
|
struct VertexNormalInputs
|
|
{
|
|
real3 tangentWS;
|
|
real3 bitangentWS;
|
|
float3 normalWS;
|
|
};
|
|
|
|
VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
|
|
{
|
|
VertexPositionInputs input;
|
|
input.positionWS = TransformObjectToWorld(positionOS);
|
|
input.positionVS = TransformWorldToView(input.positionWS);
|
|
input.positionCS = TransformWorldToHClip(input.positionWS);
|
|
|
|
float4 ndc = input.positionCS * 0.5f;
|
|
input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
|
|
input.positionNDC.zw = input.positionCS.zw;
|
|
|
|
return input;
|
|
}
|
|
|
|
VertexNormalInputs GetVertexNormalInputs(float3 normalOS)
|
|
{
|
|
VertexNormalInputs tbn;
|
|
tbn.tangentWS = real3(1.0, 0.0, 0.0);
|
|
tbn.bitangentWS = real3(0.0, 1.0, 0.0);
|
|
tbn.normalWS = TransformObjectToWorldNormal(normalOS);
|
|
return tbn;
|
|
}
|
|
|
|
VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS)
|
|
{
|
|
VertexNormalInputs tbn;
|
|
|
|
// mikkts space compliant. only normalize when extracting normal at frag.
|
|
real sign = tangentOS.w * GetOddNegativeScale();
|
|
tbn.normalWS = TransformObjectToWorldNormal(normalOS);
|
|
tbn.tangentWS = TransformObjectToWorldDir(tangentOS.xyz);
|
|
tbn.bitangentWS = cross(tbn.normalWS, tbn.tangentWS) * sign;
|
|
return tbn;
|
|
}
|
|
|
|
#if UNITY_REVERSED_Z
|
|
#if SHADER_API_OPENGL || SHADER_API_GLES || SHADER_API_GLES3
|
|
//GL with reversed z => z clip range is [near, -far] -> should remap in theory but dont do it in practice to save some perf (range is close enough)
|
|
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) max(-(coord), 0)
|
|
#else
|
|
//D3d with reversed Z => z clip range is [near, 0] -> remapping to [0, far]
|
|
//max is required to protect ourselves from near plane not being correct/meaningfull in case of oblique matrices.
|
|
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) max(((1.0-(coord)/_ProjectionParams.y)*_ProjectionParams.z),0)
|
|
#endif
|
|
#elif UNITY_UV_STARTS_AT_TOP
|
|
//D3d without reversed z => z clip range is [0, far] -> nothing to do
|
|
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) (coord)
|
|
#else
|
|
//Opengl => z clip range is [-near, far] -> should remap in theory but dont do it in practice to save some perf (range is close enough)
|
|
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) (coord)
|
|
#endif
|
|
|
|
float3 GetCameraPositionWS()
|
|
{
|
|
return _WorldSpaceCameraPos;
|
|
}
|
|
|
|
float4 GetScaledScreenParams()
|
|
{
|
|
return _ScaledScreenParams;
|
|
}
|
|
|
|
void AlphaDiscard(real alpha, real cutoff, real offset = 0.0h)
|
|
{
|
|
#ifdef _ALPHATEST_ON
|
|
clip(alpha - cutoff + offset);
|
|
#endif
|
|
}
|
|
|
|
// A word on normalization of normals:
|
|
// For better quality normals should be normalized before and after
|
|
// interpolation.
|
|
// 1) In vertex, skinning or blend shapes might vary significantly the lenght of normal.
|
|
// 2) In fragment, because even outputting unit-length normals interpolation can make it non-unit.
|
|
// 3) In fragment when using normal map, because mikktspace sets up non orthonormal basis.
|
|
// However we will try to balance performance vs quality here as also let users configure that as
|
|
// shader quality tiers.
|
|
// Low Quality Tier: Normalize either per-vertex or per-pixel depending if normalmap is sampled.
|
|
// Medium Quality Tier: Always normalize per-vertex. Normalize per-pixel only if using normal map
|
|
// High Quality Tier: Normalize in both vertex and pixel shaders.
|
|
real3 NormalizeNormalPerVertex(real3 normalWS)
|
|
{
|
|
#if defined(SHADER_QUALITY_LOW) && defined(_NORMALMAP)
|
|
return normalWS;
|
|
#else
|
|
return normalize(normalWS);
|
|
#endif
|
|
}
|
|
|
|
real3 NormalizeNormalPerPixel(real3 normalWS)
|
|
{
|
|
#if defined(SHADER_QUALITY_HIGH) || defined(_NORMALMAP)
|
|
return normalize(normalWS);
|
|
#else
|
|
return normalWS;
|
|
#endif
|
|
}
|
|
|
|
// TODO: A similar function should be already available in SRP lib on master. Use that instead
|
|
float4 ComputeScreenPos(float4 positionCS)
|
|
{
|
|
float4 o = positionCS * 0.5f;
|
|
o.xy = float2(o.x, o.y * _ProjectionParams.x) + o.w;
|
|
o.zw = positionCS.zw;
|
|
return o;
|
|
}
|
|
|
|
real ComputeFogFactor(float z)
|
|
{
|
|
float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z);
|
|
|
|
#if defined(FOG_LINEAR)
|
|
// factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
|
|
float fogFactor = saturate(clipZ_01 * unity_FogParams.z + unity_FogParams.w);
|
|
return real(fogFactor);
|
|
#elif defined(FOG_EXP) || defined(FOG_EXP2)
|
|
// factor = exp(-(density*z)^2)
|
|
// -density * z computed at vertex
|
|
return real(unity_FogParams.x * clipZ_01);
|
|
#else
|
|
return 0.0h;
|
|
#endif
|
|
}
|
|
|
|
half3 MixFogColor(real3 fragColor, real3 fogColor, real fogFactor)
|
|
{
|
|
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
|
|
#if defined(FOG_EXP)
|
|
// factor = exp(-density*z)
|
|
// fogFactor = density*z compute at vertex
|
|
fogFactor = saturate(exp2(-fogFactor));
|
|
#elif defined(FOG_EXP2)
|
|
// factor = exp(-(density*z)^2)
|
|
// fogFactor = density*z compute at vertex
|
|
fogFactor = saturate(exp2(-fogFactor*fogFactor));
|
|
#endif
|
|
fragColor = lerp(fogColor, fragColor, fogFactor);
|
|
#endif
|
|
|
|
return fragColor;
|
|
}
|
|
|
|
half3 MixFog(real3 fragColor, real fogFactor)
|
|
{
|
|
return MixFogColor(fragColor, unity_FogColor.rgb, fogFactor);
|
|
}
|
|
|
|
// Stereo-related bits
|
|
#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
|
|
|
|
// Only single-pass stereo instancing uses array indexing
|
|
#if defined(UNITY_STEREO_INSTANCING_ENABLED)
|
|
#define SLICE_ARRAY_INDEX unity_StereoEyeIndex
|
|
#else
|
|
#define SLICE_ARRAY_INDEX 0
|
|
#endif
|
|
|
|
#define TEXTURE2D_X TEXTURE2D_ARRAY
|
|
#define TEXTURE2D_X_PARAM TEXTURE2D_ARRAY_PARAM
|
|
#define TEXTURE2D_X_ARGS TEXTURE2D_ARRAY_ARGS
|
|
#define TEXTURE2D_X_HALF TEXTURE2D_ARRAY_HALF
|
|
#define TEXTURE2D_X_FLOAT TEXTURE2D_ARRAY_FLOAT
|
|
|
|
#define LOAD_TEXTURE2D_X(textureName, unCoord2) LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, SLICE_ARRAY_INDEX)
|
|
#define LOAD_TEXTURE2D_X_LOD(textureName, unCoord2, lod) LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, SLICE_ARRAY_INDEX, lod)
|
|
#define SAMPLE_TEXTURE2D_X(textureName, samplerName, coord2) SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, SLICE_ARRAY_INDEX)
|
|
#define SAMPLE_TEXTURE2D_X_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, SLICE_ARRAY_INDEX, lod)
|
|
#define GATHER_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, SLICE_ARRAY_INDEX)
|
|
#define GATHER_RED_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_RED_TEXTURE2D(textureName, samplerName, float3(coord2, SLICE_ARRAY_INDEX))
|
|
#define GATHER_GREEN_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_GREEN_TEXTURE2D(textureName, samplerName, float3(coord2, SLICE_ARRAY_INDEX))
|
|
#define GATHER_BLUE_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_BLUE_TEXTURE2D(textureName, samplerName, float3(coord2, SLICE_ARRAY_INDEX))
|
|
|
|
#else
|
|
|
|
#define SLICE_ARRAY_INDEX 0
|
|
|
|
#define TEXTURE2D_X TEXTURE2D
|
|
#define TEXTURE2D_X_PARAM TEXTURE2D_PARAM
|
|
#define TEXTURE2D_X_ARGS TEXTURE2D_ARGS
|
|
#define TEXTURE2D_X_HALF TEXTURE2D_HALF
|
|
#define TEXTURE2D_X_FLOAT TEXTURE2D_FLOAT
|
|
|
|
#define LOAD_TEXTURE2D_X LOAD_TEXTURE2D
|
|
#define LOAD_TEXTURE2D_X_LOD LOAD_TEXTURE2D_LOD
|
|
#define SAMPLE_TEXTURE2D_X SAMPLE_TEXTURE2D
|
|
#define SAMPLE_TEXTURE2D_X_LOD SAMPLE_TEXTURE2D_LOD
|
|
#define GATHER_TEXTURE2D_X GATHER_TEXTURE2D
|
|
#define GATHER_RED_TEXTURE2D_X GATHER_RED_TEXTURE2D
|
|
#define GATHER_GREEN_TEXTURE2D_X GATHER_GREEN_TEXTURE2D
|
|
#define GATHER_BLUE_TEXTURE2D_X GATHER_BLUE_TEXTURE2D
|
|
|
|
#endif
|
|
|
|
#if defined(UNITY_SINGLE_PASS_STEREO)
|
|
float2 TransformStereoScreenSpaceTex(float2 uv, float w)
|
|
{
|
|
// TODO: RVS support can be added here, if Universal decides to support it
|
|
float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
|
|
return uv.xy * scaleOffset.xy + scaleOffset.zw * w;
|
|
}
|
|
|
|
float2 UnityStereoTransformScreenSpaceTex(float2 uv)
|
|
{
|
|
return TransformStereoScreenSpaceTex(saturate(uv), 1.0);
|
|
}
|
|
#else
|
|
|
|
#define UnityStereoTransformScreenSpaceTex(uv) uv
|
|
|
|
#endif // defined(UNITY_SINGLE_PASS_STEREO)
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Deprecated.hlsl"
|
|
|
|
#endif
|