🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

OpenGL 4 multiple shadow maps

Started by
26 comments, last by taby 1 year, 8 months ago

I also added in a “light enabled“ flag, to skip lights that aren’t on.

yeah my scenes aren’t complex yet. ?

I gotta say though… it takes a very long time to initialize 24 8192x8192 cube maps! Renders fast for the knight character! ?

Advertisement

taby said:
cube maps!

Oh, so 24 shadowed spotlights are not enough for you. It has to be omnidirectional lights, of course. That's 168 renders at 8k per frame. :O
RTX 4090 owners will be happy they get some meat. ; )

Though, it makes be a bit sad you do all this just for a binary shadow on or off result.
Why don't you accumulate the light as usual, so one can actually see that's multiple light sources going on?

I see what you mean. By no means is the shading perfect at this time. I will try your accumulation method!

taby said:
I will try your accumulation method!

It's not mine. The universe has invented it! : )

@joej – I was wondering if you'd like to take a crack at the shader? How would I go about it?

https://github.com/sjhalayka/obj_ogl4/blob/main/point.fs.glsl

Here's a try:

The code is:

#version 430 core
out vec4 FragColor;

in VS_OUT{
	vec3 FragPos;
	vec3 Normal;
	vec2 TexCoords;
	vec3 mvPosition;
} fs_in;




const int max_num_lights = 24;

uniform sampler2D diffuseTexture;
uniform sampler2D specularTexture;

uniform samplerCube depthMaps[max_num_lights];

uniform vec3 lightPositions[max_num_lights];
uniform vec3 lightColours[max_num_lights];
uniform int lightEnabled[max_num_lights];








uniform vec3 viewPos;

uniform float far_plane;
uniform int shadows = 1;
uniform int flat_draw = 0;
uniform vec3 flat_colour;


vec3 MaterialKd = vec3(1.0, 1.0, 1.0);
vec3 MaterialKs = vec3(1.0, 0.5, 0.0);
vec3 MaterialKa = vec3(0, 0, 0);//vec3(0.0, 0.025, 0.075);
float MaterialShininess = 1;


vec3 phongModelDiffAndSpec(bool do_specular, vec3 lp, int index)
{
	vec3 n = fs_in.Normal;
	vec3 s_light1 = normalize(vec3(lp.xyz) - fs_in.mvPosition);

	vec3 v = normalize(-fs_in.mvPosition.xyz);
	vec3 r_light1 = reflect(-s_light1, n);

	float sDotN_light1 = max(dot(s_light1, n), 0.0);

	vec3 diffuse_light1 = lightColours[index] * texture(diffuseTexture, fs_in.TexCoords).rgb * sDotN_light1;

	vec3 spec_light1 = vec3(0.0);

	if (sDotN_light1 > 0.0)
	{
		spec_light1.x = MaterialKs.x * pow(max(dot(r_light1, v), 0.0), MaterialShininess);
		spec_light1.y = MaterialKs.y * pow(max(dot(r_light1, v), 0.0), MaterialShininess);
		spec_light1.z = MaterialKs.z * pow(max(dot(r_light1, v), 0.0), MaterialShininess);
	}


	vec3 n2 = fs_in.Normal;

	vec3 s2_light1 = normalize(vec3(-lp) - fs_in.mvPosition);

	vec3 v2 = normalize(-fs_in.mvPosition.xyz);

	vec3 r2_light1 = reflect(-s2_light1, n2);



	float sDotN2_light1 = max(dot(s2_light1, n2) * 0.5f, 0.0);




	vec3 diffuse2_light1 = lightColours[index] * 0.25 * MaterialKa * sDotN2_light1;



	float k_light1 = (1.0 - sDotN_light1) / 2.0;



	vec3 ret_light1 = diffuse_light1 + diffuse2_light1 + MaterialKa * k_light1;

	if (do_specular)
	{
		ret_light1 = ret_light1 + spec_light1;
	}

	return (ret_light1);// + ret_light2);///2.0;
}





