浏览代码

Merge projector lights into punctual lights

/RenderPassXR_Sandbox
Evgenii Golubev 7 年前
当前提交
4a9e84ed
共有 9 个文件被更改,包括 427 次插入571 次删除
  1. 2
      Assets/ScriptableRenderPipeline/Fptl/LightDefinitions.cs.hlsl
  2. 64
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs
  3. 176
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl
  4. 79
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  5. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl
  6. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl
  7. 43
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  8. 218
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  9. 404
      Assets/Textures/Batman.png

2
Assets/ScriptableRenderPipeline/Fptl/LightDefinitions.cs.hlsl


//
// This file was automatically generated from Assets/ScriptableRenderPipeline/fptl/LightDefinitions.cs. Please don't edit by hand.
// This file was automatically generated from Assets/ScriptableRenderPipeline/Fptl/LightDefinitions.cs. Please don't edit by hand.
//
#ifndef LIGHTDEFINITIONS_CS_HLSL

64
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs


public enum GPULightType
{
Directional,
ProjectorBox,
ProjectorOrtho,
ProjectorPyramid,
// AreaLight

// These structures share between C# and hlsl need to be align on float4, so we pad them.
[GenerateHLSL]
public struct LightData
public struct DirectionalLightData
public float invSqrAttenuationRadius;
public float unused;
public float angleScale; // Spot light
public int shadowIndex; // -1 if unused
public float angleOffset; // Spot light
public Vector3 up;
public float diffuseScale;
public int cookieIndex; // -1 if unused
public Vector3 right;
public Vector3 right; // Rescaled by (2 / lightLength)
public float shadowDimmer;
// index are -1 if not used
public int shadowIndex;
public int IESIndex;
public int cookieIndex;
public Vector2 size; // Used by area, projector and spot lights; x = cot(outerHalfAngle) for spot lights
public GPULightType lightType;
public float unused;
public Vector3 up; // Rescaled by (2 / lightWidth)
public float diffuseScale;
public struct DirectionalLightData
public struct LightData
public Vector3 forward;
public float diffuseScale;
public Vector3 up;
public float invScaleY;
public Vector3 right;
public float invScaleX;
// DirectionalLightData >>>
public bool tileCookie;
public float invSqrAttenuationRadius;
public float specularScale;
// Sun disc size
public float cosAngle; // Distance to the disk
public float sinAngle; // Disk radius
public Vector3 forward;
public Vector3 right; // If spot: rescaled by cot(outerHalfAngle); if projector: rescaled by (2 / lightLength)
public float specularScale;
public Vector3 up; // If spot: rescaled by cot(outerHalfAngle); if projector: rescaled by * (2 / lightWidth)
public float diffuseScale;
// <<< DirectionalLightData
public float angleScale; // Spot light
public float angleOffset; // Spot light
public float shadowDimmer;
public int IESIndex; // -1 if unused
public Vector2 size; // Used by area, frustum projector and spot lights (x = cot(outerHalfAngle))
public GPULightType lightType;
public float unused;
[GenerateHLSL]

176
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl


// UnityEngine.Experimental.Rendering.HDPipeline.GPULightType: static fields
//
#define GPULIGHTTYPE_DIRECTIONAL (0)
#define GPULIGHTTYPE_SPOT (1)
#define GPULIGHTTYPE_POINT (2)
#define GPULIGHTTYPE_PROJECTOR_ORTHO (3)
#define GPULIGHTTYPE_PROJECTOR_BOX (1)
#define GPULIGHTTYPE_SPOT (2)
#define GPULIGHTTYPE_POINT (3)
#define GPULIGHTTYPE_PROJECTOR_PYRAMID (4)
#define GPULIGHTTYPE_RECTANGLE (5)
#define GPULIGHTTYPE_LINE (6)

#define STENCILLIGHTINGUSAGE_SPLIT_LIGHTING (1)
#define STENCILLIGHTINGUSAGE_REGULAR_LIGHTING (2)
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.LightData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.DirectionalLightData
struct LightData
struct DirectionalLightData
float invSqrAttenuationRadius;
float unused;
float angleScale;
int shadowIndex;
float angleOffset;
float3 up;
float diffuseScale;
int cookieIndex;
float shadowDimmer;
int shadowIndex;
int IESIndex;
int cookieIndex;
float2 size;
int lightType;
float unused;
float3 up;
float diffuseScale;
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.DirectionalLightData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.LightData
struct DirectionalLightData
struct LightData
float3 forward;
float diffuseScale;
float3 up;
float invScaleY;
float3 right;
float invScaleX;
bool tileCookie;
float invSqrAttenuationRadius;
float specularScale;
float cosAngle;
float sinAngle;
float3 forward;
float3 right;
float specularScale;
float3 up;
float diffuseScale;
float angleScale;
float angleOffset;
float shadowDimmer;
int IESIndex;
float2 size;
int lightType;
float unused;
};
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.EnvLightData

};
//
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.LightData
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.DirectionalLightData
float3 GetPositionWS(LightData value)
float3 GetPositionWS(DirectionalLightData value)
float GetInvSqrAttenuationRadius(LightData value)
float GetUnused(DirectionalLightData value)
return value.invSqrAttenuationRadius;
return value.unused;
float3 GetColor(LightData value)
float3 GetColor(DirectionalLightData value)
float GetAngleScale(LightData value)
int GetShadowIndex(DirectionalLightData value)
return value.angleScale;
return value.shadowIndex;
float3 GetForward(LightData value)
float3 GetForward(DirectionalLightData value)
float GetAngleOffset(LightData value)
{
return value.angleOffset;
}
float3 GetUp(LightData value)
{
return value.up;
}
float GetDiffuseScale(LightData value)
int GetCookieIndex(DirectionalLightData value)
return value.diffuseScale;
return value.cookieIndex;
float3 GetRight(LightData value)
float3 GetRight(DirectionalLightData value)
float GetSpecularScale(LightData value)
float GetSpecularScale(DirectionalLightData value)
float GetShadowDimmer(LightData value)
{
return value.shadowDimmer;
}
int GetShadowIndex(LightData value)
float3 GetUp(DirectionalLightData value)
return value.shadowIndex;
return value.up;
int GetIESIndex(LightData value)
float GetDiffuseScale(DirectionalLightData value)
return value.IESIndex;
return value.diffuseScale;
int GetCookieIndex(LightData value)
//
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.LightData
//
float3 GetPositionWS(LightData value)
return value.cookieIndex;
return value.positionWS;
float2 GetSize(LightData value)
float GetInvSqrAttenuationRadius(LightData value)
return value.size;
return value.invSqrAttenuationRadius;
int GetLightType(LightData value)
float3 GetColor(LightData value)
return value.lightType;
return value.color;
float GetUnused(LightData value)
int GetShadowIndex(LightData value)
return value.unused;
return value.shadowIndex;
//
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.DirectionalLightData
//
float3 GetForward(DirectionalLightData value)
float3 GetForward(LightData value)
float GetDiffuseScale(DirectionalLightData value)
int GetCookieIndex(LightData value)
return value.diffuseScale;
}
float3 GetUp(DirectionalLightData value)
{
return value.up;
return value.cookieIndex;
float GetInvScaleY(DirectionalLightData value)
float3 GetRight(LightData value)
return value.invScaleY;
return value.right;
float3 GetRight(DirectionalLightData value)
float GetSpecularScale(LightData value)
return value.right;
return value.specularScale;
float GetInvScaleX(DirectionalLightData value)
float3 GetUp(LightData value)
return value.invScaleX;
return value.up;
float3 GetPositionWS(DirectionalLightData value)
float GetDiffuseScale(LightData value)
return value.positionWS;
return value.diffuseScale;
bool GetTileCookie(DirectionalLightData value)
float GetAngleScale(LightData value)
return value.tileCookie;
return value.angleScale;
float3 GetColor(DirectionalLightData value)
float GetAngleOffset(LightData value)
return value.color;
return value.angleOffset;
float GetSpecularScale(DirectionalLightData value)
float GetShadowDimmer(LightData value)
return value.specularScale;
return value.shadowDimmer;
float GetCosAngle(DirectionalLightData value)
int GetIESIndex(LightData value)
return value.cosAngle;
return value.IESIndex;
float GetSinAngle(DirectionalLightData value)
float2 GetSize(LightData value)
return value.sinAngle;
return value.size;
int GetShadowIndex(DirectionalLightData value)
int GetLightType(LightData value)
return value.shadowIndex;
return value.lightType;
int GetCookieIndex(DirectionalLightData value)
float GetUnused(LightData value)
return value.cookieIndex;
return value.unused;
}
//

