浏览代码

intermediate commit, decals pass info to gpu light culling

/main
Paul Melamed 6 年前
当前提交
ffd9f57f
共有 10 个文件被更改,包括 208 次插入37 次删除
  1. 142
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
  2. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
  3. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  4. 46
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs
  5. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs.hlsl
  6. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-bigtile.compute
  7. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-clustered.compute
  8. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild.compute
  9. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs
  10. 32
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs.hlsl

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


}
private const int kDefaultDrawDistance = 1000;
static public int DrawDistance
public int DrawDistance
{
get
{

}
}
public TextureCache2D TextureAtlas
{
get
{
if (m_DecalAtlas == null)
{
m_DecalAtlas = new TextureCache2D();
m_DecalAtlas.AllocTextureArray(2048, 128, 128, TextureFormat.RGBA32, true);
}
return m_DecalAtlas;
}
}
private static readonly int m_NormalToWorldID = Shader.PropertyToID("normalToWorld");
private static MaterialPropertyBlock m_PropertyBlock = new MaterialPropertyBlock();

static public Matrix4x4[] m_InstanceNormalToWorld = new Matrix4x4[kDrawIndexedBatchSize];
static public float[] m_BoundingDistances = new float[1];
private const int kMaxClusteredDecals = 2048;
static public DecalData[] m_ClusteredDecalData = new DecalData[kMaxClusteredDecals];
static public int m_TotalClusteredDecals = 0;
private TextureCache2D m_DecalAtlas = null;
public DecalSet(Material material)
{
m_Material = material;
m_DiffuseTexture = material.GetTexture("_BaseColorMap");
m_NormalTexture = material.GetTexture("_NormalMap");
m_MaskTexture = material.GetTexture("_MaskMap");
}
private BoundingSphere GetDecalProjectBoundingSphere(Matrix4x4 decalToWorld)
{
Vector4 min = new Vector4();

BoundingSphere res = new BoundingSphere();
res.position = (max + min) / 2;
res.radius = ((Vector3)(max - min)).magnitude / 2;
res.radius = ((Vector3) (max - min)).magnitude / 2;
return res;
}

Matrix4x4 decalRotation = Matrix4x4.Rotate(decal.transform.rotation);
// z/y axis swap for normal to decal space, Unity is column major
float y0 = decalRotation.m01;
float y1 = decalRotation.m11;
float y2 = decalRotation.m21;
decalRotation.m01 = decalRotation.m02;
decalRotation.m11 = decalRotation.m12;
decalRotation.m21 = decalRotation.m22;
decalRotation.m02 = y0;
decalRotation.m12 = y1;
decalRotation.m22 = y2;
float y0 = decalRotation.m01;
float y1 = decalRotation.m11;
float y2 = decalRotation.m21;
decalRotation.m01 = decalRotation.m02;
decalRotation.m11 = decalRotation.m12;
decalRotation.m21 = decalRotation.m22;
decalRotation.m02 = y0;
decalRotation.m12 = y1;
decalRotation.m22 = y2;
// draw distance can't be more than global draw distance
m_CachedDrawDistances[decal.CullIndex].x = decal.m_DrawDistance < DrawDistance ? decal.m_DrawDistance : DrawDistance;
// draw distance can't be more than global draw distance
m_CachedDrawDistances[decal.CullIndex].x = decal.m_DrawDistance < DecalSystem.instance.DrawDistance
? decal.m_DrawDistance
: DecalSystem.instance.DrawDistance;
m_CachedDrawDistances[decal.CullIndex].y = decal.m_FadeScale;
m_BoundingSpheres[decal.CullIndex] = GetDecalProjectBoundingSphere(m_CachedTransforms[decal.CullIndex]);
}

