浏览代码

calculate decal texture lod outside of the loop

/main
Paul Melamed 7 年前
当前提交
c2c2c9b4
共有 3 个文件被更改,包括 53 次插入29 次删除
  1. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl
  2. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl
  3. 77
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl


SAMPLER(sampler_DecalAtlas);
TEXTURE2D(_DecalAtlas2D);
SAMPLER(sampler_DecalAtlas2D);
SAMPLER(_trilinear_clamp_sampler_DecalAtlas2D);
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild
void EncodeIntoDBuffer( DecalSurfaceData surfaceData,

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl


surfaceData.mask = float4(0,0,0,0);
surfaceData.HTileMask = 0;
float totalBlend = clamp(normalToWorld[0][3], 0.0f, 1.0f);
// float2 diffuseScale = float2(normalToWorld[3][0], normalToWorld[3][1]);
// float2 diffuseOffset = float2(normalToWorld[3][2], normalToWorld[3][3]);
//surfaceData.baseColor = SAMPLE_TEXTURE2D(_DecalAtlas2D, sampler_DecalAtlas2D, texCoordDS.xy * diffuseScale + diffuseOffset);
surfaceData.baseColor.w *= totalBlend;
totalBlend = surfaceData.baseColor.w; // base alpha affects all other channels;
surfaceData.HTileMask |= DBUFFERHTILEBIT_DIFFUSE;

77
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl


void ApplyBlendNormal(inout float4 dst, inout int matMask, float2 texCoords, int mapMask, float3x3 decalToWorld, float blend, float lod)
{
float4 src;
src.xyz = mul(decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, sampler_DecalAtlas2D, texCoords, lod))) * 0.5f + 0.5f;
src.xyz = mul(decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod))) * 0.5f + 0.5f;
src.w = blend;
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);
dst.w = dst.w * (1.0f - src.w);

void ApplyBlendDiffuse(inout float4 dst, inout int matMask, float2 texCoords, int mapMask, inout float blend, float lod)
{
float4 src = SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, sampler_DecalAtlas2D, texCoords, lod);
float4 src = SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod);
src.w *= blend;
blend = src.w; // diffuse texture alpha affects all other channels
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);

void ApplyBlendMask(inout float4 dst, inout int matMask, float2 texCoords, int mapMask, float blend, float lod)
{
float4 src = SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, sampler_DecalAtlas2D, texCoords, lod);
float4 src = SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod);
src.z = src.w;
src.w = blend;
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);