79
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


{
Punctual,
Area,
Projector,
Env,
Count
}

Punctual = 1 << 0,
Area = 1 << 1,
Directional = 1 << 2,
Projector = 1 << 3,
Env = 1 << 4,
Sky = 1 << 5
Env = 1 << 3,
Sky = 1 << 4
}
[GenerateHLSL]

public const int k_MaxDirectionalLightsOnScreen = 4;
public const int k_MaxPunctualLightsOnScreen = 512;
public const int k_MaxAreaLightsOnScreen = 64;
public const int k_MaxProjectorLightsOnScreen = 64;
public const int k_MaxLightsOnScreen = k_MaxDirectionalLightsOnScreen + k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnScreen + k_MaxProjectorLightsOnScreen;
public const int k_MaxLightsOnScreen = k_MaxDirectionalLightsOnScreen + k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnScreen;
public const int k_MaxEnvLightsOnScreen = 64;
public const int k_MaxShadowOnScreen = 16;
public const int k_MaxCascadeCount = 4; //Should be not less than m_Settings.directionalLightCascadeCount;

LightList m_lightList;
int m_punctualLightCount = 0;
int m_areaLightCount = 0;
int m_projectorLightCount = 0;
int m_lightCount = 0;
private ComputeShader buildScreenAABBShader { get { return m_Resources.buildScreenAABBShader; } }