m_BoundingSpheres.CopyTo(newSpheres, 0);
m_CachedTransforms.CopyTo(newCachedTransforms, 0);
m_CachedNormalToWorld.CopyTo(newCachedNormalToWorld, 0);
m_CachedDrawDistances.CopyTo(newCachedDrawDistances, 0);
m_CachedDrawDistances.CopyTo(newCachedDrawDistances, 0);
m_CachedDrawDistances = newCachedDrawDistances;
m_CachedDrawDistances = newCachedDrawDistances;
}
m_Decals[m_DecalsCount] = decal;

m_BoundingSpheres[removeAtIndex] = m_BoundingSpheres[m_DecalsCount - 1];
m_CachedTransforms[removeAtIndex] = m_CachedTransforms[m_DecalsCount - 1];
m_CachedNormalToWorld[removeAtIndex] = m_CachedNormalToWorld[m_DecalsCount - 1];
m_CachedDrawDistances[removeAtIndex] = m_CachedDrawDistances[m_DecalsCount - 1];
m_CachedDrawDistances[removeAtIndex] = m_CachedDrawDistances[m_DecalsCount - 1];
m_DecalsCount--;
decal.CullIndex = DecalProjectorComponent.kInvalidIndex;
}

Debug.LogError("Begin/EndCull() called out of sequence for decal projectors.");
}
// let the culling group code do some of the heavy lifting for global draw distance
m_BoundingDistances[0] = DrawDistance;
// let the culling group code do some of the heavy lifting for global draw distance
m_BoundingDistances[0] = DecalSystem.instance.DrawDistance;
m_CullingGroup.SetDistanceReferencePoint(camera.transform.position);
m_CullingGroup.SetBoundingDistances(m_BoundingDistances);
m_CullingGroup.SetDistanceReferencePoint(camera.transform.position);
m_CullingGroup.SetBoundingDistances(m_BoundingDistances);
m_CullingGroup.SetBoundingSpheres(m_BoundingSpheres);
m_CullingGroup.SetBoundingSphereCount(m_DecalsCount);
}

}
}
public void Render(ScriptableRenderContext renderContext, HDCamera camera, CommandBuffer cmd)
void UpdateTextureCache(CommandBuffer cmd)
if ((m_DiffuseTexIndex == -1) && (m_DiffuseTexture != null))
{
m_DiffuseTexIndex = DecalSystem.instance.TextureAtlas.FetchSlice(cmd, m_DiffuseTexture);
}
if ((m_NormalTexIndex == -1) && (m_NormalTexture != null))
{
m_NormalTexIndex = DecalSystem.instance.TextureAtlas.FetchSlice(cmd, m_NormalTexture);
}
if ((m_MaskTexIndex == -1) && (m_MaskTexture != null))
{
m_MaskTexIndex = DecalSystem.instance.TextureAtlas.FetchSlice(cmd, m_MaskTexture);
}
}
public void RemoveFromTextureCache()
{
if (m_DiffuseTexture != null)
{
DecalSystem.instance.TextureAtlas.RemoveEntryFromSlice(m_DiffuseTexture);
}
if (m_NormalTexture != null)
{
DecalSystem.instance.TextureAtlas.RemoveEntryFromSlice(m_NormalTexture);
}
if (m_MaskTexture != null)
{
DecalSystem.instance.TextureAtlas.RemoveEntryFromSlice(m_MaskTexture);
}
}
public void Render(ScriptableRenderContext renderContext, HDCamera camera, CommandBuffer cmd, LightLoop lightLoop)
{
if(m_NumResults == 0)
return;
UpdateTextureCache(cmd);
var worldToView = Matrix4x4.Scale(new Vector3(1, 1, -1)) * camera.camera.worldToCameraMatrix;
int instanceCount = 0;
Vector3 cameraPos = camera.cameraPos;
for (int resultIndex = 0; resultIndex < m_NumResults; resultIndex++)

m_InstanceNormalToWorld[instanceCount] = m_CachedNormalToWorld[decalIndex];
float fadeFactor = (cullDistance - distanceToDecal) / (cullDistance * (1.0f - m_CachedDrawDistances[decalIndex].y));
m_InstanceNormalToWorld[instanceCount].m03 = fadeFactor; // rotation only matrix so 3rd column can be used to pass some values
instanceCount++;
if (m_TotalClusteredDecals < kMaxClusteredDecals)
{
lightLoop.GetDecalVolumeDataAndBound(m_CachedTransforms[decalIndex], worldToView);
m_ClusteredDecalData[m_TotalClusteredDecals].normalToWorld = m_InstanceNormalToWorld[instanceCount];
m_ClusteredDecalData[m_TotalClusteredDecals].diffuseIndex = m_DiffuseTexIndex;
m_ClusteredDecalData[m_TotalClusteredDecals].normalIndex = m_NormalTexIndex;
m_ClusteredDecalData[m_TotalClusteredDecals].maskIndex = m_MaskTexIndex;
m_TotalClusteredDecals++;
}
instanceCount++;
if (instanceCount == kDrawIndexedBatchSize)
{
m_PropertyBlock.SetMatrixArray(m_NormalToWorldID, m_InstanceNormalToWorld);

{
return this.m_Material;
}
set
{
this.m_Material = value;
}
}
public int Count

private Matrix4x4[] m_CachedNormalToWorld = new Matrix4x4[kDecalBlockSize];
private Vector2[] m_CachedDrawDistances = new Vector2[kDecalBlockSize]; // x - draw distance, y - fade scale
private Material m_Material;
private Texture m_DiffuseTexture = null;
private Texture m_NormalTexture = null;
private Texture m_MaskTexture = null;
private int m_DiffuseTexIndex = -1;
private int m_NormalTexIndex = -1;
private int m_MaskTexIndex = -1;
}
public void AddDecal(DecalProjectorComponent decal)

