浏览代码

add clamping by half a texel when sampling from decal atlas

only rebuild decal atlas if out of space
/main
Paul Melamed 6 年前
当前提交
ff3c43c1
共有 3 个文件被更改,包括 86 次插入42 次删除
  1. 38
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
  2. 47
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl
  3. 43
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs

38
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs


static public float[] m_BoundingDistances = new float[1];
private Dictionary<int, DecalSet> m_DecalSets = new Dictionary<int, DecalSet>();
private TextureCache2D m_DecalAtlas = null;
// current camera
private Camera m_Camera;

private Texture2DAtlas m_Atlas = null;
public bool m_AllocationSuccess = true;
public static int kDecalAtlasWidth = 4096;
public static int kDecalAtlasHeight= 4096;

}
}
private bool AddTexture(CommandBuffer cmd, ref Vector4 scaleBias, Texture texture)
{
if (texture != null)
{
scaleBias = instance.Atlas.AddTexture(cmd, texture);
if (scaleBias == Vector4.zero)
{
return false;
}
}
else
{
scaleBias = Vector4.zero;
}
return true;
}
m_DiffuseScaleBias = (m_DiffuseTexture != null) ? instance.Atlas.AddTexture(cmd, m_DiffuseTexture) : Vector4.zero;
m_NormalScaleBias = (m_NormalTexture != null) ? instance.Atlas.AddTexture(cmd, m_NormalTexture) : Vector4.zero;
m_MaskScaleBias = (m_MaskTexture != null) ? instance.Atlas.AddTexture(cmd, m_MaskTexture) : Vector4.zero;
instance.m_AllocationSuccess &= AddTexture(cmd, ref m_DiffuseScaleBias, m_DiffuseTexture);
instance.m_AllocationSuccess &= AddTexture(cmd, ref m_NormalScaleBias, m_NormalTexture);
instance.m_AllocationSuccess &= AddTexture(cmd, ref m_MaskScaleBias, m_MaskTexture);
}
public void RemoveFromTextureCache()

// updates textures, texture atlas indices and blend value
public void UpdateCachedMaterialData(CommandBuffer cmd)
{
Atlas.ResetAllocator();
}
if (!instance.m_AllocationSuccess) // texture failed to find space in the atlas
{
Atlas.ResetAllocator(); // clear all allocations and try again in the hope that a previously allocated texture is not in this frame
foreach (var pair in m_DecalSets)
{
pair.Value.UpdateCachedMaterialData(cmd);
}
}
}

public void Cleanup()
{
if (m_DecalAtlas != null)
m_DecalAtlas.Release();
m_DecalAtlas = null;
m_DecalMesh = null;
m_Atlas = null;
}

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


