浏览代码

Fix apply Range Attenuation

/main
Sebastien Lagarde 7 年前
当前提交
e8e01be4
共有 6 个文件被更改,包括 139 次插入124 次删除
  1. 33
      com.unity.render-pipelines.core/CoreRP/ShaderLibrary/CommonLighting.hlsl
  2. 57
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightDefinition.cs
  3. 147
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightDefinition.cs.hlsl
  4. 2
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightEvaluation.hlsl
  5. 18
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoop.cs
  6. 6
      com.unity.render-pipelines.high-definition/HDRP/Material/Lit/Lit.hlsl

33
com.unity.render-pipelines.core/CoreRP/ShaderLibrary/CommonLighting.hlsl


// Non physically based hack to limit light influence to attenuationRadius.
// SmoothInfluenceAttenuation must be use, InfluenceAttenuation is just for optimization with SmoothQuadraticDistanceAttenuation
real InfluenceAttenuation(real distSquare, real invSqrAttenuationRadius)
real InfluenceAttenuation(real distSquare, real rangeAttenuationScale, real rangeAttenuationBias)
real factor = distSquare * invSqrAttenuationRadius;
return saturate(1.0 - factor * factor);
// Apply the saturate here as we can have negative number
real factor = saturate(distSquare * rangeAttenuationScale + rangeAttenuationBias);
return 1.0 - factor * factor;
real SmoothInfluenceAttenuation(real distSquare, real invSqrAttenuationRadius)
real SmoothInfluenceAttenuation(real distSquare, real rangeAttenuationScale, real rangeAttenuationBias)
real smoothFactor = InfluenceAttenuation(distSquare, invSqrAttenuationRadius);
real smoothFactor = InfluenceAttenuation(distSquare, rangeAttenuationScale, rangeAttenuationBias);
return Sq(smoothFactor);
}

real SmoothQuadraticDistanceAttenuation(real distSquare, real distRcp, real invSqrAttenuationRadius)
real SmoothQuadraticDistanceAttenuation(real distSquare, real distRcp, real rangeAttenuationScale, real rangeAttenuationBias)
attenuation *= InfluenceAttenuation(distSquare, invSqrAttenuationRadius);
attenuation *= InfluenceAttenuation(distSquare, rangeAttenuationScale, rangeAttenuationBias);
real SmoothQuadraticDistanceAttenuation(real3 unL, real invSqrAttenuationRadius)
real SmoothQuadraticDistanceAttenuation(real3 unL, real rangeAttenuationScale, real rangeAttenuationBias)
return SmoothQuadraticDistanceAttenuation(distSquare, distRcp, invSqrAttenuationRadius);
return SmoothQuadraticDistanceAttenuation(distSquare, distRcp, rangeAttenuationScale, rangeAttenuationBias);
}
real AngleAttenuation(real cosFwd, real lightAngleScale, real lightAngleOffset)

// Combines SmoothQuadraticDistanceAttenuation() and SmoothAngleAttenuation() in an efficient manner.
// distances = {d, d^2, 1/d, d_proj}, where d_proj = dot(lightToSample, lightData.forward).
real SmoothPunctualLightAttenuation(real4 distances, real invSqrAttenuationRadius,
real SmoothPunctualLightAttenuation(real4 distances, real rangeAttenuationScale, real rangeAttenuationBias,
real lightAngleScale, real lightAngleOffset)
{
real distSq = distances.y;

real attenuation = min(distRcp, 1.0 / PUNCTUAL_LIGHT_THRESHOLD);
attenuation *= InfluenceAttenuation(distSq, invSqrAttenuationRadius);
attenuation *= AngleAttenuation(cosFwd, lightAngleScale, lightAngleOffset);
attenuation *= InfluenceAttenuation(distSq, rangeAttenuationScale, rangeAttenuationBias);
attenuation *= AngleAttenuation(cosFwd, lightAngleScale, lightAngleOffset);
return Sq(attenuation);
}

// The transformation is performed along the major axis of the ellipsoid (corresponding to 'r1').
// Both the ellipsoid (e.i. 'axis') and 'unL' should be in the same coordinate system.
// 'unL' should be computed from the center of the ellipsoid.
real EllipsoidalDistanceAttenuation(real3 unL, real invSqRadius,
real EllipsoidalDistanceAttenuation(real3 unL, real rangeAttenuationScale, real rangeAttenuationBias,
real3 axis, real invAspectRatio)
{
// Project the unnormalized light vector onto the axis.

unL -= diff * axis;
real sqDist = dot(unL, unL);
return SmoothInfluenceAttenuation(sqDist, invSqRadius);
return SmoothInfluenceAttenuation(sqDist, rangeAttenuationScale, rangeAttenuationBias);
}
// Applies SmoothInfluenceAttenuation() using the axis-aligned ellipsoid of the given dimensions.

unL *= invHalfDim;
real sqDist = dot(unL, unL);
return SmoothInfluenceAttenuation(sqDist, 1.0);
return SmoothInfluenceAttenuation(sqDist, 1.0, 0.0);
}
// Applies SmoothInfluenceAttenuation() after mapping the axis-aligned box to a sphere.

if (Max3(abs(unL.x), abs(unL.y), abs(unL.z)) > 1.0) return 0.0;
real sqDist = ComputeCubeToSphereMapSqMagnitude(unL);
return SmoothInfluenceAttenuation(sqDist, 1.0);
return SmoothInfluenceAttenuation(sqDist, 1.0, 0.0);
}
//-----------------------------------------------------------------------------

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