int key = decal.m_Material.GetInstanceID();
if (!m_DecalSets.TryGetValue(key, out decalSet))
{
decalSet = new DecalSet();
decalSet.KeyMaterial = decal.m_Material;
decalSet = new DecalSet(decal.m_Material);
m_DecalSets.Add(key, decalSet);
}
decalSet.AddDecal(decal);

decalSet.RemoveDecal(decal);
if (decalSet.Count == 0)
{
decalSet.RemoveFromTextureCache();
m_DecalSets.Remove(key);
}
}

}
}
public void Render(ScriptableRenderContext renderContext, HDCamera camera, CommandBuffer cmd)
// need a better way than passing light loop here
public void Render(ScriptableRenderContext renderContext, HDCamera camera, CommandBuffer cmd, LightLoop lightLoop)
m_TotalClusteredDecals = 0;
pair.Value.Render(renderContext, camera, cmd);
pair.Value.Render(renderContext, camera, cmd, lightLoop);
}
}
}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs


CoreUtils.SetRenderTarget(cmd, m_DbufferManager.GetDBuffers(), m_CameraDepthStencilBufferRT); // do not clear anymore
m_DbufferManager.SetHTile(m_DbufferManager.dbufferCount, cmd);
DecalSystem.instance.Render(renderContext, camera, cmd);
DecalSystem.instance.Render(renderContext, camera, cmd, m_LightLoop);
m_DbufferManager.UnSetHTile(cmd);
}
}

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int g_LayeredSingleIdxBuffer = Shader.PropertyToID("g_LayeredSingleIdxBuffer");
public static readonly int _EnvLightIndexShift = Shader.PropertyToID("_EnvLightIndexShift");
public static readonly int _DecalIndexShift = Shader.PropertyToID("_DecalIndexShift");
public static readonly int g_isOrthographic = Shader.PropertyToID("g_isOrthographic");
public static readonly int g_iNrVisibLights = Shader.PropertyToID("g_iNrVisibLights");
public static readonly int g_mScrProjection = Shader.PropertyToID("g_mScrProjection");

46
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs


Punctual,
Area,
Env,
Decal,
Count
}

