I have recently been working on area lights for a small open source game engine called Urho3D but have run into an issues when rendering tube lights where the lights look the same as sphere lights despite the length value being changed.
I am working from Epic's paper on PBR by Brian Karis. I have tried looking at other sources to see if I could find anything but none of the results fixed the issue I was having.
The method I am using for tube lighting is as follows:
float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl)
{
float3 pos = (cLightPosPS.xyz - worldPos);
float3 reflectVec = reflect(-toCamera, normal);
float3 L01 = lightVec * LightLengh;
float3 L0 = pos - 0.5 * L01;
float3 L1 = pos + 0.5 * L01;
float3 ld = L1 - L0;
float distL0 = length( L0 );
float distL1 = length( L1 );
float NoL0 = dot( L0, normal ) / ( 2.0 * distL0 );
float NoL1 = dot( L1, normal ) / ( 2.0 * distL1 );
ndl = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) )
/ ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );
float RoL0 = dot( reflectVec, L0 );
float RoLd = dot( reflectVec, ld );
float L0oLd = dot( L0, ld );
float distLd = length( ld );
float t = ( RoL0 * RoLd - L0oLd )
/ ( distLd * distLd - RoLd * RoLd );
float3 closestPoint = L0 + ld * saturate( t);
float3 centreToRay = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;
closestPoint = closestPoint + centreToRay * saturate(LightRad / length(centreToRay));
float3 l = normalize(closestPoint);
float3 h = normalize(toCamera + l);
ndl = saturate(dot(normal, l));
float hdn = saturate(dot(h, normal));
float hdv = dot(h, toCamera);
float ndv = saturate(dot(normal, toCamera));
float distL = length(closestPoint);
float alpha = roughness * roughness;
float alphaPrime = saturate(LightRad / (distL * 2.0) + alpha);
const float3 fresnelTerm = Fresnel(specColor, hdv) ;
const float distTerm = Distribution(hdn, alphaPrime);
const float visTerm = Visibility(ndl, ndv, roughness);
return distTerm * visTerm * fresnelTerm ;
}
If the code snippet is not enough to help solve this issue you can download the full area lighting branch from GitHub. Build instructions can be found on the Urho3D website (cant link due to reputation), note currently area lighting is only tested in DX11. Shader source files can be found under
[build location]/bin/CoreData/Shaders/HLSL
You can see that both images look identical here.
If pos in multiplied into line 40 then it creates more of a tube effect but is still far from correct results, As you can see here.