OpenGL directional light creating black spots
- by AnonymousDeveloper
I probably ought to start by saying that I suspect the problem is that one of my vectors is not in the correct "space", but I don't know for sure.
I am having a strange problem with a directional light. When I move the camera away from (0.0, 0.0, 0.0) it creates tiny black spots that grow larger as the distance increases. I apologize ahead of time for the length of the code.
Vertex shader:
#version 410 core
in vec3 vf_normal;
in vec3 vf_bitangent;
in vec3 vf_tangent;
in vec2 vf_textureCoordinates;
in vec3 vf_vertex;
out vec3 tc_normal;
out vec3 tc_bitangent;
out vec3 tc_tangent;
out vec2 tc_textureCoordinates;
out vec3 tc_vertex;
uniform mat3 vf_m_normal;
uniform mat4 vf_m_model;
uniform mat4 vf_m_mvp;
uniform mat4 vf_m_projection;
uniform mat4 vf_m_view;
uniform float vf_te_inner;
uniform float vf_te_outer;
void main() {
tc_normal = vf_normal;
tc_bitangent = vf_bitangent;
tc_tangent = vf_tangent;
tc_textureCoordinates = vf_textureCoordinates;
tc_vertex = vf_vertex;
gl_Position = vf_m_mvp * vec4(vf_vertex, 1.0);
}
Tessellation Control shader:
#version 410 core
layout (vertices = 3) out;
in vec3 tc_normal[];
in vec3 tc_bitangent[];
in vec3 tc_tangent[];
in vec2 tc_textureCoordinates[];
in vec3 tc_vertex[];
out vec3 te_normal[];
out vec3 te_bitangent[];
out vec3 te_tangent[];
out vec2 te_textureCoordinates[];
out vec3 te_vertex[];
uniform float vf_te_inner;
uniform float vf_te_outer;
uniform vec4 vf_l_color;
uniform vec3 vf_l_position;
uniform mat4 vf_m_depthBias;
uniform mat4 vf_m_model;
uniform mat4 vf_m_mvp;
uniform mat4 vf_m_projection;
uniform mat4 vf_m_view;
uniform sampler2D vf_t_diffuse;
uniform sampler2D vf_t_normal;
uniform sampler2DShadow vf_t_shadow;
uniform sampler2D vf_t_specular;
#define ID gl_InvocationID
float getTessLevelInner(float distance0, float distance1) {
float avgDistance = (distance0 + distance1) / 2.0;
return clamp((vf_te_inner - avgDistance), 1.0, vf_te_inner);
}
float getTessLevelOuter(float distance0, float distance1) {
float avgDistance = (distance0 + distance1) / 2.0;
return clamp((vf_te_outer - avgDistance), 1.0, vf_te_outer);
}
void main() {
te_normal[gl_InvocationID] = tc_normal[gl_InvocationID];
te_bitangent[gl_InvocationID] = tc_bitangent[gl_InvocationID];
te_tangent[gl_InvocationID] = tc_tangent[gl_InvocationID];
te_textureCoordinates[gl_InvocationID] = tc_textureCoordinates[gl_InvocationID];
te_vertex[gl_InvocationID] = tc_vertex[gl_InvocationID];
float eyeToVertexDistance0 = distance(vec3(0.0), vec4(vf_m_view * vec4(tc_vertex[0], 1.0)).xyz);
float eyeToVertexDistance1 = distance(vec3(0.0), vec4(vf_m_view * vec4(tc_vertex[1], 1.0)).xyz);
float eyeToVertexDistance2 = distance(vec3(0.0), vec4(vf_m_view * vec4(tc_vertex[2], 1.0)).xyz);
gl_TessLevelOuter[0] = getTessLevelOuter(eyeToVertexDistance1, eyeToVertexDistance2);
gl_TessLevelOuter[1] = getTessLevelOuter(eyeToVertexDistance2, eyeToVertexDistance0);
gl_TessLevelOuter[2] = getTessLevelOuter(eyeToVertexDistance0, eyeToVertexDistance1);
gl_TessLevelInner[0] = getTessLevelInner(eyeToVertexDistance2, eyeToVertexDistance0);
}
Tessellation Evaluation shader:
#version 410 core
layout (triangles, equal_spacing, cw) in;
in vec3 te_normal[];
in vec3 te_bitangent[];
in vec3 te_tangent[];
in vec2 te_textureCoordinates[];
in vec3 te_vertex[];
out vec3 g_normal;
out vec3 g_bitangent;
out vec4 g_patchDistance;
out vec3 g_tangent;
out vec2 g_textureCoordinates;
out vec3 g_vertex;
uniform float vf_te_inner;
uniform float vf_te_outer;
uniform vec4 vf_l_color;
uniform vec3 vf_l_position;
uniform mat4 vf_m_depthBias;
uniform mat4 vf_m_model;
uniform mat4 vf_m_mvp;
uniform mat3 vf_m_normal;
uniform mat4 vf_m_projection;
uniform mat4 vf_m_view;
uniform sampler2D vf_t_diffuse;
uniform sampler2D vf_t_displace;
uniform sampler2D vf_t_normal;
uniform sampler2DShadow vf_t_shadow;
uniform sampler2D vf_t_specular;
vec2 interpolate2D(vec2 v0, vec2 v1, vec2 v2) {
return vec2(gl_TessCoord.x) * v0 + vec2(gl_TessCoord.y) * v1 + vec2(gl_TessCoord.z) * v2;
}
vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2) {
return vec3(gl_TessCoord.x) * v0 + vec3(gl_TessCoord.y) * v1 + vec3(gl_TessCoord.z) * v2;
}
float amplify(float d, float scale, float offset) {
d = scale * d + offset;
d = clamp(d, 0, 1);
d = 1 - exp2(-2*d*d);
return d;
}
float getDisplacement(vec2 t0, vec2 t1, vec2 t2) {
float displacement = 0.0;
vec2 textureCoordinates = interpolate2D(t0, t1, t2);
vec2 vector = ((t0 + t1 + t2) / 3.0);
float sampleDistance = sqrt((vector.x * vector.x) + (vector.y * vector.y));
sampleDistance /= ((vf_te_inner + vf_te_outer) / 2.0);
displacement += texture(vf_t_displace, textureCoordinates).x;
displacement += texture(vf_t_displace, textureCoordinates + vec2(-sampleDistance, -sampleDistance)).x;
displacement += texture(vf_t_displace, textureCoordinates + vec2(-sampleDistance, sampleDistance)).x;
displacement += texture(vf_t_displace, textureCoordinates + vec2( sampleDistance, sampleDistance)).x;
displacement += texture(vf_t_displace, textureCoordinates + vec2( sampleDistance, -sampleDistance)).x;
return (displacement / 5.0);
}
void main() {
g_normal = normalize(interpolate3D(te_normal[0], te_normal[1], te_normal[2]));
g_bitangent = normalize(interpolate3D(te_bitangent[0], te_bitangent[1], te_bitangent[2]));
g_patchDistance = vec4(gl_TessCoord, (1.0 - gl_TessCoord.y));
g_tangent = normalize(interpolate3D(te_tangent[0], te_tangent[1], te_tangent[2]));
g_textureCoordinates = interpolate2D(te_textureCoordinates[0], te_textureCoordinates[1], te_textureCoordinates[2]);
g_vertex = interpolate3D(te_vertex[0], te_vertex[1], te_vertex[2]);
float displacement = getDisplacement(te_textureCoordinates[0], te_textureCoordinates[1], te_textureCoordinates[2]);
float d2 = min(min(min(g_patchDistance.x, g_patchDistance.y), g_patchDistance.z), g_patchDistance.w);
d2 = amplify(d2, 50, -0.5);
g_vertex += g_normal * displacement * 0.1 * d2;
gl_Position = vf_m_mvp * vec4(g_vertex, 1.0);
}
Geometry shader:
#version 410 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
in vec3 g_normal[3];
in vec3 g_bitangent[3];
in vec4 g_patchDistance[3];
in vec3 g_tangent[3];
in vec2 g_textureCoordinates[3];
in vec3 g_vertex[3];
out vec3 f_tangent;
out vec3 f_bitangent;
out vec3 f_eyeDirection;
out vec3 f_lightDirection;
out vec3 f_normal;
out vec4 f_patchDistance;
out vec4 f_shadowCoordinates;
out vec2 f_textureCoordinates;
out vec3 f_vertex;
uniform vec4 vf_l_color;
uniform vec3 vf_l_position;
uniform mat4 vf_m_depthBias;
uniform mat4 vf_m_model;
uniform mat4 vf_m_mvp;
uniform mat3 vf_m_normal;
uniform mat4 vf_m_projection;
uniform mat4 vf_m_view;
uniform sampler2D vf_t_diffuse;
uniform sampler2D vf_t_normal;
uniform sampler2DShadow vf_t_shadow;
uniform sampler2D vf_t_specular;
void main() {
int index = 0;
while (index < 3) {
vec3 vertexNormal_cameraspace = vf_m_normal * normalize(g_normal[index]);
vec3 vertexTangent_cameraspace = vf_m_normal * normalize(f_tangent);
vec3 vertexBitangent_cameraspace = vf_m_normal * normalize(f_bitangent);
mat3 TBN = transpose(mat3(
vertexTangent_cameraspace,
vertexBitangent_cameraspace,
vertexNormal_cameraspace
));
vec3 eyeDirection = -(vf_m_view * vf_m_model * vec4(g_vertex[index], 1.0)).xyz;
vec3 lightDirection = normalize(-(vf_m_view * vec4(vf_l_position, 1.0)).xyz);
f_eyeDirection = TBN * eyeDirection;
f_lightDirection = TBN * lightDirection;
f_normal = normalize(g_normal[index]);
f_patchDistance = g_patchDistance[index];
f_shadowCoordinates = vf_m_depthBias * vec4(g_vertex[index], 1.0);
f_textureCoordinates = g_textureCoordinates[index];
f_vertex = (vf_m_model * vec4(g_vertex[index], 1.0)).xyz;
gl_Position = gl_in[index].gl_Position;
EmitVertex();
index ++;
}
EndPrimitive();
}
Fragment shader:
#version 410 core
in vec3 f_bitangent;
in vec3 f_eyeDirection;
in vec3 f_lightDirection;
in vec3 f_normal;
in vec4 f_patchDistance;
in vec4 f_shadowCoordinates;
in vec3 f_tangent;
in vec2 f_textureCoordinates;
in vec3 f_vertex;
out vec4 fragColor;
uniform vec4 vf_l_color;
uniform vec3 vf_l_position;
uniform mat4 vf_m_depthBias;
uniform mat4 vf_m_model;
uniform mat4 vf_m_mvp;
uniform mat4 vf_m_projection;
uniform mat4 vf_m_view;
uniform sampler2D vf_t_diffuse;
uniform sampler2D vf_t_normal;
uniform sampler2DShadow vf_t_shadow;
uniform sampler2D vf_t_specular;
vec2 poissonDisk[16] = vec2[](
vec2(-0.94201624, -0.39906216),
vec2( 0.94558609, -0.76890725),
vec2(-0.09418410, -0.92938870),
vec2( 0.34495938, 0.29387760),
vec2(-0.91588581, 0.45771432),
vec2(-0.81544232, -0.87912464),
vec2(-0.38277543, 0.27676845),
vec2( 0.97484398, 0.75648379),
vec2( 0.44323325, -0.97511554),
vec2( 0.53742981, -0.47373420),
vec2(-0.26496911, -0.41893023),
vec2( 0.79197514, 0.19090188),
vec2(-0.24188840, 0.99706507),
vec2(-0.81409955, 0.91437590),
vec2( 0.19984126, 0.78641367),
vec2( 0.14383161, -0.14100790)
);
float random(vec3 seed, int i) {
vec4 seed4 = vec4(seed,i);
float dot_product = dot(seed4, vec4(12.9898, 78.233, 45.164, 94.673));
return fract(sin(dot_product) * 43758.5453);
}
float amplify(float d, float scale, float offset) {
d = scale * d + offset;
d = clamp(d, 0, 1);
d = 1 - exp2(-2.0 * d * d);
return d;
}
void main() {
vec3 lightColor = vf_l_color.xyz;
float lightPower = vf_l_color.w;
vec3 materialDiffuseColor = texture(vf_t_diffuse, f_textureCoordinates).xyz;
vec3 materialAmbientColor = vec3(0.1, 0.1, 0.1) * materialDiffuseColor;
vec3 materialSpecularColor = texture(vf_t_specular, f_textureCoordinates).xyz;
vec3 n = normalize(texture(vf_t_normal, f_textureCoordinates).rgb * 2.0 - 1.0);
vec3 l = normalize(f_lightDirection);
float cosTheta = clamp(dot(n, l), 0.0, 1.0);
vec3 E = normalize(f_eyeDirection);
vec3 R = reflect(-l, n);
float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
float visibility = 1.0;
float bias = 0.005 * tan(acos(cosTheta));
bias = clamp(bias, 0.0, 0.01);
for (int i = 0; i < 4; i ++) {
float shading = (0.5 / 4.0);
int index = i;
visibility -= shading * (1.0 - texture(vf_t_shadow, vec3(f_shadowCoordinates.xy + poissonDisk[index] / 3000.0, (f_shadowCoordinates.z - bias) / f_shadowCoordinates.w)));
}\n"
fragColor.xyz =
materialAmbientColor +
visibility * materialDiffuseColor * lightColor * lightPower * cosTheta +
visibility * materialSpecularColor * lightColor * lightPower * pow(cosAlpha, 5);
fragColor.w = texture(vf_t_diffuse, f_textureCoordinates).w;
}
The following images should be enough to give you an idea of the problem.
Before moving the camera:
Moving the camera just a little.
Moving it to the center of the scene.