Vulkan_Shader—高级光照_阴影_实现

高级光照_阴影_代码实现

根据上节阴影原理及附源码,主要是创建一个深度缓冲视图,然后将其使用到主场景Shader中,以此来实现阴影,大部分工作是在原有代码基础上进行改动,并新增了部分hpp文件来快捷创建各类所需结构体。
本小节,我们主要来讲述下阴影的shader部分:

一、深度贴图shader

首先来看顶点着色器,这也是深度贴图的主要地方,通过仅使用光照MVP矩阵来记录渲染图片中各点的深度值,然后通过二维纹理映射(sampler2D)返还给场景shader进行对比。

#version 450

#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (location = 0) in vec3 inPos;

layout (binding = 0) uniform UBO 
{
	mat4 depthMVP;
	mat4 model;//for test
} ubo;

out gl_PerVertex 
{
    vec4 gl_Position;   
};

 
void main()
{
	gl_Position =  ubo.depthMVP * vec4(inPos, 1.0);
	//gl_Position =  ubo.model *vec4(inPos, 1.0);
}

由于深度缓冲视图中片元着色器不关紧要,故,简单定义即可:

#version 450

#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

//layout(location = 0) out vec4  FragColor;
//layout(location = 0) out float fragmentdepth;

void main() 
{	
    //fragmentdepth = gl_FragCoord.z;
	//FragColor = vec4(vec3(0), 1.0);
}

二、场景shader

顶点着色器:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
	mat4 lightSpace;
	vec3 baseLight;
	float ambientStrength;
	vec3 lightPos;
	float specularStrength ;
	vec3 viewPos;
	vec3 lightDirect;
	vec3 flashColor;
	vec3 flashPos;
	float outerCutOff;
	vec3 flashDir;
	float flashCutOff ;
} ubo;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec3 inNormal;
layout(location = 3) in vec2 inTexCoord;
layout(location = 4) in vec3 inM_ambient;
layout(location = 5) in vec3 inM_diffuse;
layout(location = 6) in vec3 inM_specular;
layout(location = 7) in float inM_shininess;

layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec3 fragNormal;
layout(location = 2) out vec2 fragTexCoord;
layout(location = 3) out vec3 fragBaseLight;
layout(location = 4) out float ambientStrength;
layout(location = 5) out vec3 lightPos;
layout(location = 6) out vec3 fragPos;
layout(location = 7) out float specularStrength;
layout(location = 8) out vec3 viewPos;
//Material
layout(location = 9) out vec3 m_ambient;
layout(location = 10) out vec3 m_diffuse;
layout(location = 11) out vec3 m_specular;
layout(location = 12) out float m_shininess;
layout(location = 13) out vec3 lightDirect;
layout(location = 14) out vec3 flashPos;
layout(location = 15) out vec3 flashDir;
layout(location = 16) out float flashCutOff;
layout(location = 17) out float outerCutOff;
layout(location = 18) out vec3 flashColor;
layout(location = 19) out vec4 outShadowCoord;

layout(push_constant) uniform PushConsts {
	vec3 objPos;
} pushConsts;

const mat4 biasMat = mat4( 
	0.5, 0.0, 0.0, 0.0,
	0.0, 0.5, 0.0, 0.0,
	0.0, 0.0, 1.0, 0.0,
	0.5, 0.5, 0.0, 1.0 );

void main() {
    //gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition + pushConsts.objPos, 1.0);
	//fragPos =vec3( ubo.model * vec4(inPosition+ pushConsts.objPos, 1.0));
    gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
	fragPos =vec3( ubo.model * vec4(inPosition, 1.0));
    fragColor = inColor;
    fragNormal = mat3(transpose(inverse(ubo.model))) *inNormal;
	fragTexCoord = inTexCoord;
	fragBaseLight = ubo.baseLight;
	ambientStrength= ubo.ambientStrength;
	lightPos=ubo.lightPos;
	specularStrength=ubo.specularStrength;
	viewPos=ubo.viewPos;
	m_ambient = inM_ambient;
	m_diffuse = inM_diffuse;
	m_specular = inM_specular;
	m_shininess = inM_shininess;
	lightDirect= ubo.lightDirect;
	flashPos= ubo.flashPos;
	flashDir= ubo.flashDir;
	flashCutOff= ubo.flashCutOff;
	outerCutOff= ubo.outerCutOff;
	flashColor= ubo.flashColor;
	outShadowCoord =  ( biasMat * ubo.lightSpace * ubo.model ) * vec4(inPosition, 1.0);	
}

