Jamez0r

12-31-2017, 02:22 PM

Hey guys, here is an video of the problem: https://youtu.be/4nXbgaZw3x8

I'm designing a lighting system in my game, and originally was using the shader from this tutorial: https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6

I was able to implement that, and it looked great (its the first one you see in the video of the problem).

Now I'm adapting that version to a "deferred lighting" system so that I can use a lot of lights, and although it seems to be working, the shadows near the center of the light look harsh/bad. It also looks like the original shader can actually 'brighten' the scene, whereas the new-shader can only darken (add shadows) since the blending is set to multiply (see the "rundown" section below). EDIT: After taking another look at the video, it seems like this might be the main issue (not being able to 'brighten' the scene). Not sure what to do though.

This is the shader from "ShaderLesson6" that I was previously using, and looked good:

//GL ES specific stuff

#ifdef GL_ES

#define LOWP lowp

precision mediump float;

#else

#define LOWP

#endif

//attributes from vertex shader

varying LOWP vec4 vColor;

varying vec2 vTexCoord;

//our texture samplers

uniform sampler2D u_texture; //diffuse map

uniform sampler2D u_normals; //normal map

//values used for shading algorithm...

uniform vec2 Resolution; //resolution of screen

uniform vec3 LightPos; //light position, normalized

uniform LOWP vec4 LightColor; //light RGBA -- alpha is intensity

uniform LOWP vec4 AmbientColor; //ambient RGBA -- alpha is intensity

uniform vec3 Falloff; //attenuation coefficients

void main() {

//RGBA of our diffuse color

vec4 DiffuseColor = texture2D(u_texture, vTexCoord);

//RGB of our normal map

vec3 NormalMap = texture2D(u_normals, vTexCoord).rgb;

//The delta position of light

vec3 LightDir = vec3(LightPos.xy - (gl_FragCoord.xy / Resolution.xy), LightPos.z);

//Correct for aspect ratio

LightDir.x *= Resolution.x / Resolution.y;

//Determine distance (used for attenuation) BEFORE we normalize our LightDir

float D = length(LightDir);

//normalize our vectors

vec3 N = normalize(NormalMap * 2.0 - 1.0);

vec3 L = normalize(LightDir);

//Pre-multiply light color with intensity

//Then perform \"N dot L\" to determine our diffuse term

vec3 Diffuse = (LightColor.rgb * LightColor.a) * max(dot(N, L), 0.0);

//pre-multiply ambient color with intensity

vec3 Ambient = AmbientColor.rgb * AmbientColor.a;

//calculate attenuation

float Attenuation = 1.0 / ( Falloff.x + (Falloff.y*D) + (Falloff.z*D*D) );

//the calculation which brings it all together

vec3 Intensity = Ambient + Diffuse * Attenuation;

vec3 FinalColor = DiffuseColor.rgb * Intensity;

gl_FragColor = vColor * vec4(FinalColor, DiffuseColor.a);

}";

This is the "deferred lighting" shader that I'm using now, which is basically the same thing except this new one is used for *each* light, and only calculates the light's intensity:

#ifdef GL_ES

#define LOWP lowp

precision mediump float;

#else

#define LOWP

#endif

//attributes from vertex shader

varying LOWP vec4 vColor;

varying vec2 vTexCoord;

//texture samplers

uniform sampler2D u_texture;

//values for shading algorithm

uniform vec2 resolution; //Resolution of Screen

uniform vec3 lightPosition; //Position of Light, normalized

uniform LOWP vec4 lightColor; //Light RGBA -- alpha is intensity

uniform vec3 falloff; //attenuation coefficients

uniform float zoomModifier; //Inverse of camera zoom (1f/camera.zoom)