m_lightList.Allocate();
s_DirectionalLightDatas = new ComputeBuffer(k_MaxDirectionalLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DirectionalLightData)));
s_LightDatas = new ComputeBuffer(k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnScreen + k_MaxProjectorLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightData)));
s_LightDatas = new ComputeBuffer(k_MaxPunctualLightsOnScreen + k_MaxAreaLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightData)));
s_EnvLightDatas = new ComputeBuffer(k_MaxEnvLightsOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(EnvLightData)));
s_shadowDatas = new ComputeBuffer(k_MaxCascadeCount + k_MaxShadowOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(ShadowData)));

// Light direction for directional is opposite to the forward direction
directionalLightData.forward = light.light.transform.forward;
directionalLightData.up = light.light.transform.up;
directionalLightData.right = light.light.transform.right;
// Rescale for cookies and windowing.
directionalLightData.up = light.light.transform.up * 2 / additionalData.lightWidth;
directionalLightData.right = light.light.transform.right * 2 / additionalData.lightLength;
directionalLightData.invScaleX = 1.0f / light.light.transform.localScale.x;
directionalLightData.invScaleY = 1.0f / light.light.transform.localScale.y;
directionalLightData.cosAngle = 0.0f;
directionalLightData.sinAngle = 0.0f;
directionalLightData.shadowIndex = -1;
directionalLightData.cookieIndex = -1;
directionalLightData.shadowIndex = directionalLightData.cookieIndex = -1;
directionalLightData.tileCookie = (light.light.cookie.wrapMode == TextureWrapMode.Repeat);
directionalLightData.cookieIndex = m_CookieTexArray.FetchSlice(light.light.cookie);
}
// fix up shadow information

lightData.up = light.light.transform.up;
lightData.right = light.light.transform.right;
if (lightData.lightType == GPULightType.ProjectorBox || lightData.lightType == GPULightType.ProjectorPyramid)
{
// Rescale for cookies and windowing.
lightData.up *= 2 / additionalLightData.lightWidth;
lightData.right *= 2 / additionalLightData.lightLength;
}
if (lightData.lightType == GPULightType.Spot)
{
var spotAngle = light.spotAngle;

lightData.angleScale = 1.0f / val;
lightData.angleOffset = -cosSpotOuterHalfAngle * lightData.angleScale;
// TODO: Currently the spot cookie code use the cotangent, either we fix the spot cookie code to not use cotangent
// or we clean the name here, store it in size.x for now
lightData.size.x = cosSpotOuterHalfAngle / sinSpotOuterHalfAngle;
// Rescale for cookies and windowing.
float cotOuterHalfAngle = cosSpotOuterHalfAngle / sinSpotOuterHalfAngle;
lightData.up *= cotOuterHalfAngle;
lightData.right *= cotOuterHalfAngle;
// 1.0f, 2.0f are neutral value allowing GetAngleAnttenuation in shader code to return 1.0
lightData.angleScale = 1.0f;
lightData.angleOffset = 2.0f;
// These are the neutral values allowing GetAngleAnttenuation in shader code to return 1.0
lightData.angleScale = 0.0f;
lightData.angleOffset = 1.0f;
}
float distanceToCamera = (lightData.positionWS - camera.transform.position).magnitude;

