Monday, February 20, 2017

opengl - Random black pixels GLSL shader bug


I've recently been following a tutorial for writing a game engine in Java using LWJGL 2. I followed the tutorial for writing a fragment shader that utilizes spotlights in GLSL.


The example game currently running in the engine is a spotlight that follows the camera and a plane mesh with a tile texture. When I run the game, when viewing the mesh at certain distances and angles, namely close distances and sharp angles, I run into this interesting bug when certain pixels just go black. This has only occurred when I modified the fragment shader to include spotlights. This can only mean that there is a bug in the fragment shader itself.


The fragment shader code is below. What I believe to be the problematic code is marked with a comment below in the function calcSpotLight.


Update: I have found that the problem was indeed in my graphics card's driver. I just updated the driver and reran the program and indeed received no black pixels.


Edit: It appears that the problem is indeed in the calcSpotLight function, but within the calcSpotLight function, the problem is the calcPointLight function. I still don't know what the exact problem is, but that should narrow down the possible errors.



#version 330

const int MAX_POINT_LIGHTS = 4;
const int MAX_SPOT_LIGHTS = 4;

in vec2 texCoord0;
in vec3 normal0;
in vec3 worldPos0;

out vec4 fragColor;


struct BaseLight
{
vec3 color;
float intensity;
};

struct DirectionalLight
{
BaseLight base;

vec3 direction;
};

struct Attenuation
{
float constant;
float linear;
float exponent;
};


struct PointLight
{
BaseLight base;
Attenuation atten;
vec3 position;
float range;
};

struct SpotLight
{

PointLight pointLight;
vec3 direction;
float cutoff;
};

uniform vec3 baseColor;
uniform vec3 eyePos;
uniform vec3 ambientLight;
uniform sampler2D sampler;


uniform float specularIntensity;
uniform float specularPower;

uniform DirectionalLight directionalLight;
uniform PointLight pointLights[MAX_POINT_LIGHTS];
uniform SpotLight spotLights[MAX_SPOT_LIGHTS];

vec4 calcLight(BaseLight base, vec3 direction, vec3 normal)
{
float diffuseFactor = dot(normal, -direction);


vec4 diffuseColor = vec4(0,0,0,0);
vec4 specularColor = vec4(0,0,0,0);

if(diffuseFactor > 0)
{
diffuseColor = vec4(base.color, 1.0) * base.intensity * diffuseFactor;

vec3 directionToEye = normalize(eyePos - worldPos0);
vec3 reflectDirection = normalize(reflect(direction, normal));


float specularFactor = dot(directionToEye, reflectDirection);
specularFactor = pow(specularFactor, specularPower);

if(specularFactor > 0)
{
specularColor = vec4(base.color, 1.0) * specularIntensity * specularFactor;
}
}


return diffuseColor + specularColor;
}

vec4 calcDirectionalLight(DirectionalLight directionalLight, vec3 normal)
{
return calcLight(directionalLight.base, -directionalLight.direction, normal);
}

vec4 calcPointLight(PointLight pointLight, vec3 normal)
{

vec3 lightDirection = worldPos0 - pointLight.position;
float distanceToPoint = length(lightDirection);

if(distanceToPoint > pointLight.range)
return vec4(0,0,0,0);

lightDirection = normalize(lightDirection);

vec4 color = calcLight(pointLight.base, lightDirection, normal);


float attenuation = pointLight.atten.constant +
pointLight.atten.linear * distanceToPoint +
pointLight.atten.exponent * distanceToPoint * distanceToPoint +
0.0001;

return color / attenuation;
}

vec4 calcSpotLight(SpotLight spotLight, vec3 normal)
{

vec3 lightDirection = normalize(worldPos0 - spotLight.pointLight.position);
float spotFactor = dot(lightDirection, spotLight.direction);

vec4 color = vec4(0,0,0,0);

//This is likely the problematic code, but I'm not 100 percent sure

if(spotFactor > spotLight.cutoff)
{
color = calcPointLight(spotLight.pointLight, normal) *

(1.0 - (1.0 - spotFactor)/(1.0-spotLight.cutoff));
}

return color;
}
void main()
{
vec4 totalLight = vec4(ambientLight,1);
vec4 color = vec4(baseColor, 1);
vec4 textureColor = texture(sampler, texCoord0.xy);


if(textureColor != vec4(0,0,0,0))
color *= textureColor;

vec3 normal = normalize(normal0);

totalLight += calcDirectionalLight(directionalLight, normal);

for(int i = 0; i < MAX_POINT_LIGHTS; i++)
{

if(pointLights[i].base.intensity > 0)
totalLight += calcPointLight(pointLights[i],normal);
}

for(int i = 0; i < MAX_SPOT_LIGHTS; i++)
{
if(spotLights[i].pointLight.base.intensity > 0)
totalLight += calcSpotLight(spotLights[i],normal);
}


fragColor = color * totalLight;
}

I checked to see if there was maybe some division by zero problem or something of the like, but I can't for the life of me figure out what the problem actually is. And since debugging in GLSL is nearly impossible, I've decided that my last possible option is to post my question here.


Here are some example images of the bug in game:


enter image description here Here, the black pixels can be seen at the bottom of the spotlight


enter image description here Here, the black pixels are mostly at the edge of the spotlight


Any help would be appreciated.




No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...