Vulkan_Shader_Day01—光照(物體顏色)

光照之顏色

在學習部分之前,我們需要對上一部分代碼進行部分修改重塑:
1.使用立方體模型來代替測試光照場景。
將原有代碼的loadModel()方法替換成loadCube();

	void loadCube() {
		vertices = {
		  // positions             // colors          // normals          // texture coords
		  {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 1.0f},{0.0f,  0.0f, -1.0f},{0.0f,  0.0f}},
		  {{ 0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 1.0f},{0.0f,  0.0f, -1.0f},{1.0f,  0.0f}},
		  {{ 0.5f,  0.5f, -0.5f}, {1.0f, 0.0f, 1.0f},{0.0f,  0.0f, -1.0f},{1.0f,  1.0f}},
		  {{ 0.5f,  0.5f, -0.5f}, {1.0f, 0.0f, 1.0f},{0.0f,  0.0f, -1.0f},{1.0f,  1.0f}},
		  {{-0.5f,  0.5f, -0.5f}, {1.0f, 0.0f, 1.0f},{0.0f,  0.0f, -1.0f},{0.0f,  1.0f}},
		  {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 1.0f},{0.0f,  0.0f, -1.0f},{0.0f,  0.0f}},

		  {{-0.5f, -0.5f,  0.5f}, {1.0f, 0.0f, 0.0f},{0.0f,  0.0f,  1.0f},{0.0f,  0.0f}},
		  {{ 0.5f, -0.5f,  0.5f}, {1.0f, 0.0f, 0.0f},{0.0f,  0.0f,  1.0f},{1.0f,  0.0f}},
		  {{ 0.5f,  0.5f,  0.5f}, {1.0f, 0.0f, 0.0f},{0.0f,  0.0f,  1.0f},{1.0f,  1.0f}},
		  {{ 0.5f,  0.5f,  0.5f}, {1.0f, 0.0f, 0.0f},{0.0f,  0.0f,  1.0f},{1.0f,  1.0f}},
		  {{-0.5f,  0.5f,  0.5f}, {1.0f, 0.0f, 0.0f},{0.0f,  0.0f,  1.0f},{0.0f,  1.0f}},
		  {{-0.5f, -0.5f,  0.5f}, {1.0f, 0.0f, 0.0f},{0.0f,  0.0f,  1.0f},{0.0f,  0.0f}},

		  {{-0.5f,  0.5f,  0.5f}, {0.0f, 1.0f, 0.0f},{1.0f,  0.0f,  0.0f},{1.0f,  0.0f}},
		  {{-0.5f,  0.5f, -0.5f}, {0.0f, 1.0f, 0.0f},{1.0f,  0.0f,  0.0f},{1.0f,  1.0f}},
		  {{-0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f},{1.0f,  0.0f,  0.0f},{0.0f,  1.0f}},
		  {{-0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f},{1.0f,  0.0f,  0.0f},{0.0f,  1.0f}},
		  {{-0.5f, -0.5f,  0.5f}, {0.0f, 1.0f, 0.0f},{1.0f,  0.0f,  0.0f},{0.0f,  0.0f}},
		  {{-0.5f,  0.5f,  0.5f}, {0.0f, 1.0f, 0.0f},{1.0f,  0.0f,  0.0f},{1.0f,  0.0f}},

		  {{ 0.5f,  0.5f,  0.5f}, {0.0f, 0.0f, 1.0f},{1.0f,  0.0f,  0.0f},{1.0f,  0.0f}},
		  {{ 0.5f,  0.5f, -0.5f}, {0.0f, 0.0f, 1.0f},{1.0f,  0.0f,  0.0f},{1.0f,  1.0f}},
		  {{ 0.5f, -0.5f, -0.5f}, {0.0f, 0.0f, 1.0f},{1.0f,  0.0f,  0.0f},{0.0f,  1.0f}},
		  {{ 0.5f, -0.5f, -0.5f}, {0.0f, 0.0f, 1.0f},{1.0f,  0.0f,  0.0f},{0.0f,  1.0f}},
		  {{ 0.5f, -0.5f,  0.5f}, {0.0f, 0.0f, 1.0f},{1.0f,  0.0f,  0.0f},{0.0f,  0.0f}},
		  {{ 0.5f,  0.5f,  0.5f}, {0.0f, 0.0f, 1.0f},{1.0f,  0.0f,  0.0f},{1.0f,  0.0f}},

		  {{-0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 1.0f},{0.0f, -1.0f,  0.0f},{0.0f,  1.0f}},
		  {{ 0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 1.0f},{0.0f, -1.0f,  0.0f},{1.0f,  1.0f}},
		  {{ 0.5f, -0.5f,  0.5f}, {0.0f, 1.0f, 1.0f},{0.0f, -1.0f,  0.0f},{1.0f,  0.0f}},
		  {{ 0.5f, -0.5f,  0.5f}, {0.0f, 1.0f, 1.0f},{0.0f, -1.0f,  0.0f},{1.0f,  0.0f}},
		  {{-0.5f, -0.5f,  0.5f}, {0.0f, 1.0f, 1.0f},{0.0f, -1.0f,  0.0f},{0.0f,  0.0f}},
		  {{-0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 1.0f},{0.0f, -1.0f,  0.0f},{0.0f,  1.0f}},

		  {{-0.5f,  0.5f, -0.5f}, {1.0f, 1.0f, 1.0f},{0.0f,  1.0f,  0.0f},{0.0f,  1.0f}},
		  {{ 0.5f,  0.5f, -0.5f}, {1.0f, 1.0f, 1.0f},{0.0f,  1.0f,  0.0f},{1.0f,  1.0f}},
		  {{ 0.5f,  0.5f,  0.5f}, {1.0f, 1.0f, 1.0f},{0.0f,  1.0f,  0.0f},{1.0f,  0.0f}},
		  {{ 0.5f,  0.5f,  0.5f}, {1.0f, 1.0f, 1.0f},{0.0f,  1.0f,  0.0f},{1.0f,  0.0f}},
		  {{-0.5f,  0.5f,  0.5f}, {1.0f, 1.0f, 1.0f},{0.0f,  1.0f,  0.0f},{0.0f,  0.0f}},
		  {{-0.5f,  0.5f, -0.5f}, {1.0f, 1.0f, 1.0f},{0.0f,  1.0f,  0.0f},{0.0f,  1.0f}}
		 
		};

		indices = {
		   2, 1, 0, 5, 4, 3,
		   6, 7, 8, 9, 10,11,
		   12,13,14,15,16,17 ,
		   20,19,18,23,22,21,
		   24,25,26,27,28,29 ,
		   32,31,30,35,34,33
		};
	}