return true;
}
public void GetDecalVolumeDataAndBound(Matrix4x4 decalToWorld, Matrix4x4 worldToView)
{
var bound = new SFiniteLightBound();
var lightVolumeData = new LightVolumeData();
var yExtent = decalToWorld.GetColumn(1) * 0.5f; // because of how decal mesh is defined Y is not centered, but rather covers a full extent
// transform to camera space (becomes a left hand coordinate frame in Unity since Determinant(worldToView)<0)
var influenceRightVS = worldToView.MultiplyVector(decalToWorld.GetColumn(0));
var influenceUpVS = worldToView.MultiplyVector(yExtent);
var influenceForwardVS = worldToView.MultiplyVector(decalToWorld.GetColumn(2));
var influencePositionVS = worldToView.MultiplyPoint(decalToWorld.GetColumn(3) + yExtent); // place the mesh pivot in the center
var influenceExtents = influenceRightVS + influenceUpVS + influenceForwardVS;
influenceExtents.x = Mathf.Abs(influenceExtents.x);
influenceExtents.y = Mathf.Abs(influenceExtents.y);
influenceExtents.z = Mathf.Abs(influenceExtents.z);
lightVolumeData.lightCategory = (uint)LightCategory.Env;
lightVolumeData.lightVolume = (uint)LightVolumeType.Box;
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Env;
bound.center = influencePositionVS;
bound.boxAxisX = influenceRightVS;
bound.boxAxisY = influenceUpVS;
bound.boxAxisZ = influenceForwardVS;
bound.scaleXY.Set(1.0f, 1.0f);
bound.radius = influenceExtents.magnitude;
// The culling system culls pixels that are further
// than a threshold to the box influence extents.
// So we use an arbitrary threshold here (k_BoxCullingExtentOffset)
lightVolumeData.lightPos = influencePositionVS;
lightVolumeData.lightAxisX = influenceRightVS;
lightVolumeData.lightAxisY = influenceUpVS;
lightVolumeData.lightAxisZ = influenceForwardVS;
lightVolumeData.boxInnerDist = influenceExtents - k_BoxCullingExtentThreshold;
lightVolumeData.boxInvRange.Set(1.0f / k_BoxCullingExtentThreshold.x, 1.0f / k_BoxCullingExtentThreshold.y, 1.0f / k_BoxCullingExtentThreshold.z);
m_lightList.bounds.Add(bound);
m_lightList.lightVolumes.Add(lightVolumeData);
}
public void GetEnvLightVolumeDataAndBound(ProbeWrapper probe, LightVolumeType lightVolumeType, Matrix4x4 worldToView)
{
var bound = new SFiniteLightBound();

bool isOrthographic = camera.orthographic;
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs.g_isOrthographic, isOrthographic ? 1 : 0);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs._EnvLightIndexShift, m_lightList.lights.Count);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs._DecalIndexShift, m_lightList.lights.Count + m_lightList.envLights.Count);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, HDShaderIDs.g_iNrVisibLights, m_lightCount);
cmd.SetComputeMatrixParam(buildPerVoxelLightListShader, HDShaderIDs.g_mScrProjection, projscr);
cmd.SetComputeMatrixParam(buildPerVoxelLightListShader, HDShaderIDs.g_mInvScrProjection, invProjscr);

cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs.g_isOrthographic, isOrthographic ? 1 : 0);
cmd.SetComputeIntParams(buildPerBigTileLightListShader, HDShaderIDs.g_viDimensions, s_TempIntArray);
cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs._EnvLightIndexShift, m_lightList.lights.Count);
cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs._DecalIndexShift, m_lightList.lights.Count + m_lightList.envLights.Count);
cmd.SetComputeIntParam(buildPerBigTileLightListShader, HDShaderIDs.g_iNrVisibLights, m_lightCount);
cmd.SetComputeMatrixParam(buildPerBigTileLightListShader, HDShaderIDs.g_mScrProjection, projscr);
cmd.SetComputeMatrixParam(buildPerBigTileLightListShader, HDShaderIDs.g_mInvScrProjection, invProjscr);

cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs.g_isOrthographic, isOrthographic ? 1 : 0);
cmd.SetComputeIntParams(buildPerTileLightListShader, HDShaderIDs.g_viDimensions, s_TempIntArray);
cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs._EnvLightIndexShift, m_lightList.lights.Count);
cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs._DecalIndexShift, m_lightList.lights.Count + m_lightList.envLights.Count);
cmd.SetComputeIntParam(buildPerTileLightListShader, HDShaderIDs.g_iNrVisibLights, m_lightCount);
cmd.SetComputeBufferParam(buildPerTileLightListShader, s_GenListPerTileKernel, HDShaderIDs.g_vBoundsBuffer, s_AABBBoundsBuffer);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs.hlsl


#define LIGHTCATEGORY_PUNCTUAL (0)
#define LIGHTCATEGORY_AREA (1)
#define LIGHTCATEGORY_ENV (2)
#define LIGHTCATEGORY_COUNT (3)
#define LIGHTCATEGORY_DECAL (3)
#define LIGHTCATEGORY_COUNT (4)
//
// UnityEngine.Experimental.Rendering.HDPipeline.LightFeatureFlags: static fields

#define MAX_NR_LIGHTS_PER_CAMERA (1024)
#define MAX_NR_BIG_TILE_LIGHTS_PLUS_ONE (512)
#define VIEWPORT_SCALE_Z (1)
#define USE_LEFT_HAND_CAMERA_SPACE (1)
#define TILE_SIZE_FPTL (16)
#define TILE_SIZE_CLUSTERED (32)
#define NUM_FEATURE_VARIANTS (27)

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-bigtile.compute


uniform float g_fFarPlane;
uniform uint g_isOrthographic;
uniform int _EnvLightIndexShift;
uniform int _DecalIndexShift;
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<LightVolumeData> _LightVolumeData : register(t2);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild-clustered.compute


float4x4 g_mScrProjection;
uint g_isOrthographic;
int _EnvLightIndexShift;
int _DecalIndexShift;
float g_fClustScale;
float g_fClustBase;

// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT];
ZERO_INITIALIZE_ARRAY(int, shiftIndex, LIGHTCATEGORY_COUNT);
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 2] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _DecalIndexShift;
int categoryListCount[LIGHTCATEGORY_COUNT]; // direct light count and reflection lights
ZERO_INITIALIZE_ARRAY(int, categoryListCount, LIGHTCATEGORY_COUNT);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/lightlistbuild.compute


uniform float4x4 g_mScrProjection;
uniform uint g_isOrthographic;
uniform int _EnvLightIndexShift;
uniform int _DecalIndexShift;
uniform uint g_BaseFeatureFlags;
Texture2D g_depth_tex : register( t0 );

// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT];
ZERO_INITIALIZE_ARRAY(int, shiftIndex, LIGHTCATEGORY_COUNT);
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 2] = _EnvLightIndexShift;
shiftIndex[LIGHTCATEGORY_COUNT - 1] = _DecalIndexShift;
for(int category=0; category<LIGHTCATEGORY_COUNT; category++)
{

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


RTReadWrite = m_RTReadWrite;
}
}
[GenerateHLSL]
public struct DecalData
{
public Matrix4x4 normalToWorld;
public int diffuseIndex;
public int normalIndex;
public int maskIndex;
};
}

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


float4 baseColor;
float4 normalWS;
float4 mask;
int HTileMask;
uint HTileMask;
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.DecalData
// PackingRules = Exact
struct DecalData
{
float4x4 normalToWorld;
int diffuseIndex;
int normalIndex;
int maskIndex;
};
//
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.DecalData
//
float4x4 GetNormalToWorld(DecalData value)
{
return value.normalToWorld;
}
int GetDiffuseIndex(DecalData value)
{
return value.diffuseIndex;
}
int GetNormalIndex(DecalData value)
{
return value.normalIndex;
}
int GetMaskIndex(DecalData value)
{
return value.maskIndex;
}
//
// Debug functions

正在加载...
取消
保存