5
$\begingroup$

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

tube light image

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.

$\endgroup$
9
  • $\begingroup$ Could we see an image of how it looks? You said it looks the same with tube lights vs not so if you don't feel like posting both images that's ok, but an image alone might shed some light on things (: $\endgroup$
    – Alan Wolfe
    Sep 16, 2016 at 23:54
  • $\begingroup$ cant post images as i need 10 rep to do more then 2 links $\endgroup$ Sep 17, 2016 at 0:11
  • $\begingroup$ Annoying. Someone please upvote this question more :p $\endgroup$
    – Alan Wolfe
    Sep 17, 2016 at 0:18
  • $\begingroup$ Could try this http://imgur.com/a/IxhTd $\endgroup$ Sep 17, 2016 at 0:21
  • $\begingroup$ I added the link. For whatever it's worth, is the top or bottom image supposed to be the tube light? $\endgroup$
    – Alan Wolfe
    Sep 17, 2016 at 0:23

1 Answer 1

4
$\begingroup$

Found the solution, it turns out the lightVec is not the vector of light from the tube but rather the direction the tube will point. Therefore i will need to pass it a light rotation value to be used there.

Results: enter image description here

$\endgroup$
1
  • $\begingroup$ Nice looking results! $\endgroup$
    – Alan Wolfe
    Sep 20, 2016 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.