float get_shadow(vec3 lp, samplerCube dmap)
{
	float shadow = 0.0;

	// get vector between fragment position and light position
	vec3 fragToLight = fs_in.FragPos - lp;
	// ise the fragment to light vector to sample from the depth map    
	float closestDepth = texture(dmap, fragToLight).r;
	// it is currently in linear range between [0,1], let's re-transform it back to original depth value
	closestDepth *= far_plane;
	// now get current linear depth as the length between the fragment and light position
	float currentDepth = length(fragToLight);
	// test for shadows
	float bias = 0.05; // we use a much larger bias since depth is now in [near_plane, far_plane] range
	shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;

	//shadow = 1 - shadow;

	return shadow;

}



void main()
{
//	FragColor = texture(diffuseTexture, fs_in.TexCoords);
//	return;	
	
	if(flat_draw == 1)
	{
		FragColor = vec4(flat_colour, 1.0);
		return;
	}

	MaterialKs *= texture(specularTexture, fs_in.TexCoords).rgb;

	float shadow = 1.0;

	for (int i = 0; i < max_num_lights; i++)
	{
		if (lightEnabled[i] == 0)
			continue;

		shadow -= get_shadow(lightPositions[i], depthMaps[i]);;
	}

	shadow = clamp(shadow, 0.0, 1.0);

	float brightest_contribution = shadow;

/*	for (int i = 0; i < max_num_lights; i++)
	{
		if (lightEnabled[i] == 0)
			continue;

		float s = get_shadow(lightPositions[i], depthMaps[i]);

		if (s > brightest_contribution)
			brightest_contribution = s;
	}

	*/




	vec3 diffAndSpec = vec3(0, 0, 0);

	if (brightest_contribution == 1.0)
	{
		for (int i = 0; i < max_num_lights; i++)
		{
			if (lightEnabled[i] == 0)
				continue;

			diffAndSpec += phongModelDiffAndSpec(true, lightPositions[i], i++);
		}

		FragColor = vec4(diffAndSpec, 1.0);// + vec4(diffAndSpec * shadow + MaterialKa*(1.0 - shadow), 1.0);
	}
	else
	{
		for (int i = 0; i < max_num_lights; i++)
		{
			if (lightEnabled[i] == 0)
				continue;

			diffAndSpec += phongModelDiffAndSpec(false, lightPositions[i], i++);
		}

		FragColor = vec4(diffAndSpec * brightest_contribution + MaterialKa * (1.0 - brightest_contribution), 1.0) + vec4(diffAndSpec, 1.0) + vec4(diffAndSpec * brightest_contribution + MaterialKa * (1.0 - brightest_contribution), 1.0);
		FragColor /= 3;
	}

	FragColor = pow(FragColor, vec4(1.0 / 2.2));


	return;
}

Also, there is some kind of acne in the shadows still. I tried adjusting the bias in the shader, to no avail. Any ideas?

This is the lighting system that I'm using: https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows

	if (brightest_contribution == 1.0)
	{
		for (int i = 0; i < max_num_lights; i++)
		{
			//...
		}

	}
	else
	{
		for (int i = 0; i < max_num_lights; i++)
		{
			//...
		}

	}

This code section gives a performance problem.

Some threads will enter the if, others will enter the else branch. Which is no problem.
But then they do a loop within the branch. In practice this doubles your iteration count, because half of threads will wait, doing nothing while the other half is processing the loop.

In such cases you want to get the branch out of the loop, even if this increases code complexity within the loop.
It would be even better to have a little branch within the loop, but having just one loop not two.

taby said:
Also, there is some kind of acne in the shadows still. I tried adjusting the bias in the shader, to no avail. Any ideas?

I'm too confused to figure out where the shadows should come from.
It looks like the top side of the box should shadow the low front side facing the camera.
But if this is true, the front side would be a back face seen from the light source, so it should be in 100% shadow without artifacts because of that.

Looking at your code again it seems indeed you don't have such back face check for the light. So adding it should fix the issue, and also prevents a need to fetch shadow map for back faces. (Reduces bandwidth for the cost of a little branch)

Ok I have it figured out now… just have to code it. I see exactly what you meant, I believe. Screenshots soon. This should also result in coloured shadows.

This topic is closed to new replies.

Advertisement