2.新增了Vertex結構體中新增了glm::vec3 normal(後續光照中需要使用到)。結構體修改如下:

struct Vertex {
	glm::vec3 pos;
	glm::vec3 color;
	glm::vec3 normal;
	glm::vec2 texCoord;

	//綁定描述
	static VkVertexInputBindingDescription getBindingDescription() {
		VkVertexInputBindingDescription bindingDescription = {};
		bindingDescription.binding = 0;
		bindingDescription.stride = sizeof(Vertex);
		bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

		return bindingDescription;
	}

	//屬性描述
	static std::array<VkVertexInputAttributeDescription, 4> getAttributeDescriptions() {
		std::array<VkVertexInputAttributeDescription, 4> attributeDescriptions = {};

		attributeDescriptions[0].binding = 0;
		attributeDescriptions[0].location = 0;
		attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
		attributeDescriptions[0].offset = offsetof(Vertex, pos);

		attributeDescriptions[1].binding = 0;
		attributeDescriptions[1].location = 1;
		attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
		attributeDescriptions[1].offset = offsetof(Vertex, color);

		attributeDescriptions[2].binding = 0;
		attributeDescriptions[2].location = 2;
		attributeDescriptions[2].format = VK_FORMAT_R32G32B32_SFLOAT;
		attributeDescriptions[2].offset = offsetof(Vertex, normal);

		attributeDescriptions[3].binding = 0;
		attributeDescriptions[3].location = 3;
		attributeDescriptions[3].format = VK_FORMAT_R32G32_SFLOAT;
		attributeDescriptions[3].offset = offsetof(Vertex, texCoord);

		return attributeDescriptions;
	}

