浏览代码

Better dominant light detection algorithm

/main
Antoine Lelievre 6 年前
当前提交
013fb07a
共有 7 个文件被更改,包括 118 次插入58 次删除
  1. 4
      com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs
  2. 44
      com.unity.render-pipelines.high-definition/HDRP/Lighting/DeferredDirectionalShadow.compute
  3. 2
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightDefinition.cs
  4. 5
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightDefinition.cs.hlsl
  5. 4
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightEvaluation.hlsl
  6. 114
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoop.cs
  7. 3
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDStringConstants.cs

4
com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs


if (settings.isBakedOrMixed)
DrawBakedShadowParameters();
EditorGUILayout.PropertyField(m_AdditionalShadowData.contactShadows, s_Styles.contactShadows);
// There is currently no additional settings for shadow on directional light
if (m_AdditionalLightData.showAdditionalSettings.boolValue)
{

EditorGUILayout.PropertyField(m_AdditionalShadowData.contactShadows, s_Styles.contactShadows);
if (settings.lightType.enumValueIndex != (int)LightType.Directional)
{

44
com.unity.render-pipelines.high-definition/HDRP/Lighting/DeferredDirectionalShadow.compute


// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel DeferredDirectionalShadow DEFERRED_DIRECTIONAL=DeferredDirectionalShadow
#pragma kernel DeferredDirectionalShadow_Contact DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Contact ENABLE_CONTACT_SHADOWS
#pragma kernel DeferredContactShadow
#ifdef SHADER_API_PSSL
# pragma argument( scheduler=minpressure ) // instruct the shader compiler to prefer minimizing vgpr usage

#include "Lighting.hlsl"
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch
#pragma enable_d3d11_debug_symbol
float3 _LightDirection;
float4 _DirectionalLightDirection;
float4 _PunctualLightPosition;
float4 _ScreenSpaceShadowsParameters;
int _SampleCount;
CBUFFER_END

return occluded;
}
float ComputeContactShadow(PositionInputs posInput)
float ComputeContactShadow(PositionInputs posInput, float3 direction)
float contactShadow = 0.0;
float contactShadow = 1.0;
float4 result = ScreenSpaceShadowRayCast(posInput.positionWS, normalize(_LightDirection - posInput.positionWS), _ContactShadowLength * max(0.5, posInput.linearDepth * _ContactShadowDistanceScaleFactor));
float4 result = ScreenSpaceShadowRayCast(posInput.positionWS, direction, _ContactShadowLength * max(0.5, posInput.linearDepth * _ContactShadowDistanceScaleFactor));
contactShadow = 1.0 - result.x * saturate((_ContactShadowFadeEnd - posInput.linearDepth) * _ContactShadowFadeOneOverRange);
}

{
uint2 pixelCoord = groupId * DEFERRED_SHADOW_TILE_SIZE + groupThreadId;
uint2 tileCoord = groupId;
float contactShadow = 0.0;
float contactShadow = 1.0;
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, pixelCoord.xy).x;

PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, tileCoord);
//Direction got from either the directional light direction or the difference of punctual light position and the pixel position
float3 direction = normalize(_DirectionalLightDirection.xyz * _DirectionalLightDirection.w + (_PunctualLightPosition.xyz - posInput.positionWS) * _PunctualLightPosition.w);
NormalData normalData;
DecodeFromNormalBuffer(posInput.positionSS, normalData);

float shadow = GetDirectionalShadowAttenuation(shadowContext, posInput.positionWS, normalWS, _DirectionalShadowIndex, _LightDirection);
float shadow = GetDirectionalShadowAttenuation(shadowContext, posInput.positionWS, normalWS, _DirectionalShadowIndex, _DirectionalLightDirection.xyz);
contactShadow = ComputeContactShadow(posInput);
shadow *= contactShadow;
contactShadow = ComputeContactShadow(posInput, direction);
}
[numthreads(DEFERRED_SHADOW_TILE_SIZE, DEFERRED_SHADOW_TILE_SIZE, 1)]
void DeferredContactShadow(uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID)
{
uint2 pixelCoord = groupId * DEFERRED_SHADOW_TILE_SIZE + groupThreadId;
uint2 tileCoord = groupId;
float contactShadow = 1.0;
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, pixelCoord.xy).x;
if (depth == UNITY_RAW_FAR_CLIP_VALUE)
return;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, tileCoord);
float3 direction = normalize(_PunctualLightPosition.xyz - posInput.positionWS);
contactShadow = ComputeContactShadow(posInput, direction);
_DeferredShadowTextureUAV[pixelCoord] = float4(0.0, contactShadow, 0.0, 0.0);
}