void main() {

//RGBA of our normal map

vec4 normalMapColor = texture2D(u_texture, vTexCoord);

//The Delta position of light

vec3 lightDir = vec3(lightPosition.xy - (gl_FragCoord.xy / resolution.xy), lightPosition.z);

//Correct for aspect ratio

lightDir.x *= resolution.x / resolution.y;

//Correct for camera zoom

lightDir.xy *= zoomModifier;

//Determine distance (used for attenuation) BEFORE we normalize our LightDir

float D = length(lightDir);

//Normalized-normalMapColor

vec3 N = normalize(normalMapColor * 2.0 - 1.0);

//Normalized-lightDirection

vec3 L = normalize(lightDir);

//Pre-multiply light color with intensity, then perform "N dot L" to determine diffuse term

vec3 diffuse = (lightColor.rgb * lightColor.a) * max(dot(N,L), 0.0);

//Calculate attenuation

float attenuation = 1.0 / (falloff.x + (falloff.y * D) + (falloff.z * D * D));

//Calculate intensity

vec3 finalIntensity = diffuse * attenuation;

gl_FragColor = vColor * vec4(finalIntensity.rgb, normalMapColor.a);

}

This is the rundown of what I'm doing with the new shader:

1) Render the scene normally to the screen (default shader, regular textures)

2) Draw all of my normal-maps to a FrameBuffer ("normalMapBuffer")

3) On another FrameBuffer ("intensityFrameBuffer"), clear with the ambient light color

4) Set blending to additive (GL_ONE, GL_ONE)

5) For each of my lights, draw light to the intensityFrameBuffer using the normalMapBuffer texture and the newly-written shader

6) Set blending to multiply (GL_DST_COLOR, GL_ZERO)

7) Draw the intensityFrameBuffer to the screen

I'm pretty new to lighting/shaders, so I'm *hoping* its something simple I'm doing wrong, like using the wrong blending settings.

Original Shader with light intensity = 1:

https://i.imgur.com/rTjZn5f.png

Original Shader with light intensity = 2:

https://i.imgur.com/ZcRjgwF.png

New Shader with light intensity = 1:

https://i.imgur.com/YWMtese.png

New Shader with light intensity = 2:

https://i.imgur.com/4SeV3nF.png

I'm designing a lighting system in my game, and originally was using the shader from this tutorial: https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6

I was able to implement that, and it looked great (its the first one you see in the video of the problem).

Now I'm adapting that version to a "deferred lighting" system so that I can use a lot of lights, and although it seems to be working, the shadows near the center of the light look harsh/bad. It also looks like the original shader can actually 'brighten' the scene, whereas the new-shader can only darken (add shadows) since the blending is set to multiply (see the "rundown" section below). EDIT: After taking another look at the video, it seems like this might be the main issue (not being able to 'brighten' the scene). Not sure what to do though.

This is the shader from "ShaderLesson6" that I was previously using, and looked good:

//GL ES specific stuff

#ifdef GL_ES

#define LOWP lowp

precision mediump float;

#else

#define LOWP

#endif

//attributes from vertex shader

varying LOWP vec4 vColor;

varying vec2 vTexCoord;

//our texture samplers

uniform sampler2D u_texture; //diffuse map

uniform sampler2D u_normals; //normal map

//values used for shading algorithm...

uniform vec2 Resolution; //resolution of screen

uniform vec3 LightPos; //light position, normalized

uniform LOWP vec4 LightColor; //light RGBA -- alpha is intensity

uniform LOWP vec4 AmbientColor; //ambient RGBA -- alpha is intensity

uniform vec3 Falloff; //attenuation coefficients