	bool operator==(const Vertex& other) const {
		return pos == other.pos && color == other.color && texCoord == other.texCoord;
	}
};

3.在UniformBufferObject結構體中新增了基礎光照glm::vec3 baseLight和和環境光照強度float ambientStrength。結構體修改如下:

struct UniformBufferObject {
	glm::mat4 model;
	glm::mat4 view;
	glm::mat4 proj;
	glm::vec3 baseLight;
	float ambientStrength;
};

本學習沒有獨立新建另外UniformBuffer供片元着色器使用,後續會將所有光照需要用到的光照信息皆加入此結構體中,通過頂點着色器傳遞給片元着色器。

大致修改完畢,接下來我們來主要來實現vulkan中物體顏色。(shader中顏色部分基礎知識可參照LearnOpenGL中顏色章節

一、更新UniformBuffer

在此之前需要定義一個全局基礎光照

//純白光
glm::vec3 baseLight = glm::vec3(1.0f, 1.0f, 1.0f);

之後,在updateUniformBuffer函數中我們需要將UniformBufferObject結構體中的基礎光照和光照係數實時傳遞給UniformBuffer。

void updateUniformBuffer() {
		...
		UniformBufferObject ubo = {};
		ubo.ambientStrength = 1 ;
		ubo.baseLight =  baseLight;
		...

二、更新着色器

更頂點着色器shader.vert:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
	vec3 baseLight;
	float ambientStrength;
} 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 = 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;

void main() {
    gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
    fragColor = inColor;
    fragNormal = inNormal;
	fragTexCoord = inTexCoord;
	fragBaseLight = ubo.baseLight;
	ambientStrength= ubo.ambientStrength;
}

在shader.vert中將UniformBufferObject結構體同步,並新定義:

  • layout(location = 2) in vec3 inNormal; 接收Vertex中的normal法線信息
  • layout(location = 1) out vec3 fragNormal;將法線傳出到片元着色器中
  • layout(location = 3) out vec3 fragBaseLight;將基礎光照傳出到片元着色器中
  • layout(location = 4) out float ambientStrength;將光照強度傳出到片元着色器中

更新片元着色器shader.frag:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 1) uniform sampler2D texSampler;

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 = 0) out vec4 outColor;

void main() {
    vec3 lightColor=ambientStrength * fragBaseLight;
    outColor = vec4(fragColor * lightColor, 1.0);
    //outColor = vec4(fragTexCoord, 0.0, 1.0);
	//outColor = vec4(fragColor * texture(texSampler, fragTexCoord).rgb, 1.0);
    //outColor = texture(texSampler, fragTexCoord)* vec4(lightColor, 1.0);
}

重新編譯shader,之後還需修改一下camera的初始位置:

Camera camera(glm::vec3(0.0f, 2.0f, 2.0f), glm::radians(-45.0f), glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));

運行代碼,可以見到如圖所示顏色的立方體
在這裏插入圖片描述
除此之外,您還可以通過更新ubo.ambientStrength或者ubo.baseLight來查看不同的效果 。
如,修改:

glm::vec3 baseLight = glm::vec3(0.0f, 0.0f, 0.0f);

則會看到,物體所有表面都會呈現黑色
在這裏插入圖片描述
除此之外我們還可以將
ambientStrength設置爲動態的0-1之間的數值,

ubo.ambientStrength = (sin(time) + 1) / 2 ;

這樣的話,您將會看見一個隨時間變化而出現交替顏色變換的立方體。
在這裏插入圖片描述
下一步我們將着重來實現基礎光照,即馮氏光照模型(Phong Lighting Model)。

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