Phong shading implementation not giving gradual light - either on or off...

Hello,

I am attempting to adapt a phong shader I found online for a project I am working on and I essentially have a problem with the specular lighting.

It is probably best explained by the images below but essentially the sunlight implemented via the shader is “on” or “off” with no gradual degradation in between.

Below are the images and the GLSL code I am using.

Any ideas?

Thank you.

With just the textures and a black material:

Vertex Shader Code:


#version 330 core

#extension GL_ARB_explicit_attrib_location : require

// Input vertex data, different for all executions of this shader.

layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 Normals;
layout(location = 2) in vec2 vUV;

// Output data ; will be interpolated for each fragment.

out vec3 SurfaceNormal;
out vec4 vertexPosition;
out vec2 TextureCoordinates;

// Values that stay constant for the whole mesh.

uniform mat4 MVP;
uniform mat3 NormalMatrix;

void main(){	

	gl_Position = vertexPosition = MVP * vec4(vPosition, 1.0);	
	SurfaceNormal = normalize(NormalMatrix * Normals);
	TextureCoordinates = vUV;
	
}


Fragment Shader Code:


#version 330
#extension GL_ARB_explicit_attrib_location : require

//
// These values vary per Mesh
//

//
// Base Material Color.
//

uniform vec4		MaterialColor;

//
// Material Ambient Color.
//

uniform vec4		AmbientMeshColor;

//
// Material Emissive Color.  
//

uniform vec4		EmissiveMeshColor;

//
// Material Diffuse Color.
//

uniform vec4		DiffuseMeshColor;

//
// Material Specular Color.
//

uniform vec4		SpecularMeshColor;

//
// Material Mesh Shininess
//

uniform float		MeshShininess;

//
// Whether Materials are enabled at all.
//

uniform float		IfEnableTextures;

//
// Whether the object itself has Materials.
//

uniform float		ObjectHasTextureFile;

//
// Whether I am drawing the skybox or not.
//

uniform float		DrawingSkyBox;

//
// Wireframe Settings
//

uniform float		EnableWireframe;

uniform vec4		WireframeColor;

uniform float		EnableLighting;
uniform float		EnableSun;

uniform vec3		SunDirection;
uniform vec3		LightHalfVector;
uniform vec4		SunColor;
uniform vec4		SunSpotCutoff;
uniform float		SunLightStrength;

uniform float		TextureCoordinateDebug;
uniform float		TextureClamping;

uniform sampler2D 	MainTextureSampler; 

in vec4 			vertexPosition;  // position of the vertex (and fragment) in world space
in vec3 			SurfaceNormal;  // surface normal vector in world space
in vec2 			TextureCoordinates; // Texture coordinates...

uniform mat4 		InverseView;

vec4 				MaterialTextureColor;

out vec4 			finalColor;

struct lightSource
{

	vec4 position;
	vec4 diffuse;
	vec4 specular;
	float constantAttenuation, linearAttenuation, quadraticAttenuation;
	float spotCutoff, spotExponent;
	vec3 spotDirection;
  
};

lightSource light0 = lightSource(

  vec4(0.0,  1.0,  3.0, 1.0),
  vec4(1.0,  0.984, 0.569, 1.0),
  vec4(1.0,  1.0,  1.0, 1.0),
  0.0, 1.0, 0.0,
  180.0, 0.0,
  vec3(0.0, 0.0, 0.0)
  
);

void DrawSkyBox() {

	finalColor = texture(MainTextureSampler, TextureCoordinates);

}

void DrawWireFrame() {

	finalColor = WireframeColor;

}

void SunlightWithoutMaterials() {

	vec3 normalDirection = normalize(SurfaceNormal);
	vec3 viewDirection = normalize(vec3(InverseView * vec4(0.0, 0.0, 0.0, 1.0) - vertexPosition));
	vec3 lightDirection;
	float attenuation;
	
	attenuation = 1.0; // no attenuation
    lightDirection = normalize(vec3(light0.position));

	vec3 ambientLighting = vec3(MaterialColor) * vec3(AmbientMeshColor);
 
	vec3 diffuseReflection = attenuation * vec3(light0.diffuse) * vec3(DiffuseMeshColor) * max(0.0, dot(normalDirection, lightDirection));

	vec3 specularReflection;
	
	if (dot(normalDirection, lightDirection) < 0.0)
	
	{
		specularReflection = vec3(0.0, 0.0, 0.0);
	}
	
	else
	{
		specularReflection = attenuation * vec3(light0.specular) * vec3(SpecularMeshColor) 
			* pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), MeshShininess);
	}

	finalColor = vec4(ambientLighting + diffuseReflection + specularReflection, MaterialColor.a);
	
}

void SunlightWithMaterials() {

	vec3 normalDirection = normalize(SurfaceNormal);
	vec3 viewDirection = normalize(vec3(InverseView * vec4(0.0, 0.0, 0.0, 1.0) - vertexPosition));
	vec3 lightDirection;
	float attenuation;
	
	attenuation = 1.0;
    lightDirection = normalize(vec3(light0.position));

	vec3 ambientLighting = vec3(MaterialTextureColor) * vec3(AmbientMeshColor);
 
	vec3 diffuseReflection = attenuation * vec3(light0.diffuse) * vec3(DiffuseMeshColor) * max(0.0, dot(normalDirection, lightDirection));

	vec3 specularReflection;
	
	if (dot(normalDirection, lightDirection) < 0.0)
	{
	
		specularReflection = vec3(0.0, 0.0, 0.0);
		
	}
	else
	{
	
		specularReflection = attenuation * vec3(light0.specular) * vec3(SpecularMeshColor) 
			* pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), MeshShininess);
			
	}

	finalColor = vec4(ambientLighting + diffuseReflection + specularReflection, MaterialColor.a);

}

void LightingWithoutMaterials() {

	if (EnableLighting == 1.0 && EnableSun == 1.0) {
	
		SunlightWithoutMaterials();
	
	} else if (EnableLighting == 1.0) {
	
		finalColor = min(MaterialColor * AmbientMeshColor, vec4(1.0));
	
	} else {
	
		finalColor = MaterialColor;
	
	}
	
}

void LightingWithMaterials() {

	if (EnableLighting == 1.0 && EnableSun == 1.0) {
	
		SunlightWithMaterials();
	
	} else if (EnableLighting == 1.0) {
	
		finalColor = min(MaterialTextureColor * AmbientMeshColor, vec4(1.0));
	
	} else {
	
		finalColor = MaterialTextureColor;
	
	}
	
}

void main() {

	if (TextureCoordinateDebug == 1) {
	
		finalColor = vec4(TextureCoordinates, 0.0, 1.0);
		
	} else if (EnableWireframe == 1.0) {
	
		DrawWireFrame();
		
	} else if (DrawingSkyBox == 1.0) {
		
		DrawSkyBox();
		
	} else {
	
		if (IfEnableTextures != 1.0 && ObjectHasTextureFile != 1.0) {
		
			LightingWithoutMaterials();
		
		} else {
		
			MaterialTextureColor = texture(MainTextureSampler, TextureCoordinates);
		
			LightingWithMaterials();
		
		}
	
	}

}

Hmm, there is a ton of shader code here and lots of it is not relevant, making it a bit tricky to follow what is going on. It seems your code comments say that vertexPosition is in world coordinates, but the vertex shader transforms it to clip space (it applies MVP) and your normal is in eye space (since you transform it with the normal matrix) - in general make sure that all positions/directions you use for lighting calculations are in the same coordinate system (view or world space are common choices).