void main() {

//RGBA of our diffuse color

vec4 DiffuseColor = texture2D(u_texture, vTexCoord);

//RGB of our normal map

vec3 NormalMap = texture2D(u_normals, vTexCoord).rgb;

//The delta position of light

vec3 LightDir = vec3(LightPos.xy - (gl_FragCoord.xy / Resolution.xy), LightPos.z);

//Correct for aspect ratio

LightDir.x *= Resolution.x / Resolution.y;

//Determine distance (used for attenuation) BEFORE we normalize our LightDir

float D = length(LightDir);

//normalize our vectors

vec3 N = normalize(NormalMap * 2.0 - 1.0);

vec3 L = normalize(LightDir);

//Pre-multiply light color with intensity

//Then perform \"N dot L\" to determine our diffuse term

vec3 Diffuse = (LightColor.rgb * LightColor.a) * max(dot(N, L), 0.0);

//pre-multiply ambient color with intensity

vec3 Ambient = AmbientColor.rgb * AmbientColor.a;

//calculate attenuation

float Attenuation = 1.0 / ( Falloff.x + (Falloff.y*D) + (Falloff.z*D*D) );

//the calculation which brings it all together

vec3 Intensity = Ambient + Diffuse * Attenuation;

vec3 FinalColor = DiffuseColor.rgb * Intensity;

gl_FragColor = vColor * vec4(FinalColor, DiffuseColor.a);

}";

This is the "deferred lighting" shader that I'm using now, which is basically the same thing except this new one is used for *each* light, and only calculates the light's intensity:

#ifdef GL_ES

#define LOWP lowp

precision mediump float;

#else

#define LOWP

#endif

//attributes from vertex shader

varying LOWP vec4 vColor;

varying vec2 vTexCoord;

//texture samplers

uniform sampler2D u_texture;

//values for shading algorithm

uniform vec2 resolution; //Resolution of Screen

uniform vec3 lightPosition; //Position of Light, normalized

uniform LOWP vec4 lightColor; //Light RGBA -- alpha is intensity

uniform vec3 falloff; //attenuation coefficients

uniform float zoomModifier; //Inverse of camera zoom (1f/camera.zoom)

void main() {

//RGBA of our normal map

vec4 normalMapColor = texture2D(u_texture, vTexCoord);

//The Delta position of light

vec3 lightDir = vec3(lightPosition.xy - (gl_FragCoord.xy / resolution.xy), lightPosition.z);

//Correct for aspect ratio

lightDir.x *= resolution.x / resolution.y;

//Correct for camera zoom

lightDir.xy *= zoomModifier;

//Determine distance (used for attenuation) BEFORE we normalize our LightDir

float D = length(lightDir);

//Normalized-normalMapColor

vec3 N = normalize(normalMapColor * 2.0 - 1.0);

//Normalized-lightDirection

vec3 L = normalize(lightDir);

//Pre-multiply light color with intensity, then perform "N dot L" to determine diffuse term

vec3 diffuse = (lightColor.rgb * lightColor.a) * max(dot(N,L), 0.0);

//Calculate attenuation

float attenuation = 1.0 / (falloff.x + (falloff.y * D) + (falloff.z * D * D));

//Calculate intensity

vec3 finalIntensity = diffuse * attenuation;

gl_FragColor = vColor * vec4(finalIntensity.rgb, normalMapColor.a);

}

This is the rundown of what I'm doing with the new shader:

1) Render the scene normally to the screen (default shader, regular textures)

2) Draw all of my normal-maps to a FrameBuffer ("normalMapBuffer")

3) On another FrameBuffer ("intensityFrameBuffer"), clear with the ambient light color

4) Set blending to additive (GL_ONE, GL_ONE)

5) For each of my lights, draw light to the intensityFrameBuffer using the normalMapBuffer texture and the newly-written shader

6) Set blending to multiply (GL_DST_COLOR, GL_ZERO)

7) Draw the intensityFrameBuffer to the screen

I'm pretty new to lighting/shaders, so I'm *hoping* its something simple I'm doing wrong, like using the wrong blending settings.

Original Shader with light intensity = 1:

https://i.imgur.com/rTjZn5f.png

Original Shader with light intensity = 2:

https://i.imgur.com/ZcRjgwF.png

New Shader with light intensity = 1:

https://i.imgur.com/YWMtese.png

New Shader with light intensity = 2:

https://i.imgur.com/4SeV3nF.png