2
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightDefinition.cs


public Vector3 color;
public int shadowIndex; // -1 if unused
public int contactShadowIndex; // -1 if unused
public Vector3 forward;
public int cookieIndex; // -1 if unused

5
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightDefinition.cs.hlsl


int tileCookie;
float3 color;
int shadowIndex;
int contactShadowIndex;
float3 forward;
int cookieIndex;
float3 right;

int GetShadowIndex(DirectionalLightData value)
{
return value.shadowIndex;
}
int GetContactShadowIndex(DirectionalLightData value)
{
return value.contactShadowIndex;
}
float3 GetForward(DirectionalLightData value)
{

4
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightEvaluation.hlsl


float3 positionWS = posInput.positionWS;
float shadow = 1.0;
float shadowMask = 1.0;
float4 shadowData = float4(1, 1, 1, 1);
color = lightData.color;
attenuation = 1.0; // Note: no volumetric attenuation along shadow rays for directional lights

#else
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, N, lightData.shadowIndex, L, posInput.positionSS);
#endif
float contactShadow = GetContactShadow(lightLoopContext, lightData.contactShadowIndex);
shadow = min(shadow, contactShadow);
#ifdef SHADOWS_SHADOWMASK

114
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoop.cs


static int s_deferredDirectionalShadowKernel;
static int s_deferredDirectionalShadow_Contact_Kernel;
static int s_deferredContactShadowKernel;
static ComputeBuffer s_LightVolumeDataBuffer = null;
static ComputeBuffer s_ConvexBoundsBuffer = null;

FrameSettings m_FrameSettings = null;
RenderPipelineResources m_Resources = null;
ContactShadows m_ContactShadows = null;
bool m_EnableContactShadow = false;
// Following is an array of material of size eight for all combination of keyword: OUTPUT_SPLIT_LIGHTING - LIGHTLOOP_TILE_PASS - SHADOWS_SHADOWMASK - USE_FPTL_LIGHTLIST/USE_CLUSTERED_LIGHTLIST - DEBUG_DISPLAY
Material[] m_deferredLightingMaterial;
Material m_DebugViewTilesMaterial;

Light m_CurrentSunLight;
int m_CurrentSunLightShadowIndex = -1;
LightData m_DominantLightData;
bool m_CurrentSunLightContactShadow = false;
float m_DominantLightValue;
LightData m_DominantLightData;
public Light GetCurrentSunLight() { return m_CurrentSunLight; }