可以看出,我们在顶点着色器中仅添加了outShadowCoord二维纹理,之后再片元着色器中使用这一参数:

 #version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 1) uniform sampler2D texSampler;
layout(binding = 2) uniform sampler2D shadowMap;

layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec3 fragNormal;
layout(location = 2) in vec2 fragTexCoord;
layout(location = 3) in vec3 fragBaseLight;
layout(location = 4) in float ambientStrength;
layout(location = 5) in vec3 lightPos;
layout(location = 6) in vec3 fragPos;
layout(location = 7) in float specularStrength;
layout(location = 8) in vec3 viewPos;
//Material
layout(location = 9) in vec3 m_ambient;
layout(location = 10) in vec3 m_diffuse;
layout(location = 11) in vec3 m_specular;
layout(location = 12) in float m_shininess;
layout(location = 13) in vec3 lightDirect;
layout(location = 14) in vec3 flashPos;
layout(location = 15) in vec3 flashDir;
layout(location = 16) in float flashCutOff;
layout(location = 17) in float outerCutOff;
layout(location = 18) in vec3 flashColor;
layout(location = 19) in vec4 inShadowCoord;

layout(location = 0) out vec4  FragColor;

vec3 lightAmbient  = vec3( 0.1f, 0.1f, 0.1f);
vec3 lightDiffuse  = vec3( 0.5f, 0.5f, 0.5f);
vec3 lightSpecular = vec3( 0.8f, 0.8f, 0.8f);
float constant = 1.0f;
float linear =  0.09f;
float quadratic = 0.032f;
float distance = length(lightPos - fragPos);
float attenuation = 1.0 / (constant + linear * distance +  quadratic * (distance * distance));

float textureProj(vec4 P, vec2 off)
{
	float shadow = 1.0;
	vec4 shadowCoord = P / P.w;
	if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 ) 
	{
		float dist = texture( shadowMap, shadowCoord.st + off ).r;
		if(shadowCoord.w > 0.0){
		shadow = 2;
		}
		if ( shadowCoord.w > 0.0 && dist < shadowCoord.z ) 
		{
			shadow = 0.3;
		}
	}
	return shadow;
}

void main() {

	vec3 norm = normalize(fragNormal);
    vec3 lightDir = normalize(-lightDirect);
    // 漫反射着色
    float diff =  max(dot(norm, lightDir), 0.0);
    // 镜面光着色
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(normalize(viewPos - fragPos), reflectDir), 0.0), m_shininess);
    // 合并结果
    vec3 ambient  = lightAmbient  * vec3(texture(texSampler, fragTexCoord));
    vec3 diffuse  = lightDiffuse  * diff * vec3(texture(texSampler, fragTexCoord));
    vec3 specular = lightSpecular * spec * vec3(texture(texSampler, fragTexCoord));

	// 计算阴影
	float shadow = textureProj(inShadowCoord / inShadowCoord.w, vec2(0.0));
    vec3 color = (ambient +  shadow * (diffuse + specular)) * fragBaseLight;
	FragColor = vec4(color * shadow, 1.0);

}

通过textureProj函数,我们可以计算出shadow的值,并在片元着色器最后返回的时候将其作用在颜色输出中,运行代码,你将会看到:
Vulkan_Shader—高级光照_阴影_实现_第1张图片
再如您可以在更新uniformBuffer的时候动态调整光源位置,实现24h日照效果等等,以及更多关于阴影精细化设置,您如果感兴趣的话可以自行实现。

你可能感兴趣的:(vulkan,shader)