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的值,並在片元着色器最後返回的時候將其作用在顏色輸出中,運行代碼,你將會看到:
在這裏插入圖片描述
再如您可以在更新uniformBuffer的時候動態調整光源位置,實現24h日照效果等等,以及更多關於陰影精細化設置,您如果感興趣的話可以自行實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章