浏览代码

Fix, clean up and optimize the line light code

/main
Evgenii Golubev 8 年前
当前提交
ffa02031
共有 3 个文件被更改,包括 55 次插入48 次删除
  1. 72
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  2. 26
      Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl
  3. 5
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl

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


specularLighting = float3(0.0, 0.0, 0.0);
const float len = lightData.size.x;
const float3 dir = lightData.right;
const float3 p1 = lightData.positionWS - lightData.right * (0.5 * len);
const float3 T = lightData.right;
const float3 P1 = lightData.positionWS - T * (0.5 * len);
const float dt = len * rcp(sampleCount);
const float off = 0.5 * dt;

{
// Place the sample in the middle of the interval.
float t = off + i * dt;
float3 sPos = p1 + t * dir;
float3 sPos = P1 + t * T;
float sinLD = length(cross(L, dir));
float sinLT = length(cross(L, T));
float NdotL = saturate(dot(bsdfData.normalWS, L));
float3 lightDiff, lightSpec;

diffuseLighting += lightDiff * (sinLD / dist2 * NdotL);
specularLighting += lightSpec * (sinLD / dist2 * NdotL);
diffuseLighting += lightDiff * (sinLT / dist2 * NdotL);
specularLighting += lightSpec * (sinLT / dist2 * NdotL);
}
// The factor of 2 is due to the fact: Integral{0, 2 PI}{max(0, cos(x))dx} = 2.

specularLighting = float3(0.0, 0.0, 0.0);
float len = lightData.size.x;
float3 dir = lightData.right;
float3 T = lightData.right;
float3 p1 = lightData.positionWS - lightData.right * (0.5 * len);
float3 p2 = lightData.positionWS + lightData.right * (0.5 * len);
float3 P1 = lightData.positionWS - T * (0.5 * len);
float3 P2 = lightData.positionWS + T * (0.5 * len);
p1 -= positionWS;
p2 -= positionWS;
P1 -= positionWS;
P2 -= positionWS;
// Construct an orthonormal basis (local coordinate system) around N.
// TODO: it could be stored in PreLightData. All LTC lights compute it more than once!

basis[1] = normalize(cross(bsdfData.normalWS, basis[0]));
basis[2] = bsdfData.normalWS;
// Transform (rotate) both endpoints into the local coordinate system (left-handed).
p1 = mul(p1, transpose(basis));
p2 = mul(p2, transpose(basis));
// Rotate both endpoints and the tangent into the local coordinate system (left-handed).
P1 = mul(P1, transpose(basis));
P2 = mul(P2, transpose(basis));
T = mul(T, transpose(basis));
if (p1.z <= 0.0 && p2.z <= 0.0) return;
if (P1.z <= 0.0 && P2.z <= 0.0) return;
if (p2.z <= 0.0)
if (P2.z <= 0.0)
// Convention: 'p2' is above the horizon.
swap(p1, p2);
dir = -dir;
// Convention: 'P2' is above the horizon.
swap(P1, P2);
T = -T;
if (p1.z <= 0.0)
if (P1.z <= 0.0)
// p = p1 + t * dir; p.z == 0.
float t = -p1.z / dir.z;
p1 = float3(p1.xy + t * dir.xy, 0.0);
// p = P1 + t * T; p.z == 0.
float t = -P1.z / T.z;
P1 = float3(P1.xy + t * T.xy, 0.0);
// Compute the direction to the point on the line orthogonal to 'dir'.
// Its length is the shortest distance to the line.
float3 p0 = p1 - dot(p1, dir) * dir;
float dist = length(p0);
// Compute the normal direction to the line, s.t. it is the shortest vector between the shaded
// point and the line, pointing away from the shaded point. Can be viewed as a point on the line.
float proj = dot(P1, T);
float3 P0 = P1 - proj * T;
// Compute the parameterization: distances from 'l1' and 'l2' to 'l0'.
float l1 = dot(p1 - p0, dir);
// Compute the parameterization: distances from 'P1' and 'P2' to 'P0'.
float l1 = proj;
float irradiance = LineIrradiance(l1, l2, dist, p0.z, dir.z);
float irradiance = LineIrradiance(l1, l2, P0, T);
// Only Lambertian for now. TODO: Disney Diffuse and GGX.
diffuseLighting = (lightData.diffuseScale * irradiance * INV_PI) * bsdfData.diffuseColor * lightData.color;

#ifdef LIT_DISPLAY_REFERENCE_AREA
if (lightData.lightType == GPULIGHTTYPE_LINE)
{
IntegrateBSDFLineRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
IntegrateBSDFLineRef(V, positionWS, preLightData, lightData, bsdfData,
diffuseLighting, specularLighting);
IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData,
diffuseLighting, specularLighting);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
// EvaluateBSDF_Line(lightLoopContext, V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
EvaluateBSDF_Line(lightLoopContext, V, positionWS, preLightData, lightData, bsdfData,
diffuseLighting, specularLighting);
return;
}

26
Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl


return PolygonRadiance(L, twoSided);
}
float LineFpo(float rcpD, float rcpDL, float l)
float LineFpo(float l, float rcpD, float rcpDL)
return l * rcpDL + rcpD * rcpD * atan(l * rcpD);
return l * rcpDL + sq(rcpD) * atan(l * rcpD);
}
float LineFwt(float sqL, float rcpDL)

}
// Computes the integral of the clamped cosine over the line segment.
// 'dist' is the shortest distance to the line. 'l1' and 'l2' define the integration interval.
float LineIrradiance(float l1, float l2, float dist, float pointZ, float tangentZ)
// 'l1' and 'l2' define the integration interval.
// 'tangent' is the line's tangent direction.
// 'normal' is the direction orthogonal to the tangent. It is the shortest vector between
// the shaded point and the line, pointing away from the shaded point.
float LineIrradiance(float l1, float l2, float3 normal, float3 tangent)
float sqD = dist * dist;
float sqL1 = l1 * l1;
float sqL2 = l2 * l2;
float rcpD = rcp(dist);
float rcpDL1 = rcpD * rcp(sqD + sqL1);
float rcpDL2 = rcpD * rcp(sqD + sqL2);
float intP0 = LineFpo(rcpD, rcpDL2, l2) - LineFpo(rcpD, rcpDL1, l1);
float intWt = LineFwt(sqL2, rcpDL2) - LineFwt(sqL1, rcpDL1);
return intP0 * pointZ + intWt * tangentZ;
float dist = length(normal);
float rcpDL1 = rcp(dist) * rcp(sq(dist) + sq(l1));
float rcpDL2 = rcp(dist) * rcp(sq(dist) + sq(l2));
float intP0 = LineFpo(l2, rcp(dist), rcpDL2) - LineFpo(l1, rcp(dist), rcpDL1);
float intWt = LineFwt(sq(l2), rcpDL2) - LineFwt(sq(l1), rcpDL1);
return intP0 * normal.z + intWt * tangent.z;
}
#endif // UNITY_AREA_LIGHTING_INCLUDED

5
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


}
#endif // INTRINSIC_MINMAX3
float sq(float x)
{
return x * x;
}
void swap(inout float a, inout float b)
{
float t = a; a = b; b = t;

正在加载...
取消
保存