浏览代码

using new texture atlas to store decal textures

/main
Paul Melamed 7 年前
当前提交
ff3bd5a3
共有 10 个文件被更改,包括 132 次插入25 次删除
  1. 2
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl
  2. 25
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
  3. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  4. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs
  5. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs.hlsl
  6. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl
  7. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl
  8. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl
  9. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl
  10. 99
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs

2
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl


uint botBit = (vertexID & 1);
float u = topBit;
float v = (topBit + botBit) & 1; // produces 0 for indices 0,3 and 1 for 1,2
#if !UNITY_UV_STARTS_AT_TOP
#if UNITY_UV_STARTS_AT_TOP
v = 1.0 - v;
#endif
return float2(u, v);

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


normalToWorldBatch[instanceCount] = m_CachedNormalToWorld[decalIndex];
float fadeFactor = Mathf.Clamp((cullDistance - distanceToDecal) / (cullDistance * (1.0f - m_CachedDrawDistances[decalIndex].y)), 0.0f, 1.0f);
normalToWorldBatch[instanceCount].m03 = fadeFactor * m_Blend; // vector3 rotation matrix so bottom row and last column can be used for other data to save space
normalToWorldBatch[instanceCount].m13 = m_DiffuseTexIndex; // texture atlas indices needed for clustered
normalToWorldBatch[instanceCount].m23 = m_NormalTexIndex;
normalToWorldBatch[instanceCount].m33 = m_MaskTexIndex;
m_DecalDatas[m_DecalDatasCount].diffuseScaleBias = m_DiffuseScaleBias;
m_DecalDatas[m_DecalDatasCount].normalScaleBias = m_NormalScaleBias;
m_DecalDatas[m_DecalDatasCount].maskScaleBias = m_MaskScaleBias;
GetDecalVolumeDataAndBound(decalToWorldBatch[instanceCount], worldToView);
m_DecalDatasCount++;

void UpdateTextureCache(CommandBuffer cmd)
{
m_DiffuseTexIndex = (m_DiffuseTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_DiffuseTexture) : -1;
m_NormalTexIndex = (m_NormalTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_NormalTexture) : -1;
m_MaskTexIndex = (m_MaskTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_MaskTexture) : -1;
// m_DiffuseTexIndex = (m_DiffuseTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_DiffuseTexture) : -1;
// m_NormalTexIndex = (m_NormalTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_NormalTexture) : -1;
// m_MaskTexIndex = (m_MaskTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_MaskTexture) : -1;
if (m_DiffuseTexture != null)
{
instance.Atlas.AddTexture(cmd, m_DiffuseTexture);
}
m_DiffuseScaleBias = (m_DiffuseTexture != null) ? instance.Atlas.AddTexture(cmd, m_DiffuseTexture) : Vector4.zero;
}
public void RemoveFromTextureCache()

private Texture m_NormalTexture = null;
private Texture m_MaskTexture = null;
private float m_Blend = 0;
private int m_DiffuseTexIndex = -1;
private int m_NormalTexIndex = -1;
private int m_MaskTexIndex = -1;
private Vector4 m_DiffuseScaleBias = Vector4.zero;
private Vector4 m_NormalScaleBias = Vector4.zero;
private Vector4 m_MaskScaleBias = Vector4.zero;
}
public DecalHandle AddDecal(Transform transform, float drawDistance, float fadeScale, Material material)

public void SetAtlas(CommandBuffer cmd)
{
cmd.SetGlobalTexture(HDShaderIDs._DecalAtlasID, TextureAtlas.GetTexCache());
cmd.SetGlobalTexture(HDShaderIDs._DecalAtlas2DID, Atlas.AtlasTexture);
}
// updates textures, texture atlas indices and blend value

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


// all decal properties
public static readonly int _NormalToWorldID = Shader.PropertyToID("_NormalToWorld");
public static readonly int _DecalAtlas2DID = Shader.PropertyToID("_DecalAtlas2D");
public static readonly int _DecalAtlasID = Shader.PropertyToID("_DecalAtlas");
public static readonly int _DecalHTileTexture = Shader.PropertyToID("_DecalHTileTexture");
public static readonly int _DecalIndexShift = Shader.PropertyToID("_DecalIndexShift");

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs


{
public Matrix4x4 worldToDecal;
public Matrix4x4 normalToWorld;
public Vector4 diffuseScaleBias;
public Vector4 normalScaleBias;
public Vector4 maskScaleBias;
};
}

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


{
float4x4 worldToDecal;
float4x4 normalToWorld;
float4 diffuseScaleBias;
float4 normalScaleBias;
float4 maskScaleBias;
};
//

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


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

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


#include "CoreRP/ShaderLibrary/Packing.hlsl"
#include "CoreRP/ShaderLibrary/Sampling/SampleUVMapping.hlsl"
void GetSurfaceData(float2 texCoordDS, float4x4 decalToWorld, out DecalSurfaceData surfaceData)
void GetSurfaceData(float2 texCoordDS, float4x4 normalToWorld, out DecalSurfaceData surfaceData)
float totalBlend = clamp(decalToWorld[0][3], 0.0f, 1.0f);
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);
totalBlend = surfaceData.baseColor.w; // base alpha affects aall other channels;
totalBlend = surfaceData.baseColor.w; // base alpha affects all other channels;
surfaceData.normalWS.xyz = mul((float3x3)decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, texCoordDS))) * 0.5f + 0.5f;
surfaceData.normalWS.xyz = mul((float3x3)normalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, texCoordDS))) * 0.5f + 0.5f;
surfaceData.normalWS.w = totalBlend;
surfaceData.HTileMask |= DBUFFERHTILEBIT_NORMAL;
#endif

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


