您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
295 行
12 KiB
295 行
12 KiB
//-----------------------------------------------------------------------------
|
|
// LightLoop
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifdef LIGHTLOOP_TILE_PASS
|
|
|
|
// Calculate the offset in global light index light for current light category
|
|
int GetTileOffset(PositionInputs posInput, uint lightCategory)
|
|
{
|
|
uint2 tileIndex = posInput.unPositionSS / TILE_SIZE;
|
|
return (tileIndex.y + lightCategory * _NumTileY) * _NumTileX + tileIndex.x;
|
|
}
|
|
|
|
void GetCountAndStartTile(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
|
|
{
|
|
const int tileOffset = GetTileOffset(posInput, lightCategory);
|
|
|
|
// The first entry inside a tile is the number of light for lightCategory (thus the +0)
|
|
lightCount = g_vLightListGlobal[DWORD_PER_TILE * tileOffset + 0] & 0xffff;
|
|
start = tileOffset;
|
|
}
|
|
|
|
uint FetchIndexTile(uint tileOffset, uint lightIndex)
|
|
{
|
|
const uint lightIndexPlusOne = lightIndex + 1; // Add +1 as first slot is reserved to store number of light
|
|
// Light index are store on 16bit
|
|
return (g_vLightListGlobal[DWORD_PER_TILE * tileOffset + (lightIndexPlusOne >> 1)] >> ((lightIndexPlusOne & 1) * DWORD_PER_TILE)) & 0xffff;
|
|
}
|
|
|
|
|
|
#ifdef USE_FPTL_LIGHTLIST
|
|
|
|
void GetCountAndStart(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
|
|
{
|
|
GetCountAndStartTile(posInput, lightCategory, start, lightCount);
|
|
}
|
|
|
|
uint FetchIndex(uint tileOffset, uint lightIndex)
|
|
{
|
|
return FetchIndexTile(tileOffset, lightIndex);
|
|
}
|
|
|
|
#else
|
|
|
|
#include "ClusteredUtils.hlsl"
|
|
|
|
void GetCountAndStartCluster(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
|
|
{
|
|
uint2 tileIndex = posInput.unPositionSS / TILE_SIZE;
|
|
|
|
float logBase = g_fClustBase;
|
|
if (g_isLogBaseBufferEnabled)
|
|
{
|
|
logBase = g_logBaseBuffer[tileIndex.y * _NumTileX + tileIndex.x];
|
|
}
|
|
|
|
int clustIdx = SnapToClusterIdxFlex(posInput.depthVS, logBase, g_isLogBaseBufferEnabled != 0);
|
|
|
|
int nrClusters = (1 << g_iLog2NumClusters);
|
|
const int idx = ((lightCategory * nrClusters + clustIdx) * _NumTileY + tileIndex.y) * _NumTileX + tileIndex.x;
|
|
uint dataPair = g_vLayeredOffsetsBuffer[idx];
|
|
start = dataPair & 0x7ffffff;
|
|
lightCount = (dataPair >> 27) & 31;
|
|
}
|
|
|
|
uint FetchIndexCluster(uint tileOffset, uint lightIndex)
|
|
{
|
|
return g_vLightListGlobal[tileOffset + lightIndex];
|
|
}
|
|
|
|
void GetCountAndStart(PositionInputs posInput, uint lightCategory, out uint start, out uint lightCount)
|
|
{
|
|
if (_UseTileLightList)
|
|
GetCountAndStartTile(posInput, lightCategory, start, lightCount);
|
|
else
|
|
GetCountAndStartCluster(posInput, lightCategory, start, lightCount);
|
|
}
|
|
|
|
uint FetchIndex(uint tileOffset, uint lightIndex)
|
|
{
|
|
if (_UseTileLightList)
|
|
return FetchIndexTile(tileOffset, lightIndex);
|
|
else
|
|
return FetchIndexCluster(tileOffset, lightIndex);
|
|
}
|
|
|
|
#endif
|
|
|
|
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
|
|
void LightLoop( float3 V, PositionInputs posInput, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
|
|
out float3 diffuseLighting,
|
|
out float3 specularLighting)
|
|
{
|
|
LightLoopContext context;
|
|
ZERO_INITIALIZE(LightLoopContext, context);
|
|
|
|
diffuseLighting = float3(0.0, 0.0, 0.0);
|
|
specularLighting = float3(0.0, 0.0, 0.0);
|
|
|
|
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
|
|
|
|
#ifdef PROCESS_DIRECTIONAL_LIGHT
|
|
for (i = 0; i < _DirectionalLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
|
|
EvaluateBSDF_Directional( context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
|
|
diffuseLighting += localDiffuseLighting;
|
|
specularLighting += localSpecularLighting;
|
|
}
|
|
#endif
|
|
|
|
#ifdef PROCESS_PUNCTUAL_LIGHT
|
|
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
|
|
uint punctualLightStart;
|
|
uint punctualLightCount;
|
|
GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, punctualLightStart, punctualLightCount);
|
|
for (i = 0; i < punctualLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
|
|
EvaluateBSDF_Punctual( context, V, posInput, prelightData, _LightDatas[FetchIndex(punctualLightStart, i)], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
|
|
diffuseLighting += localDiffuseLighting;
|
|
specularLighting += localSpecularLighting;
|
|
}
|
|
#endif
|
|
|
|
#ifdef PROCESS_AREA_LIGHT
|
|
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
|
|
uint areaLightStart;
|
|
uint areaLightCount;
|
|
GetCountAndStart(posInput, LIGHTCATEGORY_AREA, areaLightStart, areaLightCount);
|
|
for (i = 0; i < areaLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
|
|
uint areaIndex = FetchIndex(areaLightStart, i);
|
|
|
|
if(_LightDatas[areaIndex].lightType == GPULIGHTTYPE_LINE)
|
|
{
|
|
EvaluateBSDF_Line( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
}
|
|
else
|
|
{
|
|
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
}
|
|
|
|
|
|
diffuseLighting += localDiffuseLighting;
|
|
specularLighting += localSpecularLighting;
|
|
}
|
|
#endif
|
|
|
|
#ifdef PROCESS_ENV_LIGHT
|
|
|
|
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
|
|
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
|
|
|
|
// Only apply sky IBL if the sky texture is available.
|
|
if (_EnvLightSkyEnabled)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
float2 weight;
|
|
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
|
|
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
|
|
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
|
|
EvaluateBSDF_Env(context, V, posInput, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
|
|
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
|
|
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
|
|
}
|
|
|
|
uint envLightStart;
|
|
uint envLightCount;
|
|
GetCountAndStart(posInput, LIGHTCATEGORY_ENV, envLightStart, envLightCount);
|
|
|
|
for (i = 0; i < envLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
float2 weight;
|
|
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
|
|
EvaluateBSDF_Env(context, V, posInput, prelightData, _EnvLightDatas[FetchIndex(envLightStart, i)], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
|
|
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
|
|
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
|
|
}
|
|
|
|
diffuseLighting += iblDiffuseLighting;
|
|
specularLighting += iblSpecularLighting;
|
|
#endif
|
|
|
|
// TODO: currently apply GI at the same time as reflection
|
|
#ifdef PROCESS_ENV_LIGHT
|
|
// Add indirect diffuse + emissive (if any)
|
|
diffuseLighting += bakeDiffuseLighting;
|
|
#endif
|
|
}
|
|
|
|
#else // LIGHTLOOP_SINGLE_PASS
|
|
|
|
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
|
|
void LightLoop( float3 V, PositionInputs posInput, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
|
|
out float3 diffuseLighting,
|
|
out float3 specularLighting)
|
|
{
|
|
LightLoopContext context;
|
|
ZERO_INITIALIZE(LightLoopContext, context);
|
|
|
|
diffuseLighting = float3(0.0, 0.0, 0.0);
|
|
specularLighting = float3(0.0, 0.0, 0.0);
|
|
|
|
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
|
|
|
|
for (i = 0; i < _DirectionalLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
|
|
EvaluateBSDF_Directional( context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
|
|
diffuseLighting += localDiffuseLighting;
|
|
specularLighting += localSpecularLighting;
|
|
}
|
|
|
|
for (i = 0; i < _PunctualLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
|
|
EvaluateBSDF_Punctual( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
|
|
diffuseLighting += localDiffuseLighting;
|
|
specularLighting += localSpecularLighting;
|
|
}
|
|
|
|
// Area are store with punctual, just offset the index
|
|
for (i = _PunctualLightCount; i < _AreaLightCount + _PunctualLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
|
|
if (_LightDatas[i].lightType == GPULIGHTTYPE_LINE)
|
|
{
|
|
EvaluateBSDF_Line( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
}
|
|
else
|
|
{
|
|
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
|
|
localDiffuseLighting, localSpecularLighting);
|
|
}
|
|
|
|
diffuseLighting += localDiffuseLighting;
|
|
specularLighting += localSpecularLighting;
|
|
}
|
|
|
|
// TODO: Check the reflection hierarchy, for the current system (matching legacy unity) we must sort from bigger solid angle to lower (lower override bigger). So begging by sky
|
|
// TODO: Change the way it is done by reversing the order, from smaller solid angle to bigger, so we can early out when the weight is 1.
|
|
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
|
|
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
|
|
|
|
// Only apply sky IBL if the sky texture is available.
|
|
if (_EnvLightSkyEnabled)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
float2 weight;
|
|
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
|
|
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
|
|
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
|
|
EvaluateBSDF_Env(context, V, posInput, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
|
|
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
|
|
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
|
|
}
|
|
|
|
for (i = 0; i < _EnvLightCount; ++i)
|
|
{
|
|
float3 localDiffuseLighting, localSpecularLighting;
|
|
float2 weight;
|
|
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
|
|
EvaluateBSDF_Env(context, V, posInput, prelightData, _EnvLightDatas[i], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
|
|
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
|
|
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
|
|
}
|
|
|
|
diffuseLighting += iblDiffuseLighting;
|
|
specularLighting += iblSpecularLighting;
|
|
|
|
// Add indirect diffuse + emissive (if any)
|
|
diffuseLighting += bakeDiffuseLighting;
|
|
}
|
|
|
|
#endif
|