[GenerateHLSL]
public struct DirectionalLightData
{
public Vector3 positionWS;
public int tileCookie; // TODO: make it a bool
// Packing order depends on chronological access to avoid cache misses
public Vector3 positionWS;
public int shadowIndex; // -1 if unused
public int contactShadowIndex; // -1 if unused
public Vector3 forward;
public float volumetricDimmer;
public float specularScale;
public Vector3 up; // Rescaled by (2 / shapeHeight)
public Vector3 forward;
public int tileCookie; // TODO: make it a bool
public int shadowIndex; // -1 if unused
public int contactShadowIndex; // -1 if unused
public Vector3 up; // Rescaled by (2 / shapeHeight)
public float diffuseScale;
public Vector4 shadowMaskSelector; // Use with ShadowMask feature
public float volumetricDimmer;
public Vector4 shadowMaskSelector; // Use with ShadowMask feature
public float diffuseScale;
public float specularScale;
// Packing order depends on chronological access to avoid cache misses
public float invSqrAttenuationRadius;
public int shadowIndex; // -1 if unused
public float rangeAttenuationScale;
public float rangeAttenuationBias;
public int contactShadowIndex; // -1 if unused
public Vector3 forward;
public float angleScale; // Spot light
public float angleOffset; // Spot light
public GPULightType lightType;
public float specularScale;
public float diffuseScale;
public float angleScale; // Spot light
public float angleOffset; // Spot light
public Vector3 forward;
public int shadowIndex; // -1 if unused
public int contactShadowIndex; // -1 if unused
public int nonLightmappedOnly; // Use with ShadowMask feature // TODO: make it a bool
public int nonLightmappedOnly; // Use with ShadowMask feature // TODO: make it a bool
public float minRoughness; // This is use to give a small "area" to punctual light, as if we have a light with a radius.
public float diffuseScale;
public float specularScale;
public GPULightType lightType;
public float minRoughness; // This is use to give a small "area" to punctual light, as if we have a light with a radius.
public float volumetricDimmer; // TODO: improve the cache locality
public float volumetricDimmer;
};

public struct EnvLightData
{
// Packing order depends on chronological access to avoid cache misses
// Caution: The struct need to be align on byte16 (not strictly needed for structured buffer but if we do array later better).
// Proxy properties
public Vector3 capturePositionWS;

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


struct DirectionalLightData
{
float3 positionWS;
int tileCookie;
int shadowIndex;
int contactShadowIndex;
float3 forward;
float volumetricDimmer;
float specularScale;
float diffuseScale;
float volumetricDimmer;
int nonLightmappedOnly;
float3 forward;
int tileCookie;
int shadowIndex;
int contactShadowIndex;
int nonLightmappedOnly;
float diffuseScale;
float specularScale;
};
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.LightData

float3 positionWS;
float invSqrAttenuationRadius;
int shadowIndex;
int contactShadowIndex;
float3 forward;
float rangeAttenuationScale;
float rangeAttenuationBias;
float angleScale;
float angleOffset;
int lightType;
float specularScale;
float diffuseScale;
float angleScale;
float angleOffset;
float3 forward;
int shadowIndex;
int contactShadowIndex;
float4 shadowMaskSelector;
float4 shadowMaskSelector;
float2 size;
int lightType;
float diffuseScale;
float specularScale;
float2 size;
float volumetricDimmer;
};

{
return value.positionWS;
}
int GetTileCookie(DirectionalLightData value)
{
return value.tileCookie;
}
int GetShadowIndex(DirectionalLightData value)
int GetCookieIndex(DirectionalLightData value)
return value.shadowIndex;
return value.cookieIndex;
int GetContactShadowIndex(DirectionalLightData value)
float GetVolumetricDimmer(DirectionalLightData value)
return value.contactShadowIndex;
return value.volumetricDimmer;
float3 GetForward(DirectionalLightData value)
float3 GetRight(DirectionalLightData value)
return value.forward;
return value.right;
int GetCookieIndex(DirectionalLightData value)
float3 GetUp(DirectionalLightData value)
return value.cookieIndex;
return value.up;
float3 GetRight(DirectionalLightData value)
float3 GetForward(DirectionalLightData value)
return value.right;
return value.forward;
float GetSpecularScale(DirectionalLightData value)
int GetTileCookie(DirectionalLightData value)
return value.specularScale;
return value.tileCookie;
float3 GetUp(DirectionalLightData value)
int GetShadowIndex(DirectionalLightData value)
return value.up;
return value.shadowIndex;
float GetDiffuseScale(DirectionalLightData value)
int GetContactShadowIndex(DirectionalLightData value)
return value.diffuseScale;
return value.contactShadowIndex;
float GetVolumetricDimmer(DirectionalLightData value)
float4 GetShadowMaskSelector(DirectionalLightData value)
return value.volumetricDimmer;
return value.shadowMaskSelector;
float4 GetShadowMaskSelector(DirectionalLightData value)
float GetDiffuseScale(DirectionalLightData value)
{
return value.diffuseScale;
}
float GetSpecularScale(DirectionalLightData value)
return value.shadowMaskSelector;
return value.specularScale;
}
//