void ApplyBlendDiffuse(inout float4 dst, inout int matMask, float2 texCoords, int sliceIndex, int mapMask, inout float blend, float lod)
{
float4 src = SAMPLE_TEXTURE2D_ARRAY_LOD(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex, lod);
//float4 src = SAMPLE_TEXTURE2D_ARRAY_LOD(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex, lod);
float4 src = SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, 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);

int diffuseIndex = decalData.normalToWorld[1][3];
int normalIndex = decalData.normalToWorld[2][3];
int maskIndex = decalData.normalToWorld[3][3];
float lod = ComputeTextureLOD(positionDS.xz, _DecalAtlasResolution);
positionDS.xz = positionDS.xz * decalData.diffuseScaleBias.xy + decalData.diffuseScaleBias.zw;
float lod = ComputeTextureLOD(positionDS.xz, _DecalAtlasResolution * decalData.diffuseScaleBias.xy);
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

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl


clip(1.0 - positionDS); // Clip value above one
DecalSurfaceData surfaceData;
float4x4 decalToWorld = UNITY_ACCESS_INSTANCED_PROP(matrix, _NormalToWorld);
GetSurfaceData(positionDS.xz, decalToWorld, surfaceData);
float4x4 normalToWorld = UNITY_ACCESS_INSTANCED_PROP(matrix, _NormalToWorld);
GetSurfaceData(positionDS.xz, normalToWorld, surfaceData);
// have to do explicit test since compiler behavior is not defined for RW resources and discard instructions
if((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f)))

99
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs


namespace UnityEngine.Experimental.Rendering
{
public class AtlasAllocator
{
private class AtlasNode
{
public AtlasNode m_RightChild = null;
public AtlasNode m_BottomChild = null;
public Rect m_Rect = new Rect(0,0,0,0);
public AtlasNode Allocate(int width, int height)
{
// not a leaf node, try children
if(m_RightChild != null)
{
AtlasNode node = m_RightChild.Allocate(width, height);
if(node == null)
{
node = m_BottomChild.Allocate(width, height);
}
return node;
}
//leaf node, check for fit
if ((width <= m_Rect.width) && (height <= m_Rect.height))
{
// perform the split
m_RightChild = new AtlasNode();
m_BottomChild = new AtlasNode();
if (width > height) // logic to decide which way to split +--------+------+
{ // | | |
m_RightChild.m_Rect.x = m_Rect.x + width; // | | |
m_RightChild.m_Rect.y = m_Rect.y; // +--------+------+
m_RightChild.m_Rect.width = m_Rect.width - width; // | |
m_RightChild.m_Rect.height = height; // | |
// +---------------+
m_BottomChild.m_Rect.x = m_Rect.x;
m_BottomChild.m_Rect.y = m_Rect.y + height;
m_BottomChild.m_Rect.width = m_Rect.width;
m_BottomChild.m_Rect.height = m_Rect.height - height;
}
else
{ // +---+-----------+
m_RightChild.m_Rect.x = m_Rect.x + width; // | | |
m_RightChild.m_Rect.y = m_Rect.y; // | | |
m_RightChild.m_Rect.width = m_Rect.width - width; // +---+ +
m_RightChild.m_Rect.height = m_Rect.height; // | | |
// | | |
m_BottomChild.m_Rect.x = m_Rect.x; // +---+-----------+
m_BottomChild.m_Rect.y = m_Rect.y + height;
m_BottomChild.m_Rect.width = m_Rect.width;
m_BottomChild.m_Rect.height = m_Rect.height - height;
}
m_Rect.width = width;
m_Rect.height = height;
return this;
}
return null;
}
}
private AtlasNode m_Root;
public AtlasAllocator(int width, int height)
{
m_Root = new AtlasNode();
m_Root.m_Rect.Set(0, 0, width, height);
}
public Rect Allocate(int width, int height)
{
AtlasNode node = m_Root.Allocate(width, height);
if(node != null)
{
return node.m_Rect;
}
else
{
return new Rect(0, 0, 0, 0);
}
}
}
public class Texture2DAtlas
{
private RTHandle m_AtlasTexture = null;

public RTHandle AtlasTexture
{
get
{
return m_AtlasTexture;
}
}
public Texture2DAtlas(int width, int height, RenderTextureFormat format)
{
m_Width = width;

RTHandle.Release(m_AtlasTexture);
}
public void AddTexture(CommandBuffer cmd, Texture texture)
public Vector4 AddTexture(CommandBuffer cmd, Texture texture)
Vector4 scaleBias = new Vector4(scaleW, scaleH, 0, 0);
HDUtils.BlitQuad(cmd, texture, new Vector4(1, 1, 0, 0), new Vector4(scaleW, scaleH, 0, 0), mipLevel, false);
HDUtils.BlitQuad(cmd, texture, new Vector4(1, 1, 0, 0), scaleBias, mipLevel, false);
return scaleBias;
}
}
}
正在加载...
取消
保存