Sign in to follow this  
Solid_Spy

Very strange GLSL problem. Objects not rendering when accessing shadowMaps

Recommended Posts

Solid_Spy    708

I have a very strange problem with rendering a scene, even with one point shadow map.

 

NOTE: This problem has been solved. Apparently I was trying to read my cubeMaps into an array of samplerCubes, but this does not work for me for some reason.

 

I am rendering a scene with one floor with a shader which recieves a singe shadow cube map, and 9 cubes with a light shader with no shadow map.

 

Whenever I render the scene without testing for the shadow map depth comparison, it renders just fine (but without the shadows), but if i render the scene WITH shadow map depth testing, the floor just... disappears ohmy.png

 

It doesn't give me an error message or anything.

 

Here are pictures of what I am talking about:

 

Without shadow map depth testing:

[url=http://s1298.photobucket.com/user/Solid_spy/media/shadow_map1_zps44a91e8b.png.html]shadow_map1_zps44a91e8b.png[/URL]

 

With shadow map depth testing:

[url=http://s1298.photobucket.com/user/Solid_spy/media/shadow_map2_zpsa254056f.png.html]shadow_map2_zpsa254056f.png[/URL]

 

Here is the GLSL code for the floor object (specular code omitted):

#version 400

in vec2 outUV;
in vec3 outNormals;
in vec4 outPosition;
in vec4 outEyePosition;

out vec4 outColor;

uniform vec4 diffuseColor;
uniform vec4 specularColor;
uniform float diffuseAmount;
uniform float specularAmount;
uniform float specularOffset;
uniform float ambientAmount;
uniform float emmisionAmount;
uniform unsigned int specularHardness;

uniform vec3 lightPositions[8];
uniform vec3 lightColors[8];
uniform float lightIntensities[8];
uniform float lightDistances[8];

uniform sampler2D diffuse;
uniform samplerCube shadowCubeMaps[8];

vec3 calcPointLightColor(int index, inout vec3 lightDirection, vec3 viewDirection, vec3 currentNormal, float inShadow)
{
    float lightDistance;
    float lightIntensity;

    vec3 lightColor;
    lightColor = vec3(0.0, 0.0, 0.0);

    if(inShadow == 0.0)
    {
        lightDistance = lightDistances[index];

        lightDirection = outPosition.xyz - lightPositions[index];
        lightDistance = length(lightDirection) / lightDistance;
        lightDistance = clamp(lightDistance, 0.0, 1.0);
        lightDistance = (lightDistance * -1.0) + 1.0;
        lightDirection = normalize(lightDirection);

        lightIntensity = dot(currentNormal, -lightDirection);
        if(lightIntensity < 0.0)
        {
            lightIntensity = 0.0;
        }
        lightIntensity = lightIntensity * lightDistance;

        lightColor = vec3((lightColors[index] * lightIntensities[index]) * lightIntensity);
    }

    return lightColor;
}

float shadowMapComparison(int index)
{
    float lengthToPixel;
    float shadowDistance;
    float inShadow1;

    inShadow1 = 0.0;

    vec3 directionToShadowMap = outPosition.xyz - lightPositions[index];
    shadowDistance = texture(shadowCubeMaps[index], directionToShadowMap).r;

    lengthToPixel = length(directionToShadowMap);

    if(shadowDistance + 0.001 >= lengthToPixel)
    {
        inShadow1 = 1.0;
    }
    else
    {
        inShadow1 = 0.0;
    }
    return inShadow1;
}

void main()
{
    vec3 viewDirection;
    vec3 currentNormal;
    vec3 lightDirections[8];

    vec4 finalColor;
    vec4 diffuseColorFinal;

    float inShadow[8];

    diffuseColorFinal = diffuseColor * diffuseAmount;
    
    currentNormal = normalize(outNormals);

    viewDirection = outPosition.xyz - outEyePosition.xyz;
    
    viewDirection = normalize(viewDirection);
    viewDirection = -viewDirection;
    
    inShadow[0] = shadowMapComparison(0);

    finalColor += vec4(calcPointLightColor(0, lightDirections[0], viewDirection, currentNormal, inShadow[0]), 1.0);
    finalColor.a = 1.0;

    finalColor = finalColor * vec4(texture(diffuse, outUV).rgb, 1.0);

    finalColor = finalColor * diffuseColorFinal;

    outColor = finalColor;
}

So yeah. The shadow maps are fine, I debugged them by outputting to a quad, and they look fine. They are point light shadow maps, so they check for distance stored in the red component, instead of a depth component, for spherical distance.

 

I am guessing this is just a runtime GLSL error, but I cannot figure out what I am doing wrong.

 

I am following this tutorial: http://ogldev.atspace.co.uk/www/tutorial43/tutorial43.html

Edited by Solid_Spy

Share this post


Link to post
Share on other sites
L. Spiro    25638

Why are you allowing lights to modify the alpha component of the diffuse value?

 

Why is specular not affected by shadows?

Why are you lighting via 8 speculars but only 1 diffuse?

Why is your shadowing term the reverse of what it should be?  It’s not a boolean, it is a factor. 1.0 means completely not in shadows.  0.0 means totally in shadows.

Your link is not valid so I can’t compare with what they are doing, but there are no worthwhile tutorials that teach using 1 = in shadow and 0 = not in shadow.

 

Why don’t you see if you are actually drawing the floor when you have shadow maps enabled?

If you are, why not remove code section-by-section until it appears?

 

If it turns out that it is not rendering because of the alpha value, why are you using alpha testing for opaque objects?

 

 

L. Spiro

Edited by L. Spiro

Share this post


Link to post
Share on other sites
Solid_Spy    708

"Why are you allowing lights to modify the alpha component of the diffuse value?"

 

Well I have to output a vec4 color to the back buffer, in case I ever use alpha blending, so I add an extra 1.0 to the end of the light value when adding it to the final color. I changed the default color back to vec4(0.0, 0.0, 0.0, 1.0), but no change. I'm not using alpha blending, but I plan to with other objects in the future.

 

"Why is specular not affected by shadows?"

 

I want to test it with diffuse first before testing it with specular. If the diffuse doesn't work, then the specular wont work either. It would be a wasted effort.

 

"Why are you lighting via 8 speculars but only 1 diffuse?"

 

My bad. At the moment I left it in there regardless since i'm only testing the diffuse. I commented it out for now.

 

"Why is your shadowing term the reverse of what it should be?  It’s not a boolean, it is a factor. 1.0 means completely not in shadows.  0.0 means totally in shadows.

Your link is not valid so I can’t compare with what they are doing, but there are no worthwhile tutorials that teach using 1 = in shadow and 0 = not in shadow."

 

I don't know what is wrong with the link. It's ogldev.atspace.co.uk, the 43 tutorial. I have no excuse for the floating point, other than that i've never used bools in glsl and was more familiar with floats, I changed it to a bool.

 

"Why don’t you see if you are actually drawing the floor when you have shadow maps enabled?

If you are, why not remove code section-by-section until it appears?
 

I've tried that multiple times, and the only like of code that makes things work when being commented out is this one:

bool shadowMapComparison(int index)
{
	float lengthToPixel;
	float shadowDistance;
	bool inShadow1;

	inShadow1 = false;

	vec3 directionToShadowMap = outPosition.xyz - lightPositions[index];

        //The culprit
	//shadowDistance = texture(shadowCubeMaps[index], directionToShadowMap).r;

	lengthToPixel = length(directionToShadowMap);

	if(shadowDistance + 0.001 >= lengthToPixel)
	{
		inShadow1 = true;
	}
	else
	{
		inShadow1 = false;
	}
	return(inShadow1);
}

"If it turns out that it is not rendering because of the alpha value, why are you using alpha testing for opaque objects?"

 

The alpha value isn't doing anything, since i'm just adding 0.0 to 1.0, which gives 1.0 regardless, however I do plan on using this same shader for both alpha and opaque objects.

 

And I swear I am sending the texture over to it properly. This is the function I use in C++ to send the light data over to the shader for every object:

void RenderingEngine::UpdateRenderQueueNodeLightData(RenderQueueNode& renderQueueNode,
GLuint& currentShader)
{
	GLuint location;

	glm::vec3 lightPosition;
	glm::vec3 lightColor;

	float lightIntensity;
	float lightDistance;

	for(unsigned int i = 0; i < 8; i++)
	{
		lightPosition =
				renderQueueNode.renderingComponent->GetLight(i).lightPosition;

		location = glGetUniformLocation(currentShader, lightPosStr[i].c_str());
		glUniform3fv(location, 1, (GLfloat*)&lightPosition);
	}

	for(unsigned int i = 0; i < 8; i++)
	{
		lightColor =
				renderQueueNode.renderingComponent->GetLight(i).lightColor;

		location = glGetUniformLocation(currentShader, lightColStr[i].c_str());
		glUniform3fv(location, 1, (GLfloat*)&lightColor);
	}

	for(unsigned int i = 0; i < 8; i++)
	{
		lightIntensity =
				renderQueueNode.renderingComponent->GetLight(i).lightIntensity;

		location = glGetUniformLocation(currentShader, lightIntStr[i].c_str());
		glUniform1f(location, lightIntensity);
	}

	for(unsigned int i = 0; i < 8; i++)
	{
		lightDistance =
				renderQueueNode.renderingComponent->GetLight(i).lightDistance;

		location = glGetUniformLocation(currentShader, lightDisStr[i].c_str());
		glUniform1f(location, lightDistance);
	}

	switch(renderQueueNode.shaderIndex)
	{
	case LIGHT_SHAD_1D :
	case LIGHT_SHAD_1D_1N_1S :
	case LIGHT_SHAD_1D_ALPHA_CLIP :
	case LIGHT_SHAD_1D_1N_1S_ALPHA_CLIP :
	case LIGHT_SHAD_INST_1D :
	case LIGHT_SHAD_INST_1D_1N_1S :
	case LIGHT_SHAD_REFL_1D :
	case LIGHT_SHAD_REFL_1D_1N_1S :
	case LIGHT_SHAD_BONE_ANIM_1D :
	case LIGHT_SHAD_BONE_ANIM_1D_1N_1S :
	case LIGHT_SHAD_BONE_ANIM_REFL_1D :
	case LIGHT_SHAD_BONE_ANIM_REFL_1D_1N_1S :
	case VLIGHT_SHAD_1D :
		location = glGetUniformLocation(currentShader, "shadowCubeMaps[0]");
					glUniform1i(location, 12);

					glActiveTexture(GL_TEXTURE0 + 12);
					glBindTexture(GL_TEXTURE_2D, renderQueueNode.renderingComponent->GetLight(0).shadowMap);

		break;
	default:
		break;
	}
}
Edited by Solid_Spy

Share this post


Link to post
Share on other sites
L. Spiro    25638

I don't know what is wrong with the link. It's ogldev.atspace.co.uk, the 43 tutorial. I have no excuse for the floating point, other than that i've never used bools in glsl and was more familiar with floats, I changed it to a bool.

That is exactly the opposite of what I said. Shadowing is not a boolean.

 

The alpha value isn't doing anything, since i'm just adding 0.0 to 1.0, which gives 1.0 regardless

That’s only true (partially) because your lighting is wrong.
finalColor = finalColor + calcPointLightColor(0, lightDirections[0], viewDirection, currentNormal, inShadow[0]);
should be:
finalColor *= calcPointLightColor(0, lightDirections[0], viewDirection, currentNormal, inShadow[0]);
 
But it’s not really true.
calcPointLightColor() returns [X, X, X, 1] if inShadow is not 0.0, and [X, X, X, 0] otherwise.  Whether you add (wrong) or multiply (correct), light is modifying your diffuse alpha in one condition or the other.

I've tried that multiple times, and the only like of code that makes things work when being commented out is this one:

You failed to normalize shadowDistance.



Is this shader only being run on the ground?
If so, then you may have a compiler or linker error on that shader. You should be checking all OpenGL ES errors and compilation success religiously.


L. Spiro

Share this post


Link to post
Share on other sites
Solid_Spy    708

"That is exactly the opposite of what I said. Shadowing is not a boolean."

 

Ah, ok. For some reason I misunderstood what you said earlier. Will change back to float.


 
"That’s only true (partially) because your lighting is wrong.
finalColor = finalColor + calcPointLightColor(0, lightDirections[0], viewDirection, currentNormal, inShadow[0]);
should be:
finalColor *= calcPointLightColor(0, lightDirections[0], viewDirection, currentNormal, inShadow[0]);
 
But it’s not really true.
calcPointLightColor() returns [X, X, X, 1] if inShadow is not 0.0, and [X, X, X, 0] otherwise.  Whether you add (wrong) or multiply (correct), light is modifying your diffuse alpha in one condition or the other."

 

Ah, I see now. I'm gonna just use vec3's instead just cuz I won't really need the alpha for the lights. Though I'm a bit confused. Aren't lights supposed to be added together? If I multiply a red light(vec3(1.0, 0.0, 0.0)) with a blue light(vec3(0.0, 1.0, 0.0)), the lights should cancel out. First, I add all the colored lights together, then I multiply it against the diffuse. I try this and I get no artifacts.
 

"You failed to normalize shadowDistance."

 

I'm confused. Why would I need to normalize it? if a distance value in the r component of the shadowMap is 5.0 and is sent to shadowDistance, and the distance between the pixel and light is calculated to be 4.9 and is sent to lengthToPixel, I want to check that the distance value is greater than the shadow map value for it to be in shadow. This is exactly the way it is done in the tutorial. What is it that normalizing would do to change this? As far as I know only vectors can be normalized, not floats. I'm not quite sure what you mean.

"Is this shader only being run on the ground?"

 

Yes. Only the ground.

"If so, then you may have a compiler or linker error on that shader. You should be checking all OpenGL ES errors and compilation success religiously."

 

I check for errors using glGetShaderIV and glGetShaderInfoLog. I don't get any unless I have a typo or a missing semicolon. I've been error checking the shiznitz out of this thing, and I got nothing.

Edited by Solid_Spy

Share this post


Link to post
Share on other sites
Solid_Spy    708

UPDATE: Ok, apparently the shadow map ISN'T being sent to the shader for some reason -.- (even though the light data is, which is odd since it's in the same struct as the shadow map). I don't know why, but I tried projecting the shadow map onto the floor using:

    vec3 directionToShadowMap = outPosition.xyz - lightPositions[0];
    finalColor = finalColor * vec4(texture(shadowCubeMaps[0], directionToShadowMap).r, 0.0, 0.0, 1.0);

but I get nothing but black.

 

It's very strange, because it was working previously. I will get back to you guys once I manage to even get the shadow map into the shader in the first place.

Edited by Solid_Spy

Share this post


Link to post
Share on other sites
L. Spiro    25638

Aren't lights supposed to be added together?

Yes but your variable names are confusing me (so yes your code was correct).
Why don’t you add them into a variable called “diffuseGather” and “specularGather”?
Then those get multiplied by the diffuse and specular, and then they are added together.
It is not against the law to make your code clear by using totally separate values to gather all your diffuse, and another value to gather all your specular, etc. When your variables are named, “finalColor” and “diffuseColorFinal”, it is pretty hard to follow the flow and to see what part of code is meant to do what.
In any case, you didn’t initialize finalColor and diffuseColorFinal to 0.

 

I'm confused. Why would I need to normalize it?

Because you are sampling a cube texture with it.
But I am going out of my mind all over the place in this topic for some reason. You don’t need to normalize to sample a cube texture. I am being retarded.

 

Ah, ok. For some reason I misunderstood what you said earlier. Will change back to float.

But you are still using it as a boolean. As I said. It is a factor.  1 = not in shadow.
Why?
 
fShadowFactor[0] = getShadow( 0 );
fShadowFactor[1] = getShadow( 1 );
vec3 diffuseLightGather = vec3( 0.0, 0.0, 0.0 );
diffuseLightGather += calcLight( 0 ) * fShadowFactor[0];
diffuseLightGather += calcLight( 1 ) * fShadowFactor[1];
It’s a factor. You don’t if/else it like a boolean, you multiply it (hence 0 = shadowed, 1 = no shadow).


Yes. Only the ground.

Replace the “offensive” line with a hard-coded value such as 1.0.


L. Spiro

Share this post


Link to post
Share on other sites
Solid_Spy    708
Replace the “offensive” line with a hard-coded value such as 1.0.

 

 

Ah, It seems to work this way.

 

When replacing the line with shadowDistance = 5.0, I end up with this result:

 

[URL=http://s1298.photobucket.com/user/Solid_spy/media/shadow_map3_zpsa8692179.png.html]shadow_map3_zpsa8692179.png[/URL]

 

I guess this means that the algorithm is correct, just that the shadow map really isn't getting sent in properly. I will also change my variables like you suggested. And thank you for all your help ^^.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this