s_deferredDirectionalShadowKernel = deferredDirectionalShadowComputeShader.FindKernel("DeferredDirectionalShadow");
s_deferredDirectionalShadow_Contact_Kernel = deferredDirectionalShadowComputeShader.FindKernel("DeferredDirectionalShadow_Contact");
s_deferredContactShadowKernel = deferredDirectionalShadowComputeShader.FindKernel("DeferredContactShadow");
for (int variant = 0; variant < LightDefinitions.s_NumFeatureVariants; variant++)
{

public void NewFrame(FrameSettings frameSettings)
{
m_FrameSettings = frameSettings;
m_ContactShadows = VolumeManager.instance.stack.GetComponent<ContactShadows>();
m_EnableContactShadow = m_FrameSettings.enableContactShadows && m_ContactShadows.enable && m_ContactShadows.length > 0;
// Cluster
{

return new Vector3(light.finalColor.r, light.finalColor.g, light.finalColor.b);
}
bool GetDominantLightWithShadows(AdditionalShadowData additionalShadowData, VisibleLight light, int lightIndex = -1)
{
float lightDominanceValue = light.screenRect.size.magnitude * light.light.intensity;
if (additionalShadowData == null || !additionalShadowData.contactShadows || light.light.shadows == LightShadows.None)
return false;
if (lightDominanceValue <= m_DominantLightValue || m_DominantLightValue == Single.PositiveInfinity)
return false;
if (light.lightType == LightType.Directional)
m_DominantLightValue = Single.PositiveInfinity;
else
{
m_DominantLightData = m_lightList.lights[lightIndex];
m_DominantLightIndex = lightIndex;
m_DominantLightValue = lightDominanceValue;
}
return true;
}
public bool GetDirectionalLightData(CommandBuffer cmd, ShadowSettings shadowSettings, GPULightType gpuLightType, VisibleLight light, HDAdditionalLightData additionalData, AdditionalShadowData additionalShadowData, int lightIndex)
{
var directionalLightData = new DirectionalLightData();

if (diffuseDimmer <= 0.0f && specularDimmer <= 0.0f)
return false;
// Light direction for directional is opposite to the forward direction
directionalLightData.forward = light.light.transform.forward;
// Rescale for cookies and windowing.

// Fallback to the first non shadow casting directional light.
m_CurrentSunLight = m_CurrentSunLight == null ? light.light : m_CurrentSunLight;
directionalLightData.contactShadowIndex = m_EnableContactShadow ? 1 : -1;
if (GetDominantLightWithShadows(additionalShadowData, light))
directionalLightData.contactShadowIndex = 0;
m_lightList.directionalLights.Add(directionalLightData);
return true;

int lightIndex, ref Vector3 lightDimensions)
{
var lightData = new LightData();
ContactShadows contactShadows = VolumeManager.instance.stack.GetComponent<ContactShadows>();
bool enableContactShadows = m_FrameSettings.enableContactShadows && contactShadows.enable && contactShadows.length > 0.0f;
lightData.contactShadowIndex = enableContactShadows ? 1 : -1;
lightData.positionWS = light.light.transform.position;
// Setting 0 for invSqrAttenuationRadius mean we have no range attenuation, but still have inverse square attenuation.

lightData.shadowMaskSelector.x = -1.0f;
lightData.nonLightmappedOnly = 0;
}
lightData.contactShadowIndex = m_EnableContactShadow ? 1 : -1;
GetDominantLightWithShadows(additionalshadowData, light, m_lightList.lights.Count -1);
return true;
}

m_CurrentSunLight = null;
m_CurrentSunLightShadowIndex = -1;
m_DominantLightIndex = -1;
m_CurrentSunLightContactShadow = false;
m_DominantLightValue = 0;
var stereoEnabled = m_FrameSettings.enableStereo;

var sortKeys = new uint[lightCount];
int sortCount = 0;
float biggestLight = 0;
int dominantLightDataIndex = 0;
for (int lightIndex = 0, numLights = cullResults.visibleLights.Count; (lightIndex < numLights) && (sortCount < lightCount); ++lightIndex)
{
var light = cullResults.visibleLights[lightIndex];

// to allow the preceding code to work with the absolute world space coordinates.
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
// Caution: 'DirectionalLightData.positionWS' is camera-relative after this point.
// Caution: 'DirectionalLightData.positionWS' is camera-relative after this point.
if (additionalShadowData != null && additionalShadowData.contactShadows)
{
biggestLight = Single.PositiveInfinity;
m_CurrentSunLightContactShadow = true;
}
}
continue;
}

// Punctual, area, projector lights - the rendering side.
if (GetLightData(cmd, shadowSettings, camera, gpuLightType, light, additionalLightData, additionalShadowData, lightIndex, ref lightDimensions))
{
int last = m_lightList.lights.Count - 1;
switch (lightCategory)
{
case LightCategory.Punctual:

// to allow the preceding code to work with the absolute world space coordinates.
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
int last = m_lightList.lights.Count - 1;
if (additionalShadowData != null && additionalShadowData.contactShadows && lightDimensions.magnitude > biggestLight)
{
m_DominantLightData = m_lightList.lights[m_lightList.lights.Count - 1];
m_DominantLightIndex = lightIndex;
dominantLightDataIndex = last;
biggestLight = lightDimensions.magnitude;
}
}
}

m_DominantLightData = m_lightList.lights[m_DominantLightIndex];
m_lightList.lights[dominantLightDataIndex] = m_DominantLightData;
m_lightList.lights[m_DominantLightIndex] = m_DominantLightData;
}
// Sanity check

