浏览代码

choose logBase value such that 50% of clusters (out of 64) are consumed between near plane and max opaque depth.

choose logBase value such that 50% of clusters (out of 64) are consumed
between near plane and max opaque depth (only when a depth buffer is
available). This allows us to light things behind the opaque tile while
allowing us to keep a limit on memory consumption.
/main
mmikk 8 年前
当前提交
e80c0e73
共有 5 个文件被更改,包括 66 次插入38 次删除
  1. 46
      Assets/ScriptableRenderLoop/fptl/ClusteredUtils.h
  2. 7
      Assets/ScriptableRenderLoop/fptl/FptlLighting.cs
  3. 9
      Assets/ScriptableRenderLoop/fptl/Internal-DeferredReflections.shader
  4. 11
      Assets/ScriptableRenderLoop/fptl/Internal-DeferredShading.shader
  5. 31
      Assets/ScriptableRenderLoop/fptl/lightlistbuild-clustered.compute

46
Assets/ScriptableRenderLoop/fptl/ClusteredUtils.h


#ifndef __CLUSTEREDUTILS_H__
#define __CLUSTEREDUTILS_H__
#ifndef FLT_EPSILON
#define FLT_EPSILON 1.192092896e-07f
#endif
int SnapToClusterIdx(float z_in, float fModulUserScale)
float GetScaleFromBase(float base)
{
const float C = (float) (1<<g_iLog2NumClusters);
const float geomSeries = (1.0 - pow(base, C))/(1-base); // geometric series: sum_k=0^{C-1} base^k
return geomSeries/(g_fFarPlane-g_fNearPlane);
}
int SnapToClusterIdx(float z_in, float suggestedBase)
{
#ifdef LEFT_HAND_COORDINATES
float z = z_in;

float userscale = g_fClustScale;
userscale *= fModulUserScale;
float userscale = GetScaleFromBase(suggestedBase);
#else
float userscale = g_fClustScale;
return (int) clamp( log2(dist*userscale*(g_fClustBase-1.0f) + 1) / log2(g_fClustBase), 0.0, (float) ((1<<g_iLog2NumClusters)-1) );
return (int) clamp( log2(dist*userscale*(suggestedBase-1.0f) + 1) / log2(suggestedBase), 0.0, (float) ((1<<g_iLog2NumClusters)-1) );
float ClusterIdxToZ(int k, float fModulUserScale)
float ClusterIdxToZ(int k, float suggestedBase)
float userscale = g_fClustScale;
userscale *= fModulUserScale;
float userscale = GetScaleFromBase(suggestedBase);
#else
float userscale = g_fClustScale;
float dist = (pow(g_fClustBase,(float) k)-1.0)/(userscale*(g_fClustBase-1.0f));
float dist = (pow(suggestedBase,(float) k)-1.0)/(userscale*(suggestedBase-1.0f));
res = dist+g_fNearPlane;
#ifdef LEFT_HAND_COORDINATES

#endif
}
// generate a log-base value such that half of the clusters are consumed from near plane to max. opaque depth of tile.
float SuggestLogBase50(float tileFarPlane)
{
const float C = (float) (1<<g_iLog2NumClusters);
float normDist = clamp( (tileFarPlane-g_fNearPlane) / (g_fFarPlane-g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow( (1.0 + sqrt(max(0.0,1.0-4.0*normDist*(1.0-normDist))))/(2.0*normDist), 2.0/C); //
return max(g_fClustBase, suggested_base);
}
// generate a log-base value such that (approximately) a quarter of the clusters are consumed from near plane to max. opaque depth of tile.
float SuggestLogBase25(float tileFarPlane)
{
const float C = (float) (1<<g_iLog2NumClusters);
float normDist = clamp( (tileFarPlane-g_fNearPlane) / (g_fFarPlane-g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow( (1/2.3)*max(0.0, (0.8/normDist)-1), 4.0/(C*2)); // approximate inverse of d*x^4 + (-x) + (1-d) = 0 - d is normalized distance
return max(g_fClustBase,suggested_base);
}

7
Assets/ScriptableRenderLoop/fptl/FptlLighting.cs


cmd.SetGlobalFloat("g_fClustScale", m_clustScale);
cmd.SetGlobalFloat("g_fClustBase", m_clustLogBase);
cmd.SetGlobalFloat("g_fNearPlane", camera.nearClipPlane);
cmd.SetGlobalFloat("g_fFarPlane", camera.farClipPlane);
cmd.SetGlobalFloat("g_fLog2NumClusters", (float) g_iLog2NumClusters);
m_DeferredMaterial.SetBuffer("g_vLayeredOffsetsBuffer", m_perVoxelOffset);

m_DeferredMaterial.SetBuffer("g_fModulUserscale", m_perTileLogBaseTweak);
m_DeferredReflectionMaterial.SetBuffer("g_fModulUserscale", m_perTileLogBaseTweak);
m_DeferredMaterial.SetBuffer("g_logBaseBuffer", m_perTileLogBaseTweak);
m_DeferredReflectionMaterial.SetBuffer("g_logBaseBuffer", m_perTileLogBaseTweak);
}
}

cmd.SetComputeBufferParam(m_BuildPerVoxelLightListShader, kGenListPerVoxelKernel, "g_LayeredOffset", m_perVoxelOffset);
cmd.SetComputeBufferParam(m_BuildPerVoxelLightListShader, kGenListPerVoxelKernel, "g_LayeredSingleIdxBuffer", m_globalLightListAtomic);
if(gUseDepthBuffer) cmd.SetComputeBufferParam(m_BuildPerVoxelLightListShader, kGenListPerVoxelKernel, "g_fModulUserscale", m_perTileLogBaseTweak);
if(gUseDepthBuffer) cmd.SetComputeBufferParam(m_BuildPerVoxelLightListShader, kGenListPerVoxelKernel, "g_logBaseBuffer", m_perTileLogBaseTweak);
int nrTilesX = (camera.pixelWidth + 15) / 16;
int nrTilesY = (camera.pixelHeight + 15) / 16;

9
Assets/ScriptableRenderLoop/fptl/Internal-DeferredReflections.shader


uniform float g_fClustScale;
uniform float g_fClustBase;
uniform float g_fNearPlane;
uniform float g_fFarPlane;
//uniform int g_iLog2NumClusters; // numClusters = (1<<g_iLog2NumClusters)
uniform float g_fLog2NumClusters;
static int g_iLog2NumClusters;

Buffer<float> g_fModulUserscale;
Buffer<float> g_logBaseBuffer;
#endif
#include "ClusteredUtils.h"

g_iLog2NumClusters = (int) (g_fLog2NumClusters+0.5); // ridiculous
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
float modulScale = g_fModulUserscale[tileIDX.y*nrTilesX + tileIDX.x];
float logBase = g_logBaseBuffer[tileIDX.y*nrTilesX + tileIDX.x];
float modulScale = 1.0;
float logBase = g_fClustBase;
int clustIdx = SnapToClusterIdx(linDepth, modulScale);
int clustIdx = SnapToClusterIdx(linDepth, logBase);
int nrClusters = (1<<g_iLog2NumClusters);
const int idx = ((REFLECTION_LIGHT*nrClusters + clustIdx)*nrTilesY + tileIDX.y)*nrTilesX + tileIDX.x;

11
Assets/ScriptableRenderLoop/fptl/Internal-DeferredShading.shader


uniform float g_fClustScale;
uniform float g_fClustBase;
uniform float g_fNearPlane;
uniform float g_fFarPlane;
//uniform int g_iLog2NumClusters; // numClusters = (1<<g_iLog2NumClusters)
uniform float g_fLog2NumClusters;
static int g_iLog2NumClusters;

Buffer<float> g_fModulUserscale;
Buffer<float> g_logBaseBuffer;
#endif
#include "ClusteredUtils.h"

g_iLog2NumClusters = (int) (g_fLog2NumClusters+0.5); // ridiculous
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
float modulScale = g_fModulUserscale[tileIDX.y*nrTilesX + tileIDX.x];
float logBase = g_logBaseBuffer[tileIDX.y*nrTilesX + tileIDX.x];
float modulScale = 1.0;
float logBase = g_fClustBase;
int clustIdx = SnapToClusterIdx(linDepth, modulScale);
int clustIdx = SnapToClusterIdx(linDepth, logBase);
int nrClusters = (1<<g_iLog2NumClusters);
const int idx = ((DIRECT_LIGHT*nrClusters + clustIdx)*nrTilesY + tileIDX.y)*nrTilesX + tileIDX.x;

GetLightCountAndStart(start, numLights, tileIDX, nrTilesX, nrTilesY, linDepth);
float3 c = ExecuteLightList(pixCoord, start, numLights, linDepth);
//c = OverlayHeatMap(numLights, c);
c = OverlayHeatMap(numLights, c);
return float4(c,1.0);
}

31
Assets/ScriptableRenderLoop/fptl/lightlistbuild-clustered.compute


RWBuffer<uint> g_LayeredSingleIdxBuffer : register( u2 );
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
RWBuffer<float> g_fModulUserscale : register( u3 );
RWBuffer<float> g_logBaseBuffer : register( u3 );
#endif

float4 FetchPlane(int l, int p);
bool CheckIntersection(int l, int k, uint2 viTilLL, uint2 viTilUR, float fModulUserScale)
bool CheckIntersection(int l, int k, uint2 viTilLL, uint2 viTilUR, float suggestedBase)
{
unsigned int val = (clusterIdxs[l>>1]>>(16*(l&1)))&0xffff;
bool bIsHit = ((val>>0)&0xff)<=((uint) k) && ((uint) k)<=((val>>8)&0xff);

float depthAtNearZ = ClusterIdxToZ(k, fModulUserScale);
float depthAtFarZ = ClusterIdxToZ(k+1, fModulUserScale);
float depthAtNearZ = ClusterIdxToZ(k, suggestedBase);
float depthAtFarZ = ClusterIdxToZ(k+1, suggestedBase);
for(int p=0; p<6; p++)
{

#endif
float3 vTileLL = float3(viTilLL.x/(float) iWidth, viTilLL.y/(float) iHeight, 0.0);
float3 vTileUR = float3((viTilLL.x+16)/(float) iWidth, (viTilLL.y+16)/(float) iHeight, dpt_ma);
float3 vTileUR = float3((viTilLL.x+16)/(float) iWidth, (viTilLL.y+16)/(float) iHeight, 1.0);
vTileUR.xy = min(vTileUR.xy,float2(1.0,1.0)).xy;

const float3 vMi = g_vBoundsBuffer[l];
const float3 vMa = g_vBoundsBuffer[l+g_iNrVisibLights];
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
if( all(vMa.xy>vTileLL.xy) && all(vMi.xyz<vTileUR.xyz))
#else
#endif
{
unsigned int uInc = 1;
unsigned int uIndex;

#else
float fTileFarPlane = -GetLinearDepth(dpt_ma);
#endif
float fDenom = fTileFarPlane - g_fNearPlane;
float fModulUserScale = fDenom>0.0 ? ((g_fFarPlane-g_fNearPlane)/fDenom) : 1.0; // readjust to new range.
float suggestedBase = SuggestLogBase50(fTileFarPlane);
float fModulUserScale = 1.0;
float suggestedBase = g_fClustBase;
#endif

for(int l=(int) t; l<((iNrCoarseLights+1)>>1); l += NR_THREADS)
{
const int l0 = coarseList[2*l+0], l1 = coarseList[min(2*l+1,iNrCoarseLights)];
const unsigned int clustIdxMi0 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l0].z), fModulUserScale));
const unsigned int clustIdxMa0 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l0+g_iNrVisibLights].z), fModulUserScale));
const unsigned int clustIdxMi1 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l1].z), fModulUserScale));
const unsigned int clustIdxMa1 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l1+g_iNrVisibLights].z), fModulUserScale));
const unsigned int clustIdxMi0 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l0].z), suggestedBase));
const unsigned int clustIdxMa0 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l0+g_iNrVisibLights].z), suggestedBase));
const unsigned int clustIdxMi1 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l1].z), suggestedBase));
const unsigned int clustIdxMa1 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l1+g_iNrVisibLights].z), suggestedBase));
clusterIdxs[l] = (clustIdxMa1<<24) | (clustIdxMi1<<16) | (clustIdxMa0<<8) | (clustIdxMi0<<0);
}

for(int l=ll; l<min(iNrCoarseLights,(ll+4)); l++)
{
if(offs<(start+iSpaceAvail) && i<nrClusters && CheckIntersection(l, i, viTilLL.xy, viTilUR.xy, fModulUserScale) )
if(offs<(start+iSpaceAvail) && i<nrClusters && CheckIntersection(l, i, viTilLL.xy, viTilUR.xy, suggestedBase) )
{
uint lightModel = g_vLightData[ coarseList[l] ].uLightModel;
++modelListCount[ lightModel==REFLECTION_LIGHT ? 1 : 0];

}
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
g_fModulUserscale[tileIDX.y*nrTilesX + tileIDX.x] = fModulUserScale;
g_logBaseBuffer[tileIDX.y*nrTilesX + tileIDX.x] = suggestedBase;
#endif
}

正在加载...
取消
保存