2
votes

I have a basic shader which just renders a fragment based on a sampled vertex attribute color. However, the shading comes out as blocky/flat even with gl_Smooth turned on. I understand gourad and phong when it pertains to an eye position and a light, but I am trying to get smooth diffuse shading with only 'ambient light'; rather, the light values come in as part of the color as sampled with real world camera data. My world is constructed via rgbd input and creates very polygonized meshes (marching cubes) with sampled colors. My question is regarding the method of how to smooth out the shading per fragment when there is no direct light direction? I have my shader setup such that Colors, Position, and Normals are vertex attributes.

My current shaders:

vert:

#version 330

uniform mat4 ProjectionModelView;

layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Color;
layout(location = 1) in vec3 Normal;

out vec3 VertexPosition;
out vec3 VertexColor;
out vec3 VertexNormal;

void main(void)
{
    VertexColor = Color; 
    VertexPosition = Position;
    VertexNormal = Normal;
    gl_Position = ProjectionModelView*vec4(Position, 1.0);
}

fragment

#version 330
in vec3 VertexPosition;
in vec3 VertexColor;
in vec3 VertexNormal;

out vec4 FinalColor;

void main(void)
{
   float intensity = dot(VertexPosition, VertexNormal);
   FinalColor = vec4(VertexColor.x, VertexColor.y, VertexColor.z, 1)*intensity;
}

Current Output: enter image description here

And for reference, the wireframe which is pretty high triangle count:

enter image description here

With normals rendered:

enter image description here

And with just rendering the per vertex color without modifications: enter image description here

1

1 Answers

1
votes

The VertexPosition is not normalized and the VertexNormal will not be normalized after interpolation from vertex shader to fragment shader.

The unit vector direction from the fragment to the camera, is the normalized direction from the fragment position to the eye position. While the eye position is (0, 0, 0) in eye space, the fragment position is the interpolated vertex position, transformed by the model matrix and the view matrix.

Note, also the normal vector has to be transformed into the same reference system (the eye space).

The vertex shader should look somehow like this:

#version 330

uniform mat4 ModelView;
uniform mat4 Projection;

layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Color;
layout(location = 1) in vec3 Normal;

out vec3 VertexPosition;
out vec3 VertexColor;
out vec3 VertexNormal;

void main(void)
{
    vec4 pos       = ModelView * vec4(Position, 1.0);
    VertexColor    = Color; 
    VertexPosition = Position.xyz;
    VertexNormal   = mat3(ModelView) * Normal;
    gl_Position    = Projection * pos;
}

And the fragment shader should look somehow like this:

#version 330

in vec3 VertexPosition;
in vec3 VertexColor;
in vec3 VertexNormal;

out vec4 FinalColor;

void main(void)
{
    float intensity = dot( normalize( vec3(0.0) - VertexPosition ), normalize(VertexNormal) );
    FinalColor      = vec4( VertexColor.rgb * intensity, 1.0 );
}