float3 positionDS = mul(decalData.worldToDecal, float4(positionWS, 1.0)).xyz;
positionDS = positionDS * float3(1.0, -1.0, 1.0) + float3(0.5, 0.0f, 0.5); // decal clip space
if ((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f)))
{
// clamp by half a texel to avoid sampling neighboring textures in the atlas
float2 clampAmount = float2(0.5f / _DecalAtlasResolution.x, 0.5f / _DecalAtlasResolution.y);
float2 sampleDiffuse = positionDS.xz * decalData.diffuseScaleBias.xy + decalData.diffuseScaleBias.zw;
float2 sampleNormal = positionDS.xz * decalData.normalScaleBias.xy + decalData.normalScaleBias.zw;
float2 sampleMask = positionDS.xz * decalData.maskScaleBias.xy + decalData.maskScaleBias.zw;
float2 diffuseMin = decalData.diffuseScaleBias.zw + clampAmount; // offset into atlas is in .zw
float2 diffuseMax = decalData.diffuseScaleBias.zw + decalData.diffuseScaleBias.xy - clampAmount; // scale relative to full atlas size is in .xy so total texture extent in atlas is (1,1) * scale
// need to compute the mipmap LOD manually because we are sampling inside a loop
float3 positionDSDdx = mul(decalData.worldToDecal, float4(positionWSDdx, 0.0)).xyz; // transform the derivatives to decal space, any translation is irrelevant
float3 positionDSDdy = mul(decalData.worldToDecal, float4(positionWSDdy, 0.0)).xyz;
float2 normalMin = decalData.normalScaleBias.zw + clampAmount;
float2 normalMax = decalData.normalScaleBias.zw + decalData.normalScaleBias.xy - clampAmount;
float2 maskMin = decalData.maskScaleBias.zw + clampAmount;
float2 maskMax = decalData.maskScaleBias.zw + decalData.maskScaleBias.xy - clampAmount;
float2 sampleDiffuse = clamp(positionDS.xz * decalData.diffuseScaleBias.xy + decalData.diffuseScaleBias.zw, diffuseMin, diffuseMax);
float2 sampleNormal = clamp(positionDS.xz * decalData.normalScaleBias.xy + decalData.normalScaleBias.zw, normalMin, normalMax);
float2 sampleMask = clamp(positionDS.xz * decalData.maskScaleBias.xy + decalData.maskScaleBias.zw, maskMin, maskMax);
// need to compute the mipmap LOD manually because we are sampling inside a loop
float3 positionDSDdx = mul(decalData.worldToDecal, float4(positionWSDdx, 0.0)).xyz; // transform the derivatives to decal space, any translation is irrelevant
float3 positionDSDdy = mul(decalData.worldToDecal, float4(positionWSDdy, 0.0)).xyz;
float2 sampleDiffuseDdx = positionDSDdx.xz * decalData.diffuseScaleBias.xy; // factor in the atlas scale
float2 sampleDiffuseDdy = positionDSDdy.xz * decalData.diffuseScaleBias.xy;
float lodDiffuse = ComputeTextureLOD(sampleDiffuseDdx, sampleDiffuseDdy, _DecalAtlasResolution);
float2 sampleDiffuseDdx = positionDSDdx.xz * decalData.diffuseScaleBias.xy; // factor in the atlas scale
float2 sampleDiffuseDdy = positionDSDdy.xz * decalData.diffuseScaleBias.xy;
float lodDiffuse = ComputeTextureLOD(sampleDiffuseDdx, sampleDiffuseDdy, _DecalAtlasResolution);
float2 sampleNormalDdx = positionDSDdx.xz * decalData.normalScaleBias.xy;
float2 sampleNormalDdy = positionDSDdy.xz * decalData.normalScaleBias.xy;
float lodNormal = ComputeTextureLOD(sampleNormalDdx, sampleNormalDdy, _DecalAtlasResolution);
float2 sampleNormalDdx = positionDSDdx.xz * decalData.normalScaleBias.xy;
float2 sampleNormalDdy = positionDSDdy.xz * decalData.normalScaleBias.xy;
float lodNormal = ComputeTextureLOD(sampleNormalDdx, sampleNormalDdy, _DecalAtlasResolution);
float2 sampleMaskDdx = positionDSDdx.xz * decalData.maskScaleBias.xy;
float2 sampleMaskDdy = positionDSDdy.xz * decalData.maskScaleBias.xy;
float lodMask = ComputeTextureLOD(sampleMaskDdx, sampleMaskDdy, _DecalAtlasResolution);
float2 sampleMaskDdx = positionDSDdx.xz * decalData.maskScaleBias.xy;
float2 sampleMaskDdy = positionDSDdy.xz * decalData.maskScaleBias.xy;
float lodMask = ComputeTextureLOD(sampleMaskDdx, sampleMaskDdy, _DecalAtlasResolution);
float decalBlend = decalData.normalToWorld[0][3];
float decalBlend = decalData.normalToWorld[0][3];
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);

43
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs


using System.Collections.Generic;
using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;

private int m_Height;
private RenderTextureFormat m_Format;
private AtlasAllocator m_AtlasAllocator = null;
private Dictionary<IntPtr, Vector4> m_AllocationCache = new Dictionary<IntPtr, Vector4>();
public RTHandle AtlasTexture
{
get

public void Release()
{
ResetAllocator();
RTHandle.Release(m_AtlasTexture);
}

m_AllocationCache.Clear();
int width = texture.width;
int height = texture.height;
Vector4 scaleBias = m_AtlasAllocator.Allocate(width, height);
if ((scaleBias.x > 0) && (scaleBias.y > 0))
{
scaleBias.Scale(new Vector4(1.0f / m_Width, 1.0f / m_Height, 1.0f / m_Width, 1.0f / m_Height));
for (int mipLevel = 0; mipLevel < (texture as Texture2D).mipmapCount; mipLevel++)
IntPtr key = texture.GetNativeTexturePtr();
Vector4 scaleBias;
if (!m_AllocationCache.TryGetValue(key, out scaleBias))
{
int width = texture.width;
int height = texture.height;
scaleBias = m_AtlasAllocator.Allocate(width, height);
if ((scaleBias.x > 0) && (scaleBias.y > 0))
cmd.SetRenderTarget(m_AtlasTexture, mipLevel);
HDUtils.BlitQuad(cmd, texture, new Vector4(1, 1, 0, 0), scaleBias, mipLevel, false);
scaleBias.Scale(new Vector4(1.0f / m_Width, 1.0f / m_Height, 1.0f / m_Width, 1.0f / m_Height));
for (int mipLevel = 0; mipLevel < (texture as Texture2D).mipmapCount; mipLevel++)
{
cmd.SetRenderTarget(m_AtlasTexture, mipLevel);
HDUtils.BlitQuad(cmd, texture, new Vector4(1, 1, 0, 0), scaleBias, mipLevel, false);
}
m_AllocationCache.Add(key, scaleBias);
return scaleBias;
return scaleBias;
}
else
{
return new Vector4(0,0,0,0);
else
{
return new Vector4(0, 0, 0, 0);
}
return scaleBias;
}
}
}
正在加载...
取消
保存