pixijs / lights

Adds dynamic lighting via deferred shading to PixiJS
https://pixijs.io/lights/docs/index.html
MIT License
198 stars 29 forks source link

Light biased towards two sides? #27

Open sjlynch opened 5 years ago

sjlynch commented 5 years ago

I tried the demo out locally and noticed that with an ambient light in the scene, the right side and bottom side of the rectangles are lit up (kind of neutral) when the point light is on the opposite sides.

I turned OFF directionalLight to be sure that wasn't it and the lighting issue remained (also directionalLight doesn't seem to do anything).

I boosted the ambient light brightness to 1.0 and that made the issue more apparent. After removing both ambient and directional lights the behavior is how I would expect (dark edges are always on opposite side of point light).

Is this a bug? This is problematic for my game because pink sided sprites (right-side and/or bottom side) do not darken when facing away from the point light. I'm going to try to hunt this issue down myself, but wanted to see if this is expected functionality or not. It's almost like AmbientLight washes out the red normal values.

ivanpopelyshev commented 5 years ago

yes, that can be an issue. Keep the research!

The only problem i noticed was with "transparent" objects on top of background, and solved that in one of demos. This plugin is highly experimental and the fact that it was possible to do that on v4 is a miracle :) previous versoin based on pixi-v3 was really hacky.

sjlynch commented 5 years ago

I think I fixed the issue.

I changed ambient.frag.js code from

    // simplified lambert shading that makes assumptions for ambient color
    // compute Distance
    float D = 1.0;
    // normalize vectors
    vec3 N = normalize(normalColor.xyz * 2.0 - 1.0);
    vec3 L = vec3(1.0, 1.0, 1.0);
    // pre-multiply light color with intensity
    // then perform "N dot L" to determine our diffuse
    vec3 diffuse = (uLightColor.rgb * uLightColor.a) * max(dot(N, L), 0.0);
    vec4 diffuseColor = texture2D(uSampler, texCoord);
    vec3 finalColor = diffuseColor.rgb * diffuse;
    gl_FragColor = vec4(finalColor, diffuseColor.a);

to

    vec3 diffuse = uLightColor.rgb * uLightColor.a;
    vec4 diffuseColor = texture2D(uSampler, texCoord);
    vec3 finalColor = diffuseColor.rgb * diffuse;
    gl_FragColor = vec4(finalColor, diffuseColor.a);

The key was removing "* max(dot(N, L), 0.0)" Removing normalized lighting values from the AmbientLight makes a lot of sense because ambient light is supposed to have no directional source so it cannot cast shadow and so it should not be sampling the normal maps. Obviously ambient light is different IRL, but for games I think this is generally what is expected.