lightVolumeData.lightPos = worldToView.MultiplyPoint(lightPos);
lightVolumeData.radiusSq = range * range;
lightVolumeData.cotan = cota;
lightVolumeData.featureFlags = (gpuLightType == GPULightType.Spot) ? (uint)LightFeatureFlags.Punctual
: (uint)LightFeatureFlags.Projector;
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Punctual;
}
else if (gpuLightType == GPULightType.Point)
{

lightVolumeData.boxInvRange.Set(1.0f / radius, 1.0f / radius, 1.0f / radius);
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Area;
}
else if (gpuLightType == GPULightType.ProjectorOrtho)
else if (gpuLightType == GPULightType.ProjectorBox)
Vector3 xAxisVS = worldToView.MultiplyVector(lightData.right);
Vector3 yAxisVS = worldToView.MultiplyVector(lightData.up);
Vector3 xAxisVS = worldToView.MultiplyVector(lightData.right.normalized); // Undo scaling
Vector3 yAxisVS = worldToView.MultiplyVector(lightData.up.normalized); // Undo scaling
Vector3 zAxisVS = worldToView.MultiplyVector(lightData.forward);
// Projector lights point forwards (along Z). The projection window is aligned with the XY plane.

lightVolumeData.lightAxisZ = zAxisVS;
lightVolumeData.boxInnerDist = halfDims; // No idea what this is. Document your code
lightVolumeData.boxInvRange.Set(1.0f / halfDims.x, 1.0f / halfDims.y, 1.0f / halfDims.z); // No idea what this is. Document your code
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Projector;
lightVolumeData.featureFlags = (uint)LightFeatureFlags.Punctual;
}
else
{

int directionalLightcount = 0;
int punctualLightcount = 0;
int areaLightCount = 0;
int projectorLightCount = 0;
int lightCount = Math.Min(cullResults.visibleLights.Count, k_MaxLightsOnScreen);
var sortKeys = new uint[lightCount];

// Note: LightType.Area is offline only, use for baking, no need to test it
if (additionalData.archetype == LightArchetype.Punctual)
{
lightCategory = LightCategory.Punctual;
lightCategory = LightCategory.Punctual;
gpuLightType = GPULightType.Point;
lightVolumeType = LightVolumeType.Sphere;
break;

continue;
lightCategory = LightCategory.Punctual;
gpuLightType = GPULightType.Spot;
lightVolumeType = LightVolumeType.Cone;
break;

continue;
lightCategory = LightCategory.Punctual;
gpuLightType = GPULightType.Directional;
// No need to add volume, always visible
lightVolumeType = LightVolumeType.Count; // Count is none

lightVolumeType = LightVolumeType.Box;
break;
case LightArchetype.Projector:
if (projectorLightCount >= k_MaxProjectorLightsOnScreen) { continue; }
lightCategory = LightCategory.Projector;
if (punctualLightcount >= k_MaxPunctualLightsOnScreen) { continue; }
lightCategory = LightCategory.Punctual;
gpuLightType = GPULightType.ProjectorOrtho;
gpuLightType = GPULightType.ProjectorBox;
lightVolumeType = LightVolumeType.Box;
break;
case LightType.Spot:

}
continue;
}
// Punctual, area, projector lights - the rendering side.
if (GetLightData(shadowSettings, camera, gpuLightType, light, additionalLightData, additionalShadowData, lightIndex))
{

break;
case LightCategory.Area:
areaLightCount++;
break;
case LightCategory.Projector:
projectorLightCount++;
break;
default:
Debug.Assert(false, "TODO: encountered an unknown LightCategory.");

// Sanity check
Debug.Assert(m_lightList.directionalLights.Count == directionalLightcount);
Debug.Assert(m_lightList.lights.Count == areaLightCount + punctualLightcount + projectorLightCount);
Debug.Assert(m_lightList.lights.Count == areaLightCount + punctualLightcount);
m_punctualLightCount = punctualLightcount;
m_areaLightCount = areaLightCount;
m_projectorLightCount = projectorLightCount;
m_punctualLightCount = punctualLightcount;
m_areaLightCount = areaLightCount;
// Redo everything but this time with envLights
int envLightCount = 0;

SetGlobalBuffer("_LightDatas", s_LightDatas);
SetGlobalInt("_PunctualLightCount", m_punctualLightCount);
SetGlobalInt("_AreaLightCount", m_areaLightCount);
SetGlobalInt("_ProjectorLightCount", m_projectorLightCount);
SetGlobalBuffer("_EnvLightDatas", s_EnvLightDatas);
SetGlobalInt("_EnvLightCount", m_lightList.envLights.Count);
SetGlobalBuffer("_ShadowDatas", s_shadowDatas);

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl


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

#define LIGHTFEATUREFLAGS_DIRECTIONAL (4)
#define LIGHTFEATUREFLAGS_PROJECTOR (8)
#define LIGHTFEATUREFLAGS_ENV (16)
#define LIGHTFEATUREFLAGS_SKY (32)
#define LIGHTFEATUREFLAGS_ENV (8)
#define LIGHTFEATUREFLAGS_SKY (16)
//
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightDefinitions: static fields

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl


#define PROCESS_DIRECTIONAL_LIGHT
#define PROCESS_PUNCTUAL_LIGHT
#define PROCESS_AREA_LIGHT
#define PROCESS_PROJECTOR_LIGHT
#endif
#if defined (LIGHTLOOP_TILE_INDIRECT) || defined(LIGHTLOOP_TILE_ALL)

uint _DirectionalLightCount;
uint _PunctualLightCount;
uint _AreaLightCount;
uint _ProjectorLightCount;
uint _EnvLightCount;
float4 _DirShadowSplitSpheres[4]; // TODO: share this max between C# and hlsl

43
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional( context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Directional(context, V, posInput, prelightData,
GPULIGHTTYPE_DIRECTIONAL, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;

}
#endif
#ifdef PROCESS_PROJECTOR_LIGHT
if(featureFlags & LIGHTFEATUREFLAGS_PROJECTOR)
{
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
uint projectorLightStart;
uint projectorLightCount;
GetCountAndStart(posInput, LIGHTCATEGORY_PROJECTOR, projectorLightStart, projectorLightCount);
for(i = 0; i < projectorLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
uint projectorIndex = FetchIndex(projectorLightStart, i);
EvaluateBSDF_Projector(context, V, posInput, prelightData, _LightDatas[projectorIndex], 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);

{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional( context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Directional(context, V, posInput, prelightData,
GPULIGHTTYPE_DIRECTIONAL, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;

EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
for (; i < _PunctualLightCount + _AreaLightCount + _ProjectorLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Projector( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;

218
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


// EvaluateBSDF_Directional
//-----------------------------------------------------------------------------
void EvaluateBSDF_Directional( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData, DirectionalLightData lightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
void EvaluateBSDF_Directional(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
int lightType, DirectionalLightData lightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane.
float3 lightToSurface = positionWS - lightData.positionWS;
float2 positionNDC = float2(dot(lightToSurface, lightData.right), dot(lightToSurface, lightData.up));
bool isInBounds = abs(positionNDC.x) <= 1 && abs(positionNDC.y) <= 1;
// Clip only box projector lights.
float clipFactor = (lightType != GPULIGHTTYPE_PROJECTOR_BOX || isInBounds) ? 1 : 0;
float attenuation = clipFactor;
float illuminance = saturate(NdotL);
float illuminance = saturate(NdotL * attenuation);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float4 cookie = float4(1.0, 1.0, 1.0, 1.0);
diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
float3 cookie = float3(1, 1, 1);
float shadow = 1;
[branch] if (lightData.shadowIndex >= 0)

[branch] if (lightData.cookieIndex >= 0)
{
float3 lightToSurface = positionWS - lightData.positionWS;
// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2.
float2 coord = positionNDC * 0.5 + 0.5;
// Project 'lightToSurface' onto the light's axes.
float2 coord = float2(dot(lightToSurface, lightData.right), dot(lightToSurface, lightData.up));
// Compute the NDC coordinates (in [-1, 1]^2).
coord.x *= lightData.invScaleX;
coord.y *= lightData.invScaleY;
// We let the sampler handle tiling or clamping to border.
// Note: tiling (the repeat mode) is not currently supported.
float4 c = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
if (lightData.tileCookie || (abs(coord.x) <= 1 && abs(coord.y) <= 1))
{
// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2.
coord = coord * 0.5 + 0.5;
// Tile the texture if the 'repeat' wrap mode is enabled.
if (lightData.tileCookie) { coord = frac(coord); }
cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
}
else
{
cookie = float4(0, 0, 0, 0);
}
illuminance *= cookie.a;
// Use premultiplied alpha to save 1x VGPR.
cookie = c.rgb * c.a;
}
[branch] if (illuminance > 0.0)

diffuseLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale);
specularLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.specularScale);
diffuseLighting *= (cookie * lightData.color) * (illuminance * lightData.diffuseScale);
specularLighting *= (cookie * lightData.color) * (illuminance * lightData.specularScale);
}
[branch] if (bsdfData.enableTransmission)

// (we reuse the illumination) with the reversed normal of the current sample.
// We apply wrapped lighting instead of the regular Lambertian diffuse
// to compensate for these approximations.
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT);
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT) * attenuation;
illuminance *= shadow * cookie.a;
illuminance *= shadow;
float3 backLight = (cookie.rgb * lightData.color) * (Lambert() * illuminance * lightData.diffuseScale);
float3 backLight = (cookie * lightData.color) * (Lambert() * illuminance * lightData.diffuseScale);
// TODO: multiplication by 'diffuseColor' and 'transmittance' is the same for each light.
float3 transmittedLight = backLight * (bsdfData.diffuseColor * bsdfData.transmittance);

out float3 specularLighting)
{
float3 positionWS = posInput.positionWS;
int lightType = lightData.lightType;
// Translate and rotate 'positionWS' into the light space.
float3 lightToSurface = positionWS - lightData.positionWS;
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
float3 positionLS = mul(lightToSurface, transpose(lightToWorld));
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the plane at 1m distance.
// Box projector lights require no perspective division.
float2 positionNDC = (lightType != GPULIGHTTYPE_PROJECTOR_BOX && lightType != GPULIGHTTYPE_POINT) ? positionLS.xy / positionLS.z : positionLS.xy;
bool isInBounds = abs(positionNDC.x) <= 1 && abs(positionNDC.y) <= 1;
// Do not clip point lights.
float clipFactor = (lightType == GPULIGHTTYPE_POINT || isInBounds) ? 1 : 0;
// All punctual light type in the same formula, attenuation is neutral depends on light type.
// light.positionWS is the normalize light direction in case of directional light and invSqrAttenuationRadius is 0

float3 unL = lightData.positionWS - positionWS;
float3 L = normalize(unL);
float3 unL = -lightToSurface;
float3 L = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? normalize(unL) : -lightData.forward;
float attenuation = GetDistanceAttenuation(unL, lightData.invSqrAttenuationRadius);
// Reminder: lights are ortiented backward (-Z)
float attenuation = clipFactor;
attenuation *= (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? GetDistanceAttenuation(unL, lightData.invSqrAttenuationRadius) : 1;
// Reminder: lights are oriented backward (-Z)
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float4 cookie = float4(1.0, 1.0, 1.0, 1.0);
diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
float3 cookie = float3(1, 1, 1);
float shadow = 1;
// TODO: measure impact of having all these dynamic branch here and the gain (or not) of testing illuminace > 0

[branch] if (lightData.shadowIndex >= 0)
{
// TODO: make projector lights cast shadows.
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
shadow = lerp(1.0, shadow, lightData.shadowDimmer);

[branch] if (lightData.cookieIndex >= 0)
{
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
// Rotate 'L' into the light space.
// We perform the negation because lights are oriented backwards (-Z).
float3 coord = mul(-L, transpose(lightToWorld));
[branch] if (lightData.lightType == GPULIGHTTYPE_SPOT)
[branch] if (lightType == GPULIGHTTYPE_POINT)
// Perform the perspective projection of the hemisphere onto the disk.
coord.xy /= coord.z;
// Rescale the projective coordinates to fit into the [-1, 1]^2 range.
float cotOuterHalfAngle = lightData.size.x;
coord.xy *= cotOuterHalfAngle;
// Identical to 'positionLS', but saves us 2x VGPR.
float3 coord = float3(positionNDC, positionLS.z);
// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2.
coord.xy = coord.xy * 0.5 + 0.5;
float4 c = SampleCookieCube(lightLoopContext, coord, lightData.cookieIndex);
cookie = SampleCookie2D(lightLoopContext, coord.xy, lightData.cookieIndex);
// Use premultiplied alpha to save 1x VGPR.
cookie = c.rgb * c.a;
else // GPULIGHTTYPE_POINT
else
cookie = SampleCookieCube(lightLoopContext, coord, lightData.cookieIndex);
// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2.
float2 coord = positionNDC * 0.5 + 0.5;
// We let the sampler handle clamping to border.
float4 c = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
// Use premultiplied alpha to save 1x VGPR.
cookie = c.rgb * c.a;
illuminance *= cookie.a;
}
[branch] if (illuminance > 0.0)

// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = bsdfData.useThinObjectMode ? shadow : 1;
illuminance *= shadow * cookie.a;
float3 backLight = (cookie.rgb * lightData.color) * (Lambert() * illuminance * lightData.diffuseScale);
// TODO: multiplication by 'diffuseColor' and 'transmittance' is the same for each light.
float3 transmittedLight = backLight * (bsdfData.diffuseColor * bsdfData.transmittance);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += transmittedLight;
}
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Projector
//-----------------------------------------------------------------------------
void EvaluateBSDF_Projector(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
{
float3 positionWS = posInput.positionWS;
// Translate and rotate 'positionWS' into the light space.
float3 positionLS = mul(positionWS - lightData.positionWS,
transpose(float3x3(lightData.right, lightData.up, lightData.forward)));
if (lightData.lightType == GPULIGHTTYPE_PROJECTOR_PYRAMID)
{
// Perform perspective division.
positionLS *= rcp(positionLS.z);
}
else
{
// For orthographic projection, the Z coordinate plays no role.
positionLS.z = 0;
}
// Compute the NDC position (in [-1, 1]^2). TODO: precompute the inverse?
float2 positionNDC = positionLS.xy * rcp(0.5 * lightData.size);
// Perform clipping.
float clipFactor = ((positionLS.z >= 0) && (abs(positionNDC.x) <= 1 && abs(positionNDC.y) <= 1)) ? 1 : 0;
float3 L = -lightData.forward; // Lights are pointing backward in Unity
float NdotL = dot(bsdfData.normalWS, L);
float illuminance = saturate(NdotL * clipFactor);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float4 cookie = float4(1.0, 1.0, 1.0, 1.0);
float shadow = 1;
[branch] if (lightData.shadowIndex >= 0)
{
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
}
[branch] if (lightData.cookieIndex >= 0)
{
// Compute the texture coordinates in [0, 1]^2.
float2 coord = positionNDC * 0.5 + 0.5;
cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
illuminance *= cookie.a;
}
[branch] if (illuminance > 0.0)
{
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting);
diffuseLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale);
specularLighting *= (cookie.rgb * lightData.color) * (illuminance * lightData.specularScale);
}
[branch] if (bsdfData.enableTransmission)
{
// Currently, we only model diffuse transmission. Specular transmission is not yet supported.
// We assume that the back side of the object is a uniformly illuminated infinite plane
// (we reuse the illumination) with the reversed normal of the current sample.
// We apply wrapped lighting instead of the regular Lambertian diffuse
// to compensate for these approximations.
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT) * clipFactor;
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = bsdfData.useThinObjectMode ? shadow : 1;
illuminance *= shadow * cookie.a;
float3 backLight = (cookie.rgb * lightData.color) * (Lambert() * illuminance * lightData.diffuseScale);
// TODO: multiplication by 'diffuseColor' and 'transmittance' is the same for each light.

404
Assets/Textures/Batman.png

之前 之后
宽度: 512  |  高度: 512  |  大小: 49 KiB
正在加载...
取消
保存