float ComputeTextureLOD(float2 uv, float2 uvdx, float2 uvdy, float2 scale)
{
float2 ddx_ = scale * (uvdx - uv);
float2 ddy_ = scale * (uvdy - uv);
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
return max(0.5 * log2(d), 0.0);
}
void AddDecalContribution(PositionInputs posInput, inout SurfaceData surfaceData, inout float alpha)
{
if(_EnableDBuffer)

decalCount = _DecalCount;
decalStart = 0;
#endif
UNITY_LOOP
// get world space position for adjacent pixels to be used later in mipmap lod calculation
float3 positionWSDX = positionWS + ddx(positionWS);
float3 positionWSDY = positionWS + ddy(positionWS);
// need to compute the mipmap LOD manually because we are sampling inside a loop
float3 positionDSDX = mul(decalData.worldToDecal, float4(positionWSDX, 1.0)).xyz;
float3 positionDSDY = mul(decalData.worldToDecal, float4(positionWSDY, 1.0)).xyz;
float decalBlend = decalData.normalToWorld[0][3];
positionDSDX = positionDSDX * float3(1.0, -1.0, 1.0) + float3(0.5, 0.0f, 0.5);
positionDSDY = positionDSDY * float3(1.0, -1.0, 1.0) + float3(0.5, 0.0f, 0.5);
float2 sampleDiffuseDX = positionDSDX.xz * decalData.diffuseScaleBias.xy + decalData.diffuseScaleBias.zw;
float2 sampleDiffuseDY = positionDSDY.xz * decalData.diffuseScaleBias.xy + decalData.diffuseScaleBias.zw;
float2 sampleNormalDX = positionDSDX.xz * decalData.normalScaleBias.xy + decalData.normalScaleBias.zw;
float2 sampleNormalDY = positionDSDY.xz * decalData.normalScaleBias.xy + decalData.normalScaleBias.zw;
float lodDiffuse = ComputeTextureLOD(sampleDiffuse, _DecalAtlasResolution * decalData.diffuseScaleBias.xy);
float lodNormal = ComputeTextureLOD(sampleNormal, _DecalAtlasResolution * decalData.normalScaleBias.xy);
float lodMask = ComputeTextureLOD(sampleMask, _DecalAtlasResolution * decalData.maskScaleBias.xy);
float2 sampleMaskDX = positionDSDX.xz * decalData.maskScaleBias.xy + decalData.maskScaleBias.zw;
float2 sampleMaskDY = positionDSDY.xz * decalData.maskScaleBias.xy + decalData.maskScaleBias.zw;
decalBlend = ((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f))) ? decalBlend : 0; // use blend of 0 instead of an 'if' because compiler moves the lod calculation inside the 'if' which causes incorrect values
// if any of the pixels in the 2x2 quad gets rejected
float lodDiffuse = ComputeTextureLOD(sampleDiffuse, sampleDiffuseDX, sampleDiffuseDY, _DecalAtlasResolution);
float lodNormal = ComputeTextureLOD(sampleNormal, sampleNormalDX, sampleNormalDY, _DecalAtlasResolution);
float lodMask = ComputeTextureLOD(sampleMask, sampleMaskDX, sampleMaskDY, _DecalAtlasResolution);
// Verified that lod calculation works with a test texture, looking at the shader code in Razor the lod calculation is outside the dynamic branches where the texture fetch happens,
// however compiler was placing it inside the branch that was rejecting the pixel, which was causing incorrect lod to be calculated for any 2x2 quad where any of the pixels were rejected,
// so had to use alpha blend of 0 instead of branching to solve that issue."
float decalBlend = decalData.normalToWorld[0][3];
if((decalData.diffuseScaleBias.x > 0) && (decalData.diffuseScaleBias.y > 0))
{
ApplyBlendDiffuse(DBuffer0, mask, sampleDiffuse, DBUFFERHTILEBIT_DIFFUSE, decalBlend, lodDiffuse);
alpha = alpha < decalBlend ? decalBlend : alpha; // use decal alpha if it is higher than transparent alpha
}
if ((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f)))
{
if((decalData.diffuseScaleBias.x > 0) && (decalData.diffuseScaleBias.y > 0))
{
ApplyBlendDiffuse(DBuffer0, mask, sampleDiffuse, DBUFFERHTILEBIT_DIFFUSE, decalBlend, lodDiffuse);
alpha = alpha < decalBlend ? decalBlend : alpha; // use decal alpha if it is higher than transparent alpha
}
if ((decalData.normalScaleBias.x > 0) && (decalData.normalScaleBias.y > 0))
{
ApplyBlendNormal(DBuffer1, mask, sampleNormal, DBUFFERHTILEBIT_NORMAL, (float3x3)decalData.normalToWorld, decalBlend, lodNormal);
}
if ((decalData.normalScaleBias.x > 0) && (decalData.normalScaleBias.y > 0))
{
ApplyBlendNormal(DBuffer1, mask, sampleNormal, DBUFFERHTILEBIT_NORMAL, (float3x3)decalData.normalToWorld, decalBlend, lodNormal);
}
if ((decalData.maskScaleBias.x > 0) && (decalData.maskScaleBias.y > 0))
{
ApplyBlendMask(DBuffer2, mask, sampleMask, DBUFFERHTILEBIT_MASK, decalBlend, lodMask);
if ((decalData.maskScaleBias.x > 0) && (decalData.maskScaleBias.y > 0))
{
ApplyBlendMask(DBuffer2, mask, sampleMask, DBUFFERHTILEBIT_MASK, decalBlend, lodMask);
}
}
}
#else

正在加载...
取消
保存