2

I've been trying to implement a simple light / shading system, a simple Phong lighting system without specular lights to be precise. It basically works, except it has some (in my opinion) nasty artifacts.

My first thought was that maybe this is a problem of the texture mipmaps, but disabling them didn't work. My next best guess would be a shader issue, but I can't seem to find the error.

Has anybody ever experienced a similiar issue or an idea on how to solve this?

Image of the artifacts

Vertex shader:

#version 330 core

// Vertex shader
layout(location = 0) in vec3 vpos;
layout(location = 1) in vec2 vuv;
layout(location = 2) in vec3 vnormal;

out vec2 uv;        // UV coordinates
out vec3 normal;    // Normal in camera space
out vec3 pos;       // Position in camera space
out vec3 light[3];  // Vertex -> light vector in camera space

uniform mat4 mv;    // View * model matrix
uniform mat4 mvp;   // Proj * View * Model matrix
uniform mat3 nm;    // Normal matrix for transforming normals into c-space

void main() {
    // Pass uv coordinates
    uv = vuv;

    // Adjust normals
    normal = nm * vnormal;

    // Calculation of vertex in camera space
    pos = (mv * vec4(vpos, 1.0)).xyz;

    // Vector vertex -> light in camera space
    light[0] = (mv * vec4(0.0,0.3,0.0,1.0)).xyz - pos;
    light[1] = (mv * vec4(-6.0,0.3,0.0,1.0)).xyz - pos;
    light[2] = (mv * vec4(0.0,0.3,4.8,1.0)).xyz - pos;

    // Pass position after projection transformation
    gl_Position = mvp * vec4(vpos, 1.0);
}

Fragment shader:

#version 330 core

// Fragment shader
layout(location = 0) out vec3 color;

in vec2 uv;     // UV coordinates
in vec3 normal;     // Normal in camera space
in vec3 pos;        // Position in camera space
in vec3 light[3];   // Vertex -> light vector in camera space

uniform sampler2D tex;
uniform float flicker;

void main() {
    vec3 n = normalize(normal);

    // Ambient
    color = 0.05 * texture(tex, uv).rgb;

    // Diffuse lights
    for (int i = 0; i < 3; i++) {
        l = normalize(light[i]);
        cos = clamp(dot(n,l), 0.0, 1.0);
        length = length(light[i]);
        color += 0.6 * texture(tex, uv).rgb * cos / pow(length, 2);
    }
}

2 Answers2

1

As the first comment says, it looks like your color computation is using insufficient precision. Try using mediump or highp floats.

Additionally, the length = length(light[i]); pow(length,2) expression is quite inefficient, and could also be a source of the observed banding; you should use dot(light[i],light[i]) instead.

dognotdog
  • 681
  • 3
  • 14
  • Thank you for the dot(light[i],light[i]) advice! Unfortunately, using highp floats changed nothing at all, the problem still persists. – user3413372 Feb 16 '16 at 20:43
  • are you also using highp for the vectors? – dognotdog Feb 16 '16 at 22:55
  • Yes, I've tried writing highp in front of everything, both, vertex and fragment shader, just to be sure. – user3413372 Feb 17 '16 at 15:08
  • Very odd, I'm all out of ideas. The varyings are also using highp? If you do find the error, please do post an update! – dognotdog Feb 17 '16 at 15:57
  • Yes of course! And yes, also the varyings, everything. This is really bugging me. Also, the effect is getting worse the farther away from the light you are (I tried leaving the pow or dot(light[i],light[i]) out of the equation, but it didn't change anything). – user3413372 Feb 17 '16 at 20:17
0

So i found information about my problem described as "gradient banding", also discussed here. The problem appears to be in the nature of my textures, since both, only the "white" texture and the real texture are mostly grey/white and there are effectively 256 levels of grey when using 8 bit per color channel.

The solution would be to implement post-processing dithering or to use better textures.

  • You are seeing banding, but not because of the texture bit depth. If you look at the screenshot you posted in photoshop, you can see that each band is not one gray value apart, like in the linked post, but two or three. Gradient banding like in the linked post looks distinctly different, notice how much finer it is. Unless you have a lot of noise in your texture (did you try just a solid color instead, how the banding looks?), in which case it could be a color-space issue (linear vs. gamma corrected), it doesn't look like a likely explanation. – dognotdog Feb 18 '16 at 15:05
  • I still think its some computation artifact, maybe even the division, '... / pow ...'. You could try pre-computing falloff = 1.0 / pow... and then multiply that instead of the division in the final computation. – dognotdog Feb 18 '16 at 15:07
  • I've tried leaving the falloff out completely. I've tried it with white color instead of a texture, it gives me exactly the bands as seen in the link. The simplest fragment shader I had, removed everything except the dot product of the light and the normal vector and it still gave me the bands. I've turned to the OpenGL Forum and was also told it's just bands. – user3413372 Feb 18 '16 at 19:43
  • An enigma, it is. Have you tried a different computer, with a different GPU? – dognotdog Feb 18 '16 at 21:05
  • I'll try later if I can get your program to work in shader builder, so far I've not succeeded getting it running... – dognotdog Feb 18 '16 at 21:23
  • I've tried on an Nvidia GPU, remember that it needed some fixing to run there, but the bands where still there. – user3413372 Feb 20 '16 at 09:34