🎉 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!

Creating Shadows with Vulkan

Started by
2 comments, last by pixma92 2 years, 10 months ago

Hi everyone,

i, am working on my master project and have a lot of trouble with shadows.

I created a little scene with the help of vulkan.

Make my three rendersteps

1st. Geometry Pass

2st. Shadow Pass

3st. Deferred Pass

I got the shadows, but they overlap with my mesh.

I don't know why. I assumed, the reason for this could be the perspective Matrix.

So, I changed this to orthographic, but then there is no visible shadow.

Does anyone have an Idea, does anyone had the same problem in the past and could solve it?

This is the code of my Light Space Matrix Calculation:

LightIndex GraphicsInstance::AddLight(Light& light)
{
	mLightUbo.light[lightIndex] = light.GetLightInformations();

	// Light Transformation Matrix Generation
	float near_plane = 1.0f, far_plane = 64.0f;
	//glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
	//lightProjection[1][1] *= -1;
	glm::mat4 lightProjection = glm::perspective(glm::radians(45.0f), 1.0f, 1.0f, 96.0f);
	glm::mat4 lightView = glm::lookAt(glm::vec3(light.GetPosition()),
		glm::vec3(0.0f, 0.0f, 0.0f),
		glm::vec3(0.0f, 1.0f, 0.0f));

	mLightUbo.lightSpaceMatrix = lightProjection * lightView;
}

Kind regards and thx

Pixma ?

Advertisement

Question is irrevelant to library you use, first thing is to actually put window position and dimensions in pixels to your ortogtaphic matrix func, you dont -10 10., Second thing is that you didn't show shadow calculation code - which is wrong, it had to do with shadowmap resolution, screen dpi and perspective, depending on logic you use you need to address pixels that are not in the shadow but they are, to your question almost all shadowmapping tutorials cover how it is done.

But for now i assume you get the depth from light position and compare to actual shadowmap with wrong comparsion

Everything depends on how you write z values for shadowmap i write them as distance from light to vertex divided by light z far (same code showed below)

float dst = n3ddistance(LightPos, vertex_pos); //worldspace
	

	float lsvdepth = depth from shadowmap
	float vdepth = dst / z_far;  //light z far
	if (vdepth <= lsvdepth)//is not in the shadow
	
	same can be written as
	if (vertex_depth > shadowmap_depth)
	which is where i assume you have bug
	

@WeirdCat

Hello _WeirdCat_,

thanks for your hint.
I replaced

glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
with
glm::mat4 lightProjection = glm::ortho(-(1024.0f / 768.0f), (1024.0f / 768.0f), -(1024.0f / 768.0f), (1024.0f / 768.0f), near_plane, far_plane);

But there is despite of this no shadow visible.
1024 are the with of my window size and 768 is the window height.

edit:

I use the shadow code from Learn Opengl.
The Depth of the shadowmap is calculated like following in the deferred fragment shader:

float closestDepth = texture(shadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;

I am using the following shader code:

Deferred.frag

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform sampler2D texAlbedo;
layout(binding = 1) uniform sampler2D texNormal;
layout(binding = 2) uniform sampler2D texPosition;
layout(binding = 3) uniform sampler2D shadowMap;

layout(location = 1) in vec2 textureCord;

layout(location = 0) out vec4 outColor;

layout(binding = 4) uniform OptionsUniformBuffer {
	int option;
} uob;

struct Light
{
	vec4 position;
	vec4 color;
	float strength;
	mat4 lightSpaceMatrix;
	float direction;
};

layout(set = 0, binding = 5) uniform LightUbo {
	Light lights[8];
	int countLights;
} lUbo;

layout(set = 0, binding = 6) uniform GeneralUniformBufferObject {
	mat4 view;
	mat4 proj;
	vec3 viewPos;
} genUbo;

float ShadowCalculation(vec4 fragPosLightSpace, vec3 FragPos, vec3 Normal)
{
    // perform perspective divide
    vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    // transform to [0,1] range
    projCoords = projCoords * 0.5 + 0.5;
    // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
    float closestDepth = texture(shadowMap, projCoords.xy).r;
    // get depth of current fragment from light's perspective
    float currentDepth = projCoords.z;
    // calculate bias (based on depth map resolution and slope)
    vec3 normal = normalize(Normal);
    vec3 lightShadowDir = normalize(lUbo.lights[0].position.xyz - FragPos);
    float bias = max(0.05 * (1.0 - dot(normal, lightShadowDir)), 0.005);
    // check whether current frag pos is in shadow
    // float shadow = currentDepth - bias > closestDepth  ? 1.0 : 0.0;
    // PCF
    float shadow = 0.0;
    vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
    for(int x = -1; x <= 1; ++x)
    {
        for(int y = -1; y <= 1; ++y)
        {
            float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; 
            shadow += currentDepth - bias > pcfDepth  ? 1.0 : 0.0;        
        }    
    }
    shadow /= 9.0;
    
    // keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
    if(projCoords.z > 1)
        shadow = 0.0;
        
    return shadow;
}

void main() {
	switch(uob.option)
	{
		case 1:
		{
			...
		}
		case n:
		{		
			...
		}
		case 5: // lightning and shadows
		{
			// src: https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping
		
			
			vec3 FragPos = texture(texPosition, textureCord).rgb;
		
			vec3 color = texture(texAlbedo, textureCord).rgb;
			vec3 normal = texture(texNormal, textureCord).rgb;
			
			// ambient
			float ambientStrength = 0.1f;
			vec3 ambient = ambientStrength * lUbo.lights[0].color.xyz;

			// diffuse
			vec3 norm = normalize(normal);
			vec3 lightDir = normalize(lUbo.lights[0].position.xyz - FragPos);
			float diff = max(dot(norm, lightDir), 0.0f);
			vec3 diffuse = diff * lUbo.lights[0].color.xyz;
	
			// specular
			float specularStrength = 0.5;
			vec3 viewDir = normalize(genUbo.viewPos - FragPos);
			vec3 reflectDir = reflect(-lightDir, norm);
			float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
			vec3 specular = specularStrength * spec * lUbo.lights[0].color.xyz;  
	
			// calculate light and shadow
			float shadow = ShadowCalculation( lUbo.lights[0].lightSpaceMatrix  * vec4(FragPos, 1.0), FragPos, normal);
			vec3 lightning = (ambient + (1.0 - 0.99 * shadow) * (diffuse + specular)) * color; 
	
			//outColor = vec4((ambient + diffuse + specular)  * color, 1.0);
			outColor = vec4(lightning, 1.0);
		
			break;
		}
	}
}

Deferred.vert

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(location = 1) out vec2 textureCord;

void main() {
	textureCord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
	gl_Position = vec4(textureCord * 2.0f - 1.0f, 0.0f, 1.0f);
}

shadow.vert

#version 450
#extension GL_ARB_separate_shader_objects : enable

struct Light
{
	vec4 position;
	vec4 color;
	float strength;
	mat4 lightSpaceMatrix;
	float direction;
};

struct Material
{
	float specularStrength;
	float shininess;
};

layout(set = 0, binding = 0) uniform UniformBufferObject {
	Material material;
    mat4 model;
} ubo;

layout(set = 0, binding = 1) uniform LightUbo {
	Light lights[8];
	int countLights;
} lUbo;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec3 inNormal;

out gl_PerVertex 
{
    vec4 gl_Position;   
};


void main() {
	gl_Position =  lUbo.lights[0].lightSpaceMatrix * ubo.model  * vec4(inPosition, 1.0);
}

This topic is closed to new replies.

Advertisement