pezcode / Cluster

Clustered shading implementation with bgfx

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Directional Light support?

opened this issue Β· comments

Hi am quite new to graphics programming and currently trying to add directional light support to Forward Shader.
Could you please let me know if this is a correct approach ? Also I believe spot lights branch was never actually made to support spot lights? Sorry for 2 questions in one. Please see my snippet below

    // Directional light comes after Point light calculation to add up Radiance
    vec3 L = normalize(u_sunDirection.xyz); // directional light vector
    float NoL = clamp(dot(N, L), 0.0, 1.0); // calculate the dot between the normal and sun vector

    float illuminance = 1 * NoL; // (1 picked for moon light, can be tweaked depending on day time)
    radianceOut += BRDF(V, L, N, NoV, NoL, mat) * msFactor * illuminance; // apply final radiance for the directional light

My result there are no shadows yet. Thank you

That looks good to me πŸ‘ Nice sky shader you got there, too!

As for the spot lights - I started working on it but never got around to finishing it. It's missing the culling entirely, so not really useful. Maybe I can find some time over a weekend to finish it, but no promises.

That looks good to me πŸ‘ Nice sky shader you got there, too!

As for the spot lights - I started working on it but never got around to finishing it. It's missing the culling entirely, so not really useful. Maybe I can find some time over a weekend to finish it, but no promises.

Thank you so much for your feedback. Cluster repo helped me a lot to understand a lot of things I did not know before !
I ported parts of it to C .

As for the sky I used bgfx's sample, maybe you'd like me to add a PR?

However I am yet to add sky color to the PBR shader in fragment shader . This is what they do

image

Regardless I truly appreciate your reactivity on the matter and do not feel pressured to finish spot lights, it will be a good learning material for me like the rest of the code you written.

Cheers !

As for the sky I used bgfx's sample, maybe you'd like me to add a PR?

I appreciate the offer, but I'd prefer to keep this code a bit more focused on just the lighting part. If anyone needs the sky part, they can grab it from other places, like you did.

And thank you for the kind words ☺️ Great to know that this repo is helping people in one way or another.

As for the sky I used bgfx's sample, maybe you'd like me to add a PR?

I appreciate the offer, but I'd prefer to keep this code a bit more focused on just the lighting part. If anyone needs the sky part, they can grab it from other places, like you did.

And thank you for the kind words ☺️ Great to know that this repo is helping people in one way or another.

No problem !

EDIT:
I will close the issue since it was addressed :)

Hey @pezcode I am reopening the topic as I'd like to seek your advice on how to implement directional light with deferred as the shading done in screen space?

My final shader code worked for forward shader but I have trouble wrapping my head around deferred one. If you could take a look I would gladly appreciate it.

My forward shader code

    // Directional light (point lights calculated above inside fs_forward.sc
	vec3 skyDirection = vec3(0.0, 0.0, 1.0);
	vec3 L = normalize(u_sunDirection.xyz);

	float diffuseSun = max(0.0, dot(N, L));
	float diffuseSky = 1.0 + 0.5 * dot(N, skyDirection);

    float NoL = saturate(dot(N, L));

    // Apply sky color 
	vec3 color = diffuseSun * u_sunLuminance.rgb + (diffuseSky * u_skyLuminance.rgb + 0.01);
	color *= 0.5 * u_parameters.z; // time of day

    float illuminance = (diffuseSun + diffuseSky);
    float illuminaneIntensity = 5;
    illuminance *= illuminaneIntensity;

    radianceOut += BRDF(V, L, N, NoV, NoL, mat) * color * msFactor * illuminance * NoL;

For deferred, directional lights should happen in the fullscreen shading pass in fs_deferred_fullscreen.sc. Currently that only adds ambient lighting and emissive but you can more or less copy paste what you have in the forward version.

