浏览代码

HDRenderPipeline: Add tetrahedron encoding for normal in GBuffer

/Branch_batcher
Sebastien Lagarde 8 年前
当前提交
af575b78
共有 1 个文件被更改,包括 86 次插入3 次删除
  1. 89
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

89
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


// conversion function for deferred
//-----------------------------------------------------------------------------
#define USE_NORMAL_TETRAHEDRON_ENCODING
#ifdef USE_NORMAL_TETRAHEDRON_ENCODING
// To generate the basisNormal below we use these 4 vertex of a regular tetrahedron
// v0 = float3(1.0, 0.0, -1.0 / sqrt(2.0));
// v1 = float3(-1.0, 0.0, -1.0 / sqrt(2.0));
// v2 = float3(0.0, 1.0, 1.0 / sqrt(2.0));
// v3 = float3(0.0, -1.0, 1.0 / sqrt(2.0));
// Then we normalize the average of each face's vertices
// normalize(v0 + v1 + v2), etc...
static const float3 basisNormal[4] =
{
float3(0.816497, 0., -0.57735),
float3(-0.816497, 0., -0.57735),
float3(0., 0.816497, 0.57735),
float3(0., -0.816497, 0.57735)
};
// Then to get the local matrix (with z axis rotate to basisNormal) use GetLocalFrame(basisNormal[xxx])
static const float3x3 basisArray[4] =
{
float3x3(0., 1., 0., 0.57735, 0., 0.816497, 0.816497, 0., -0.57735),
float3x3(0., -1., 0., -0.57735, 0., 0.816497, -0.816497, 0., -0.57735),
float3x3(-1., 0., 0., 0., -0.57735, 0.816497, 0., 0.816497, 0.57735),
float3x3(1., 0., 0., 0., 0.57735, 0.816497, 0., -0.816497, 0.57735)
};
// Return [-1..1] vector2 oriented in plane of the faceIndex of a regular tetrahedron
float2 PackNormalTetraEncode(float3 n, out uint faceIndex)
{
// Retrieve the tetrahedra's face for the normal direction
// It is the one with the greatest dot value with face normal
float dot0 = dot(n, basisNormal[0]);
float dot1 = dot(n, basisNormal[1]);
float dot2 = dot(n, basisNormal[2]);
float dot3 = dot(n, basisNormal[3]);
float maxi0 = max(dot0, dot1);
float maxi1 = max(dot2, dot3);
float maxi = max(maxi0, maxi1);
// Get the index from the greatest dot
if (maxi == dot0)
faceIndex = 0;
else if (maxi == dot1)
faceIndex = 1;
else if (maxi == dot2)
faceIndex = 2;
else //(maxi == dot3)
faceIndex = 3;
// Rotate n into this local basis
n = mul(basisArray[faceIndex], n);
// Project n onto the local plane
return n.xy;
}
// Assume f [-1..1]
float3 UnpackNormalTetraEncode(float2 f, uint faceIndex)
{
// Recover n from local plane
float3 n = float3(f.xy, sqrt(1.0 - dot(f.xy, f.xy)));
// Inverse of transform PackNormalTetraEncode (just swap order in mul as we have a rotation)
return mul(n, basisArray[faceIndex]);
}
#endif
// Encode SurfaceData (BSDF parameters) into GBuffer
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild
void EncodeIntoGBuffer( SurfaceData surfaceData,

outGBuffer0 = float4(surfaceData.baseColor, surfaceData.specularOcclusion);
// RT1 - 10:10:10:2
// We store perceptualRoughness instead of roughness because it save a sqrt ALU when decoding
// (as we want both perceptualRoughness and roughness for the lighting due to Disney Diffuse model)
#ifdef USE_NORMAL_TETRAHEDRON_ENCODING
// Encode normal on 20bit + 2bit (faceIndex) with tetrahedal compression
uint faceIndex;
float2 tetraNormalWS = PackNormalTetraEncode(surfaceData.normalWS, faceIndex);
// Store faceIndex on two bits with perceptualRoughness
outGBuffer1 = float4(tetraNormalWS * 0.5 + 0.5, PackFloatInt10bit(PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness), faceIndex, 4.0), PackMaterialId(surfaceData.materialId));
#else
// We store perceptualRoughness instead of roughness because it save a sqrt ALU when decoding
// (as we want both perceptualRoughness and roughness for the lighting due to Disney Diffuse model)
// TODO: Store 2 bit of flag into perceptualSmoothness (one for SSR, other is free (deferred planar reflection ID ? / MatID extension ?)
#endif
// RT2 - 8:8:8:8
if (surfaceData.materialId == MATERIALID_LIT_STANDARD)

float3 baseColor = inGBuffer0.rgb;
bsdfData.specularOcclusion = inGBuffer0.a;
#ifdef USE_NORMAL_TETRAHEDRON_ENCODING
uint faceIndex;
UnpackFloatInt10bit(inGBuffer1.b, 4.0, bsdfData.perceptualRoughness, faceIndex);
bsdfData.normalWS = UnpackNormalTetraEncode(inGBuffer1.xy * 2.0 - 1.0, faceIndex);
#else
#endif
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
int supportsStandard = (featureFlags & (FEATURE_FLAG_MATERIAL_LIT_STANDARD | FEATURE_FLAG_MATERIAL_LIT_ANISO)) != 0;

正在加载...
取消
保存