{
return value.positionWS;
}
float GetInvSqrAttenuationRadius(LightData value)
float3 GetColor(LightData value)
return value.invSqrAttenuationRadius;
return value.color;
float3 GetColor(LightData value)
float GetRangeAttenuationScale(LightData value)
return value.color;
return value.rangeAttenuationScale;
int GetShadowIndex(LightData value)
float GetRangeAttenuationBias(LightData value)
return value.shadowIndex;
return value.rangeAttenuationBias;
int GetContactShadowIndex(LightData value)
float GetAngleScale(LightData value)
return value.contactShadowIndex;
return value.angleScale;
float3 GetForward(LightData value)
float GetAngleOffset(LightData value)
return value.forward;
return value.angleOffset;
}
int GetLightType(LightData value)
{
return value.lightType;
float GetSpecularScale(LightData value)
{
return value.specularScale;
}
float GetDiffuseScale(LightData value)
float3 GetForward(LightData value)
return value.diffuseScale;
return value.forward;
float GetAngleScale(LightData value)
int GetShadowIndex(LightData value)
return value.angleScale;
return value.shadowIndex;
float GetAngleOffset(LightData value)
int GetContactShadowIndex(LightData value)
return value.angleOffset;
return value.contactShadowIndex;
float4 GetShadowMaskSelector(LightData value)
{
return value.shadowMaskSelector;
}
float4 GetShadowMaskSelector(LightData value)
float GetMinRoughness(LightData value)
return value.shadowMaskSelector;
return value.minRoughness;
float2 GetSize(LightData value)
float GetDiffuseScale(LightData value)
return value.size;
return value.diffuseScale;
int GetLightType(LightData value)
float GetSpecularScale(LightData value)
return value.lightType;
return value.specularScale;
float GetMinRoughness(LightData value)
float2 GetSize(LightData value)
return value.minRoughness;
return value.size;
}
float GetVolumetricDimmer(LightData value)
{

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


float shadowMask = 1.0;
color = lightData.color;
attenuation = SmoothPunctualLightAttenuation(distances, lightData.invSqrAttenuationRadius,
attenuation = SmoothPunctualLightAttenuation(distances, lightData.rangeAttenuationScale, lightData.rangeAttenuationBias,
lightData.angleScale, lightData.angleOffset);
#if (SHADEROPTIONS_VOLUMETRIC_LIGHTING_PRESET != 0)

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


lightData.lightType = gpuLightType;
lightData.positionWS = light.light.transform.position;
// Setting 0 for invSqrAttenuationRadius mean we have no range attenuation, but still have inverse square attenuation.
lightData.invSqrAttenuationRadius = applyRangeAttenuation ? 1.0f / (light.range * light.range) : 0.0f;
// In the shader we do range remapping: (x - start) / (end - start) = (dist^2 * rangeAttenuationScale + rangeAttenuationBias)
if (applyRangeAttenuation)
{
// start = 0.0f, end = range^2
lightData.rangeAttenuationScale = 1.0f / (light.range * light.range);
lightData.rangeAttenuationBias = 0.0f;
}
else // Don't apply any attenuation but do a 'step' at range
{
// start = range^2 - epsilon, end = range^2
lightData.rangeAttenuationScale = 1.0f / 0.01f;
lightData.rangeAttenuationBias = - (light.range * light.range - 0.01f) / 0.01f;
}
lightData.color = GetLightColor(light);
lightData.forward = light.light.transform.forward; // Note: Light direction is oriented backward (-Z)

6
com.unity.render-pipelines.high-definition/HDRP/Material/Lit/Lit.hlsl


// We define the ellipsoid s.t. r1 = (r + len / 2), r2 = r3 = r.
// TODO: This could be precomputed.
float radius = rsqrt(lightData.invSqrAttenuationRadius);
float radius = rsqrt(lightData.rangeAttenuationScale); // // rangeAttenuationScale is inverse Square Radius
float intensity = EllipsoidalDistanceAttenuation(unL, lightData.invSqrAttenuationRadius,
float intensity = EllipsoidalDistanceAttenuation(unL, lightData.rangeAttenuationScale, lightData.rangeAttenuationBias,
axis, invAspectRatio);
// Terminate if the shaded point is too far away.

// Define the dimensions of the attenuation volume.
// TODO: This could be precomputed.
float radius = rsqrt(lightData.invSqrAttenuationRadius);
float radius = rsqrt(lightData.rangeAttenuationScale); // rangeAttenuationScale is inverse Square Radius
float3 invHalfDim = rcp(float3(radius + halfWidth,
radius + halfHeight,
radius));

正在加载...
取消
保存