Skip to content

Commit 732a8d0

Browse files
2 parents 523df79 + 5021801 commit 732a8d0

File tree

4 files changed

+978
-120
lines changed

4 files changed

+978
-120
lines changed

Assets/ScriptableRenderLoop/AdditionalLightData.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
namespace UnityEngine.Experimental.ScriptableRenderLoop
22
{
3-
//@TODO: We should continously move these values
3+
public enum LightArchetype {Punctual, Rectangle, Line};
4+
5+
//@TODO: We should continuously move these values
46
// into the engine when we can see them being generally useful
57
[RequireComponent(typeof(Light))]
68
public class AdditionalLightData : MonoBehaviour
79
{
10+
811
public const int DefaultShadowResolution = 512;
912

1013
public int shadowResolution = DefaultShadowResolution;
@@ -31,9 +34,8 @@ public float GetInnerSpotPercent01()
3134
public bool affectDiffuse = true;
3235
public bool affectSpecular = true;
3336

34-
// Area Light Hack
35-
public bool treatAsAreaLight = false;
36-
public bool isDoubleSided = false;
37+
public LightArchetype archetype = LightArchetype.Punctual;
38+
public bool isDoubleSided = false;
3739

3840
[RangeAttribute(0.0f, 20.0f)]
3941
public float areaLightLength = 0.0f;

Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -776,15 +776,22 @@ void ConvertLightForGPU(CullResults cullResults, ref ShadowOutput shadowOutput,
776776
// Note: LightType.Area is offline only, use for baking, no need to test it
777777
var lightData = new LightData();
778778

779-
// Early out if we reach the maximum
780779
// Test whether we should treat this punctual light as an area light.
781780
// It's a temporary hack until the proper UI support is added.
782-
if (additionalData.treatAsAreaLight)
781+
if (additionalData.archetype != LightArchetype.Punctual)
783782
{
783+
// Early out if we reach the maximum
784784
if (lightList.areaLights.Count >= k_MaxAreaLightsOnSCreen)
785785
continue;
786786

787-
lightData.lightType = GPULightType.Rectangle;
787+
if (additionalData.archetype == LightArchetype.Rectangle)
788+
{
789+
lightData.lightType = GPULightType.Rectangle;
790+
}
791+
else
792+
{
793+
lightData.lightType = GPULightType.Line;
794+
}
788795
}
789796
else
790797
{
@@ -874,13 +881,14 @@ void ConvertLightForGPU(CullResults cullResults, ref ShadowOutput shadowOutput,
874881
lightData.size = new Vector2(additionalData.areaLightLength, additionalData.areaLightWidth);
875882
lightData.twoSided = additionalData.isDoubleSided;
876883

877-
if (additionalData.treatAsAreaLight)
884+
if (additionalData.archetype == LightArchetype.Punctual)
878885
{
879-
lightList.areaLights.Add(lightData);
886+
lightList.punctualLights.Add(lightData);
880887
}
881888
else
882889
{
883-
lightList.punctualLights.Add(lightData);
890+
// Area and line lights are both currently stored as area lights on the GPU.
891+
lightList.areaLights.Add(lightData);
884892
}
885893
}
886894

Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -751,19 +751,25 @@ void IntegrateGGXAreaRef( float3 V, float3 positionWS, PreLightData preLightDa
751751

752752
float4x4 localToWorld = float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(lightData.forward, 0.0), float4(lightData.positionWS, 1.0));
753753

754-
if (lightData.lightType == GPULIGHTTYPE_SPHERE)
755-
SampleSphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
756-
else if (lightData.lightType == GPULIGHTTYPE_HEMISPHERE)
757-
SampleHemisphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
758-
else if (lightData.lightType == GPULIGHTTYPE_CYLINDER)
759-
SampleCylinder(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
760-
else if (lightData.lightType == GPULIGHTTYPE_RECTANGLE)
761-
SampleRectangle(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
762-
else if (lightData.lightType == GPULIGHTTYPE_DISK)
763-
SampleDisk(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
764-
else if (lightData.lightType == GPULIGHTTYPE_LINE)
765-
// SampleLine(u, localToWorld, areaLight.lightRadius0, lightPdf, P, Ns);
766-
; // TODO
754+
switch (lightData.lightType)
755+
{
756+
case GPULIGHTTYPE_SPHERE:
757+
SampleSphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
758+
break;
759+
case GPULIGHTTYPE_HEMISPHERE:
760+
SampleHemisphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
761+
break;
762+
case GPULIGHTTYPE_CYLINDER:
763+
SampleCylinder(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
764+
break;
765+
case GPULIGHTTYPE_RECTANGLE:
766+
SampleRectangle(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
767+
break;
768+
case GPULIGHTTYPE_DISK:
769+
SampleDisk(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
770+
break;
771+
// case GPULIGHTTYPE_LINE: handled by a separate function.
772+
}
767773

768774
// Get distance
769775
float3 unL = P - positionWS;
@@ -795,6 +801,53 @@ void IntegrateGGXAreaRef( float3 V, float3 positionWS, PreLightData preLightDa
795801
specularLighting /= float(sampleCount);
796802
}
797803

804+
//-----------------------------------------------------------------------------
805+
// EvaluateBSDFLine - Reference
806+
//-----------------------------------------------------------------------------
807+
808+
void IntegrateBSDFLineRef(float3 V, float3 positionWS, PreLightData preLightData,
809+
LightData lightData, BSDFData bsdfData,
810+
out float3 diffuseLighting, out float3 specularLighting,
811+
int sampleCount = 128)
812+
{
813+
diffuseLighting = float3(0.0, 0.0, 0.0);
814+
specularLighting = float3(0.0, 0.0, 0.0);
815+
816+
const float len = lightData.size.x;
817+
const float3 p0 = lightData.positionWS - lightData.right * (0.5 * len);
818+
const float3 dir = lightData.right;
819+
const float dt = len * rcp(sampleCount);
820+
const float off = 0.5 * dt;
821+
822+
// Uniformly sample the line segment with the Pdf = 1 / len.
823+
const float invPdf = len;
824+
825+
for (int i = 0; i < sampleCount; ++i)
826+
{
827+
// Place the sample in the middle of the interval.
828+
float t = off + i * dt;
829+
float3 sPos = p0 + t * dir;
830+
float3 unL = sPos - positionWS;
831+
float dist2 = dot(unL, unL);
832+
float3 L = normalize(unL);
833+
float sinLD = length(cross(L, dir));
834+
float NdotL = saturate(dot(bsdfData.normalWS, L));
835+
836+
float3 lightDiff, lightSpec;
837+
838+
BSDF(V, L, positionWS, preLightData, bsdfData, lightDiff, lightSpec);
839+
840+
diffuseLighting += lightDiff * (sinLD / dist2 * NdotL);
841+
specularLighting += lightSpec * (sinLD / dist2 * NdotL);
842+
}
843+
844+
// The factor of 2 is due to the fact: Integral{0, 2 PI}{max(0, cos(x))dx} = 2.
845+
float normFactor = 2.0 * invPdf * rcp(sampleCount);
846+
847+
diffuseLighting *= normFactor * lightData.diffuseScale * lightData.color;
848+
specularLighting *= normFactor * lightData.specularScale * lightData.color;
849+
}
850+
798851
//-----------------------------------------------------------------------------
799852
// EvaluateBSDF_Area
800853
//-----------------------------------------------------------------------------
@@ -805,7 +858,14 @@ void EvaluateBSDF_Area( LightLoopContext lightLoopContext,
805858
out float3 specularLighting)
806859
{
807860
#ifdef LIT_DISPLAY_REFERENCE_AREA
808-
IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
861+
if (lightData.lightType == GPULIGHTTYPE_LINE)
862+
{
863+
IntegrateBSDFLineRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
864+
}
865+
else
866+
{
867+
IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
868+
}
809869
#else
810870
// TODO: This could be precomputed
811871
float halfWidth = lightData.size.x * 0.5;

0 commit comments

Comments
 (0)