214 lines
7.8 KiB
HLSL
214 lines
7.8 KiB
HLSL
#ifndef UNIVERSAL_DBUFFER_INCLUDED
|
|
#define UNIVERSAL_DBUFFER_INCLUDED
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceData.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DecalInput.hlsl"
|
|
|
|
|
|
#if (defined(_DBUFFER_MRT1) || defined(_DBUFFER_MRT2) || defined(_DBUFFER_MRT3)) && !defined(_SURFACE_TYPE_TRANSPARENT)
|
|
#define _DBUFFER
|
|
#endif
|
|
|
|
#define DBufferType0 half4
|
|
#define DBufferType1 half4
|
|
#define DBufferType2 half4
|
|
|
|
#if defined(_DBUFFER_MRT3)
|
|
|
|
#define OUTPUT_DBUFFER(NAME) \
|
|
out DBufferType0 MERGE_NAME(NAME, 0) : SV_Target0, \
|
|
out DBufferType1 MERGE_NAME(NAME, 1) : SV_Target1, \
|
|
out DBufferType2 MERGE_NAME(NAME, 2) : SV_Target2
|
|
|
|
#define DECLARE_DBUFFER_TEXTURE(NAME) \
|
|
TEXTURE2D_X_HALF(MERGE_NAME(NAME, 0)); \
|
|
TEXTURE2D_X_HALF(MERGE_NAME(NAME, 1)); \
|
|
TEXTURE2D_X_HALF(MERGE_NAME(NAME, 2));
|
|
|
|
#define FETCH_DBUFFER(NAME, TEX, unCoord2) \
|
|
DBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D_X(MERGE_NAME(TEX, 0), unCoord2); \
|
|
DBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D_X(MERGE_NAME(TEX, 1), unCoord2); \
|
|
DBufferType2 MERGE_NAME(NAME, 2) = LOAD_TEXTURE2D_X(MERGE_NAME(TEX, 2), unCoord2);
|
|
|
|
#define ENCODE_INTO_DBUFFER(DECAL_SURFACE_DATA, NAME) EncodeIntoDBuffer(DECAL_SURFACE_DATA, MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), MERGE_NAME(NAME,2))
|
|
#define DECODE_FROM_DBUFFER(NAME, DECAL_SURFACE_DATA) DecodeFromDBuffer(MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), MERGE_NAME(NAME,2), DECAL_SURFACE_DATA)
|
|
|
|
#elif defined(_DBUFFER_MRT2)
|
|
|
|
#define OUTPUT_DBUFFER(NAME) \
|
|
out DBufferType0 MERGE_NAME(NAME, 0) : SV_Target0, \
|
|
out DBufferType1 MERGE_NAME(NAME, 1) : SV_Target1
|
|
|
|
#define DECLARE_DBUFFER_TEXTURE(NAME) \
|
|
TEXTURE2D_X_HALF(MERGE_NAME(NAME, 0)); \
|
|
TEXTURE2D_X_HALF(MERGE_NAME(NAME, 1));
|
|
|
|
#define FETCH_DBUFFER(NAME, TEX, unCoord2) \
|
|
DBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D_X(MERGE_NAME(TEX, 0), unCoord2); \
|
|
DBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D_X(MERGE_NAME(TEX, 1), unCoord2);
|
|
|
|
#define ENCODE_INTO_DBUFFER(DECAL_SURFACE_DATA, NAME) EncodeIntoDBuffer(DECAL_SURFACE_DATA, MERGE_NAME(NAME,0), MERGE_NAME(NAME,1))
|
|
#define DECODE_FROM_DBUFFER(NAME, DECAL_SURFACE_DATA) DecodeFromDBuffer(MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), DECAL_SURFACE_DATA)
|
|
|
|
|
|
#else
|
|
|
|
#define OUTPUT_DBUFFER(NAME) \
|
|
out DBufferType0 MERGE_NAME(NAME, 0) : SV_Target0
|
|
|
|
#define DECLARE_DBUFFER_TEXTURE(NAME) \
|
|
TEXTURE2D_X_HALF(MERGE_NAME(NAME, 0));
|
|
|
|
#define FETCH_DBUFFER(NAME, TEX, unCoord2) \
|
|
DBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D_X(MERGE_NAME(TEX, 0), unCoord2);
|
|
|
|
#define ENCODE_INTO_DBUFFER(DECAL_SURFACE_DATA, NAME) EncodeIntoDBuffer(DECAL_SURFACE_DATA, MERGE_NAME(NAME,0))
|
|
#define DECODE_FROM_DBUFFER(NAME, DECAL_SURFACE_DATA) DecodeFromDBuffer(MERGE_NAME(NAME,0), DECAL_SURFACE_DATA)
|
|
|
|
#endif
|
|
|
|
void EncodeIntoDBuffer(DecalSurfaceData surfaceData
|
|
, out DBufferType0 outDBuffer0
|
|
#if defined(_DBUFFER_MRT2) || defined(_DBUFFER_MRT3)
|
|
, out DBufferType1 outDBuffer1
|
|
#endif
|
|
#if defined(_DBUFFER_MRT3)
|
|
, out DBufferType2 outDBuffer2
|
|
#endif
|
|
)
|
|
{
|
|
outDBuffer0 = surfaceData.baseColor;
|
|
#if defined(_DBUFFER_MRT2) || defined(_DBUFFER_MRT3)
|
|
outDBuffer1 = half4(surfaceData.normalWS.xyz * 0.5 + 0.5, surfaceData.normalWS.w);
|
|
#endif
|
|
#if defined(_DBUFFER_MRT3)
|
|
outDBuffer2 = half4(surfaceData.metallic, surfaceData.occlusion, surfaceData.smoothness, surfaceData.MAOSAlpha);
|
|
#endif
|
|
}
|
|
|
|
void DecodeFromDBuffer(
|
|
DBufferType0 inDBuffer0
|
|
#if defined(_DBUFFER_MRT2) || defined(_DBUFFER_MRT3)
|
|
, DBufferType1 inDBuffer1
|
|
#endif
|
|
#if defined(_DBUFFER_MRT3) || defined(DECALS_4RT)
|
|
, DBufferType2 inDBuffer2
|
|
#endif
|
|
, out DecalSurfaceData surfaceData
|
|
)
|
|
{
|
|
ZERO_INITIALIZE(DecalSurfaceData, surfaceData);
|
|
surfaceData.baseColor = inDBuffer0;
|
|
#if defined(_DBUFFER_MRT2) || defined(_DBUFFER_MRT3)
|
|
// Use (254.0 / 255.0) instead of 0.5 to allow to encode 0 perfectly (encode as 127)
|
|
// Range goes from -0.99607 to 1.0039
|
|
surfaceData.normalWS.xyz = inDBuffer1.xyz * 2.0 - (254.0 / 255.0);
|
|
surfaceData.normalWS.w = inDBuffer1.w;
|
|
#endif
|
|
#if defined(_DBUFFER_MRT3)
|
|
surfaceData.metallic = inDBuffer2.x;
|
|
surfaceData.occlusion = inDBuffer2.y;
|
|
surfaceData.smoothness = inDBuffer2.z;
|
|
surfaceData.MAOSAlpha = inDBuffer2.w;
|
|
#endif
|
|
}
|
|
|
|
DECLARE_DBUFFER_TEXTURE(_DBufferTexture);
|
|
|
|
void ApplyDecal(float4 positionCS,
|
|
inout half3 baseColor,
|
|
inout half3 specularColor,
|
|
inout half3 normalWS,
|
|
inout half metallic,
|
|
inout half occlusion,
|
|
inout half smoothness)
|
|
{
|
|
FETCH_DBUFFER(DBuffer, _DBufferTexture, int2(positionCS.xy));
|
|
|
|
DecalSurfaceData decalSurfaceData;
|
|
DECODE_FROM_DBUFFER(DBuffer, decalSurfaceData);
|
|
|
|
// using alpha compositing https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html, mean weight of 1 is neutral
|
|
|
|
// Note: We only test weight (i.e decalSurfaceData.xxx.w is < 1.0) if it can save something
|
|
baseColor.xyz = baseColor.xyz * decalSurfaceData.baseColor.w + decalSurfaceData.baseColor.xyz;
|
|
|
|
#if defined(_DBUFFER_MRT2) || defined(_DBUFFER_MRT3)
|
|
// Always test the normal as we can have decompression artifact
|
|
if (decalSurfaceData.normalWS.w < 1.0)
|
|
{
|
|
normalWS.xyz = normalize(normalWS.xyz * decalSurfaceData.normalWS.w + decalSurfaceData.normalWS.xyz);
|
|
}
|
|
#endif
|
|
|
|
#if defined(_DBUFFER_MRT3)
|
|
#ifdef _SPECULAR_SETUP
|
|
if (decalSurfaceData.MAOSAlpha.x < 1.0)
|
|
{
|
|
half3 decalSpecularColor = ComputeFresnel0((decalSurfaceData.baseColor.w < 1.0) ? decalSurfaceData.baseColor.xyz : half3(1.0, 1.0, 1.0), decalSurfaceData.metallic, DEFAULT_SPECULAR_VALUE);
|
|
specularColor = specularColor * decalSurfaceData.MAOSAlpha + decalSpecularColor * (1.0f - decalSurfaceData.MAOSAlpha);
|
|
}
|
|
#else
|
|
metallic = metallic * decalSurfaceData.MAOSAlpha + decalSurfaceData.metallic;
|
|
#endif
|
|
|
|
occlusion = occlusion * decalSurfaceData.MAOSAlpha + decalSurfaceData.occlusion;
|
|
|
|
smoothness = smoothness * decalSurfaceData.MAOSAlpha + decalSurfaceData.smoothness;
|
|
#endif
|
|
}
|
|
|
|
void ApplyDecalToBaseColor(float4 positionCS, inout half3 baseColor)
|
|
{
|
|
FETCH_DBUFFER(DBuffer, _DBufferTexture, int2(positionCS.xy));
|
|
|
|
DecalSurfaceData decalSurfaceData;
|
|
DECODE_FROM_DBUFFER(DBuffer, decalSurfaceData);
|
|
|
|
// using alpha compositing https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html, mean weight of 1 is neutral
|
|
|
|
// Note: We only test weight (i.e decalSurfaceData.xxx.w is < 1.0) if it can save something
|
|
baseColor.xyz = baseColor.xyz * decalSurfaceData.baseColor.w + decalSurfaceData.baseColor.xyz;
|
|
}
|
|
|
|
void ApplyDecalToBaseColorAndNormal(float4 positionCS, inout half3 baseColor, inout half3 normalWS)
|
|
{
|
|
half3 specular = 0;
|
|
half metallic = 0;
|
|
half occlusion = 0;
|
|
half smoothness = 0;
|
|
ApplyDecal(positionCS,
|
|
baseColor,
|
|
specular,
|
|
normalWS,
|
|
metallic,
|
|
occlusion,
|
|
smoothness);
|
|
}
|
|
|
|
void ApplyDecalToSurfaceData(float4 positionCS, inout SurfaceData surfaceData, inout InputData inputData)
|
|
{
|
|
#ifdef _SPECULAR_SETUP
|
|
half metallic = 0;
|
|
ApplyDecal(positionCS,
|
|
surfaceData.albedo,
|
|
surfaceData.specular,
|
|
inputData.normalWS,
|
|
metallic,
|
|
surfaceData.occlusion,
|
|
surfaceData.smoothness);
|
|
#else
|
|
half3 specular = 0;
|
|
ApplyDecal(positionCS,
|
|
surfaceData.albedo,
|
|
specular,
|
|
inputData.normalWS,
|
|
surfaceData.metallic,
|
|
surfaceData.occlusion,
|
|
surfaceData.smoothness);
|
|
#endif
|
|
}
|
|
#endif // UNIVERSAL_DBUFFER_INCLUDED
|