Edge artifact with basic diffuse shading

Started by
7 comments, last by DavidColson 8 years, 9 months ago

Hello all,

I implemented basic diffuse and ambient lighting in a glsl shader which I'm using to draw some cubes. However at a distance there are some strange artifacts on the edge's of the object. It's not aliasing. At least I'm reasonably sure. It's almost like a whole chunk of the edge isn't being lit correctly or something.

Here's a picture:

sbjxRnO.png

It doesn't occur when the lighting is turned off. So it's definitely the lighting that's causing it.

Obviously I want this to go away. I'm not quite sure what code needs to be shown so here's the fragment shader for starters:


#version 330

in vec2 UV;
in vec3 Normal0;

out vec4 FragColor;

uniform sampler2D myTextureSampler;

void main() {
	vec3 DirectionalLightColor = vec3(1.0f, 1.0f, 1.0f);
	float AmbientLightIntensity = 0.4f;
	float DirectionalLightIntensity = 1.2f;
	vec3 DirectionalLightDirection = normalize(vec3(1.0f, 1.0f, 1.0f));

	vec4 AmbientColor = vec4(DirectionalLightColor * AmbientLightIntensity, 1.0f);

	float DiffuseFactor = dot(normalize(Normal0), -DirectionalLightDirection);

	vec4 DiffuseColor;

	if (DiffuseFactor > 0) {
		DiffuseColor = vec4(DirectionalLightColor * DirectionalLightIntensity * DiffuseFactor, 1.0f);
	}
	else {
		DiffuseColor = vec4(0, 0, 0, 0);
	}

	//FragColor = (texture(myTextureSampler, UV)) * (AmbientColor + DiffuseColor);
	//FragColor = (texture(myTextureSampler, UV));
	FragColor = vec4(0.5,0.5,0.5,1) * (AmbientColor + DiffuseColor);
}

And here's the vertex shader as well incase it might be the cause of the problem


#version 330

uniform mat4 gMVP;
uniform mat4 gWorld;

layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 TexCoords;
layout (location = 2) in vec3 Normal;

out vec2 UV;
out vec3 Normal0;

void main() {
    gl_Position = gMVP * vec4(Position, 2.0);
    UV = TexCoords;
	Normal0 = (gWorld * vec4(Normal, 0.0)).xyz;
}

I'm not that experienced with OpenGL so I'm not even sure how to go about debugging this. I observed the effect lessens when you get closer to the objects. Don't know if that's relevant.

Oh here's the code that submits the draw call as well


void DrawCube(State* state, Maths::Vec3f Position, Maths::Vec3f Rotation, Maths::Vec3f Scale)
{
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, cube.VertexPositionsBuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, cube.TexCoordsBuffer);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, cube.VertexNormalsBuffer);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube.ElementBuffer);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, cube.Texture);
    glUniform1i(state->TextureUniformHandle, 0);

    Maths::Mat4f scale = Maths::MakeScale(Scale);
    Maths::Mat4f translate = Maths::MakeTranslate(Position);
    Maths::Mat4f rotate = Maths::MakeRotate(Rotation);

    Maths::Mat4f cameraTranslate = Maths::MakeTranslate(Maths::Vec3f(-state->Camera.Position.X, -state->Camera.Position.Y, -state->Camera.Position.Z));
    Maths::Mat4f cameraRotate = Maths::MakeLookAt(state->Camera.Forward, state->Camera.Up);

    Maths::Mat4f projection = Maths::MakePerspective(800, 450, 0.01, 100, 30);

    Maths::Mat4f Model = translate * rotate * scale;
    Maths::Mat4f MVP = projection * cameraRotate * cameraTranslate * Model;

    glUniformMatrix4fv(state->gMVPHandle, 1, GL_TRUE, &MVP.m[0][0]);
    glUniformMatrix4fv(state->gWorldHandle, 1, GL_TRUE, &Model.m[0][0]);

    glDrawElements(GL_TRIANGLES, cube.NumIndices, GL_UNSIGNED_INT,0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
}
Advertisement

Had a quick look, this may not be the issue, but why is your w set to 2 here?


gl_Position = gMVP * vec4(Position, 2.0);

Also try instead of (1,1,1).


vec3 DirectionalLightDirection = normalize(vec3(1.0f, 0.0f, 0.0f));

I'm not sure why w is set to 2.0 I set it to 1.0 and didn't make a difference regardless.

I tried the light direction at 1,0,0, didn't make any difference to the artifact sadly.

Thanks though!

The matrix you use to transform the normals is wrong. You're only using the model matrix when you should use the inverse of the transpose of the model view matrix, that is the model matrix multiplied with the camera's matrix.

If your model view matrix is orthogonal, you won't even need to use the inverse transpose (as it shall be the same).

Anyway, the gWorld matrix should be


cameraRotate * cameraTranslate * Model

The matrix you use to transform the normals is wrong. You're only using the model matrix when you should use the inverse of the transpose of the model view matrix, that is the model matrix multiplied with the camera's matrix.

If your model view matrix is orthogonal, you won't even need to use the inverse transpose (as it shall be the same).

Anyway, the gWorld matrix should be


cameraRotate * cameraTranslate * Model

So I made these changes to the matrix calculations:


Maths::Mat4f Model = translate * rotate * scale;
Maths::Mat4f World = cameraRotate * cameraTranslate * Model;
Maths::Mat4f MVP = projection * World;

glUniformMatrix4fv(context->gMVPHandle, 1, GL_TRUE, &MVP.m[0][0]);
glUniformMatrix4fv(context->gWorldHandle, 1, GL_TRUE, &World.m[0][0]);

But it didn't make any difference to my edge artifact. The World matrix should be orthogonal in this case since the scale matrix is setup with 1,1,1.

Regardless as a quick test I did this in the shader:


Normal0 = (inverse(transpose(gWorld)) * vec4(Normal, 0.0)).xyz;

But sadly it did nothing to my artifact.

Thanks for the help regardless!

Looks like you have face-culling disabled and the depth-buffer precision isn't enough to avoid Z-fighting at the edges.

Create a 24-bit depth-buffer, or increase the distance to your near-plane in the projection matrix, like changing 0.01 to 0.1 or even 1.

Looks like you have face-culling disabled and the depth-buffer precision isn't enough to avoid Z-fighting at the edges.

Create a 24-bit depth-buffer, or increase the distance to your near-plane in the projection matrix, like changing 0.01 to 0.1 or even 1.

That did the trick! Thank you so much!

WUuaXhM.png

Looks like you have face-culling disabled and the depth-buffer precision isn't enough to avoid Z-fighting at the edges.

Create a 24-bit depth-buffer, or increase the distance to your near-plane in the projection matrix, like changing 0.01 to 0.1 or even 1.

Its implicit here, but you should enable face culling if you dont need it to be disabled, as well. At least this particular scene does not need it disabled, assuming the cube meshes are defined correctly (counterclockwise order defined triangle vertices)

o3o

Looks like you have face-culling disabled and the depth-buffer precision isn't enough to avoid Z-fighting at the edges.

Create a 24-bit depth-buffer, or increase the distance to your near-plane in the projection matrix, like changing 0.01 to

Its implicit here, but you should enable face culling if you dont need it to be disabled, as well. At least this particular scene does not need it disabled, assuming the cube meshes are defined correctly (counterclockwise order defined triangle vertices)

Yea I had it on out of laziness. I've disabled it in the last screenshot I posted.

This topic is closed to new replies.

Advertisement