public void RenderDeferredDirectionalShadow(HDCamera hdCamera, RTHandleSystem.RTHandle deferredShadowRT, RenderTargetIdentifier depthTexture, CommandBuffer cmd)
{
if ((m_CurrentSunLight == null || m_CurrentSunLight.GetComponent<AdditionalShadowData>() == null || m_CurrentSunLightShadowIndex < 0) && m_DominantLightIndex == -1)
bool sunLightShadow = m_CurrentSunLight != null && m_CurrentSunLight.GetComponent<AdditionalShadowData>() != null && m_CurrentSunLightShadowIndex >= 0;
if (!sunLightShadow && m_DominantLightIndex == -1)
{
cmd.SetGlobalTexture(HDShaderIDs._DeferredShadowTexture, RuntimeUtilities.whiteTexture);
return;

{
ContactShadows contactShadows = VolumeManager.instance.stack.GetComponent<ContactShadows>();
bool enableContactShadows = m_FrameSettings.enableContactShadows && contactShadows.enable && contactShadows.length > 0.0f;
Vector4 lightDirection;
Vector4 lightDirection = Vector4.zero;
Vector4 lightPosition = Vector4.zero;
if (enableContactShadows && (m_DominantLightIndex != -1 || m_CurrentSunLightContactShadow))
kernel = s_deferredDirectionalShadow_Contact_Kernel;
if (m_EnableContactShadow)
{
if (sunLightShadow)
kernel = s_deferredDirectionalShadow_Contact_Kernel;
else
kernel = s_deferredContactShadowKernel;
}
if (m_DominantLightIndex == -1 && m_CurrentSunLight != null)
if (m_CurrentSunLight != null)
lightDirection.w = 0;
lightDirection.w = 1;
else
if (m_DominantLightIndex != -1)
lightDirection = m_DominantLightData.positionWS;
lightDirection.w = 1;
lightPosition = m_DominantLightData.positionWS;
lightPosition.w = 1;
lightDirection.w = 0;
if (enableContactShadows)
if (m_ContactShadows)
float contactShadowRange = Mathf.Clamp(contactShadows.fadeDistance, 0.0f, contactShadows.maxDistance);
float contactShadowFadeEnd = contactShadows.maxDistance;
float contactShadowRange = Mathf.Clamp(m_ContactShadows.fadeDistance, 0.0f, m_ContactShadows.maxDistance);
float contactShadowFadeEnd = m_ContactShadows.maxDistance;
Vector4 contactShadowParams = new Vector4(contactShadows.length, contactShadows.distanceScaleFactor, contactShadowFadeEnd, contactShadowOneOverFadeRange);
Vector4 contactShadowParams = new Vector4(m_ContactShadows.length, m_ContactShadows.distanceScaleFactor, contactShadowFadeEnd, contactShadowOneOverFadeRange);
cmd.SetComputeIntParam(deferredDirectionalShadowComputeShader, HDShaderIDs._DirectionalContactShadowSampleCount, contactShadows.sampleCount);
cmd.SetComputeIntParam(deferredDirectionalShadowComputeShader, HDShaderIDs._DirectionalContactShadowSampleCount, m_ContactShadows.sampleCount);
cmd.SetComputeVectorParam(deferredDirectionalShadowComputeShader, HDShaderIDs._PunctualLightPosition, lightPosition);
cmd.SetComputeTextureParam(deferredDirectionalShadowComputeShader, kernel, HDShaderIDs._DeferredShadowTextureUAV, deferredShadowRT);
cmd.SetComputeTextureParam(deferredDirectionalShadowComputeShader, kernel, HDShaderIDs._CameraDepthTexture, depthTexture);

3
com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDStringConstants.cs


public static readonly int _DirectionalShadowIndex = Shader.PropertyToID("_DirectionalShadowIndex");
public static readonly int _DirectionalContactShadowParams = Shader.PropertyToID("_ScreenSpaceShadowsParameters");
public static readonly int _DirectionalContactShadowSampleCount = Shader.PropertyToID("_SampleCount");
public static readonly int _DirectionalLightDirection = Shader.PropertyToID("_LightDirection");
public static readonly int _DirectionalLightDirection = Shader.PropertyToID("_DirectionalLightDirection");
public static readonly int _PunctualLightPosition = Shader.PropertyToID("_PunctualLightPosition");
public static readonly int _StencilMask = Shader.PropertyToID("_StencilMask");
public static readonly int _StencilRef = Shader.PropertyToID("_StencilRef");

正在加载...
取消
保存