浏览代码

Add the initial impl. of LTC line light Lambertian diffuse shading

/main
Evgenii Golubev 8 年前
当前提交
472d34b5
共有 3 个文件被更改,包括 138 次插入8 次删除
  1. 94
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  2. 32
      Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl
  3. 20
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl

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


specularLighting = float3(0.0, 0.0, 0.0);
const float len = lightData.size.x;
const float3 p0 = lightData.positionWS - lightData.right * (0.5 * len);
const float3 p1 = lightData.positionWS - lightData.right * (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 = p0 + t * dir;
float3 sPos = p1 + t * dir;
float3 unL = sPos - positionWS;
float dist2 = dot(unL, unL);
float3 L = normalize(unL);

}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Area
// EvaluateBSDF_Line | Approximation with Linearly Transformed Cosines
//-----------------------------------------------------------------------------
void EvaluateBSDF_Line( LightLoopContext lightLoopContext,
float3 V, float3 positionWS, PreLightData preLightData,
LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
{
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float len = lightData.size.x;
float3 dir = lightData.right;
// TODO: precompute half-length. Same as for LTC area lights.
// In fact, why not store both endpoints? Saves us 7 cycles.
float3 p1 = lightData.positionWS - lightData.right * (0.5 * len);
float3 p2 = lightData.positionWS + lightData.right * (0.5 * len);
// Translate both points s.t. the shaded point is at the origin of the coordinate system.
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!
float3x3 basis;
basis[0] = normalize(V - bsdfData.normalWS * preLightData.NdotV);
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));
// Terminate the algorithm if both points are below the horizon.
if (p1.z <= 0.0 && p2.z <= 0.0) return;
if (p2.z <= 0.0)
{
// Convention: 'p2' is above the horizon.
swap(p1, p2);
dir = -dir;
}
// Clip the part of the light below the horizon.
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);
// Set the length of the visible part of the light.
len -= t;
}
// 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 parameterization: distances from 'l1' and 'l2' to 'l0'.
float l1 = dot(p1 - p0, dir);
float l2 = l1 + len;
// Integrate the clamped cosine over the line segment.
float irradiance = LineIrradiance(l1, l2, dist, p0.z, dir.z);
// Only Lambertian for now. TODO: Disney Diffuse and GGX.
diffuseLighting = (lightData.diffuseScale * irradiance * INV_PI) * bsdfData.diffuseColor * lightData.color;
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Area | Approximation with Linearly Transformed Cosines
//-----------------------------------------------------------------------------
void EvaluateBSDF_Area( LightLoopContext lightLoopContext,

IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
}
#else
if (lightData.lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line(lightLoopContext, V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return;
}
// TODO: store 4 points and save 24 cycles.
float3 p0 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
float3 p1 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;
float3 p2 = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;

0.0, 1.0, 0.0,
0.0, 0.0, 1.0};
ltcValue = LTCEvaluate(V, bsdfData.normalWS, identity3x3, L, lightData.twoSided);
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
identity3x3);
ltcValue = LTCEvaluate(V, bsdfData.normalWS, preLightData.ltcXformDisneyDiffuse, L, lightData.twoSided);
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
preLightData.ltcXformDisneyDiffuse);
#endif
if (ltcValue == 0.0)

float3 fresnelTerm = bsdfData.fresnel0 * preLightData.ltcGGXFresnelMagnitudeDiff
+ (float3)preLightData.ltcGGXFresnelMagnitude;
ltcValue = LTCEvaluate(V, bsdfData.normalWS, preLightData.ltcXformGGX, L, lightData.twoSided);
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
preLightData.ltcXformGGX);
ltcValue *= lightData.specularScale;
specularLighting = fresnelTerm * lightData.color * ltcValue;
}

32
Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl


return twoSided ? abs(sum) : max(sum, 0.0);
}
float LTCEvaluate(float3 V, float3 N, float3x3 minV, float4x3 L, bool twoSided)
float LTCEvaluate(float4x3 L, float3 V, float3 N, float NdotV, bool twoSided, float3x3 minV)
// TODO: it could be stored in PreLightData. All LTC lights compute it more than once!
basis[0] = normalize(V - N * dot(V, N));
basis[0] = normalize(V - N * NdotV);
basis[1] = normalize(cross(N, basis[0]));
basis[2] = N;

// Polygon radiance in transformed configuration - specular
return PolygonRadiance(L, twoSided);
}
float LineFpo(float rcpD, float rcpDL, float l)
{
// Compute: l / d / (d * d + l * l) + 1.0 / (d * d) * atan(l / d).
return l * rcpDL + rcpD * rcpD * atan(l * rcpD);
}
float LineFwt(float sqL, float rcpDL)
{
// Compute: l * l / d / (d * d + l * l).
return sqL * 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)
{
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;
}
#endif // UNITY_AREA_LIGHTING_INCLUDED

20
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


}
#endif // INTRINSIC_MINMAX3
void swap(inout float a, inout float b)
{
float t = a; a = b; b = t;
}
void swap(inout float2 a, inout float2 b)
{
float2 t = a; a = b; b = t;
}
void swap(inout float3 a, inout float3 b)
{
float3 t = a; a = b; b = t;
}
void swap(inout float4 a, inout float4 b)
{
float4 t = a; a = b; b = t;
}
#ifndef INTRINSIC_CUBEMAP_FACE_ID
// TODO: implement this. Is the reference implementation of cubemapID provide by AMD the reverse of our ?
/*

正在加载...
取消
保存