@pezcode thank you for your answer but I am afraid I am totally stuck as how to achieve the directional light in camera space. I recorded a small video of my artifact if you may take a look as well as the shader code I have. I would gladly appreciate if you could take couple minutes to help me out. As I understood is that my Directional Light might not supply a position ? or is dependent on camera position . Maybe I should just do it in world space like I did in forward shader?

    vec4 diffuseA = texture2D(s_texDiffuseA, texcoord);
    vec3 N = unpackNormal(texture2D(s_texNormal, texcoord).xy);
    vec4 F0Metallic = texture2D(s_texF0Metallic, texcoord);


    // unpack material parameters used by the PBR BRDF function
    PBRMaterial mat;
    mat.diffuseColor = diffuseA.xyz;
    mat.a = diffuseA.w;
    mat.F0 = F0Metallic.xyz;
    mat.metallic = F0Metallic.w;

    // get fragment position
    // rendering happens in view space
    vec4 screen = gl_FragCoord;
    screen.z = texture2D(s_texDepth, texcoord).x;
    vec3 fragPos = screen2Eye(screen).xyz;

    vec3 V = normalize(-fragPos);
    float NoV = abs(dot(N, V)) + 1e-5;
	// vec3 L = normalize(u_sunDirection.xyz); // sun direction is in world space
    vec3 L = normalize(mul(u_view, vec4(u_sunDirection.xyz, 1.0)).xyz); // also tried in camera space

    float NoL = saturate(dot(N, L));

    // Directional light
	vec3 skyDirection = vec3(0.0, 0.0, 1.0);


	float diffuseSun = max(0.0, dot(N, L));
	float diffuseSky = 1.0 + 0.5 * dot(N, skyDirection);


    // Apply sky color 
	vec3 color = diffuseSun * u_sunLuminance.rgb + (diffuseSky * u_skyLuminance.rgb + 0.01);
	color *= 0.5 * u_parameters.z; // time of day

    float illuminance = (diffuseSun + diffuseSky);
    float illuminaneIntensity = 5;
    illuminance *= illuminaneIntensity;

    radianceOut += BRDF(V, L, N, NoV, NoL, mat) * color * illuminance * NoL;

https://streamable.com/13bdnr

Can you try changing to vec3 L = normalize(mul(u_view, vec4(u_sunDirection.xyz, 0.0)).xyz);? Notice the 0.0 instead of 1.0. Since the sun direction is a vector, not a point, you need w to be 0 so the translation in u_view doesn't get applied.

vec3 L = normalize(mul(u_view, vec4(u_sunDirection.xyz, 0.0)).xyz);

Thank you for your answer. Unfortunately this resulted in the same behavior. I will continue searching and will get back here once I solve this mystery 😁

My issue is that the Normal is in Camera Space, as soon as I keep it in world space I am able to do the correct light calculation. I wonder what am I doing wrong when converting my sun direction which is just a rotational vector

You're not transforming skyDirection to camera space, that seems like it would be an issue

You're not transforming skyDirection to camera space, that seems like it would be an issue

Would that be the line of code that does exactly that?
vec3 L = normalize(mul(u_view, vec4(u_sunDirection.xyz, 0.0)).xyz);

since


    // save normal in camera space
    // the other renderers render in world space but the
    // deferred renderer uses camera space to hide artifacts from
    // normal packing and to make fragment position reconstruction easier
    // the normal matrix transforms to world coordinates, so undo that
    N = mul(u_view, vec4(N, 0.0)).xyz;

Edit : oh I see, but I tried with minimal repo with no skyDirection parameter , skyDirection is used to tell that Z is forward vector

    vec3 N = unpackNormal(texture2D(s_texNormal, texcoord).xy);

    vec3 radianceOut = vec3_splat(0.0);
    radianceOut += getAmbientLight().irradiance * diffuseColor * occlusion;
    radianceOut += emissive;


    if(saturate(dot(N, normalize(mul(u_view, vec4(u_sunDirection.xyz, 0))))) > 0)
       radianceOut += 10000;

I painted every pixel bright white to see if the dot product returns correct values
https://streamable.com/bmsxd1

@pezcode I think I am totally stuck . Do you think it would be possible for you to take some time to add support for directional lights in deferred rendering? I think it will be a good feature to add into the stack: directional lights, point lights , spot lights.

I am also simply not getting the right results and lack the graphic knowledge πŸ˜„

If I find some time and motivation over a weekend, I'll give it a shot. The spot lights I'm not 100% sure about. I've done those in another project but they're a bit ugly to implement without struct support in compute buffers.

@clibequilibrium I found the cause of your troubles πŸ™Š For the deferred fullscreen pass I tried to be clever and re-use the existing vs_deferred_light.sc. For that to work I needed to set the view and projection matrices to identity matrices, because the fullscreen triangle vertices are already in clip space for simplicity. But that also meant u_view in fs_deferred_fullscreen.sc is useless and keeps the light direction in world space instead of transforming it to view space.

I cleaned this stuff up to use a separate shader instead of silly hacks like that in 840ca87.

Out of boredom I also pushed a branch that adds a sun light to all 3 renderers, feel free to use that for inspiration. But the code you have above should work fine now.

Thank you @pezcode I will check it out ASAP.
I truly appreciate your help on the matter πŸ™Œ

@pezcode this worked flawlessly. Thank you once again !