光照之顏色
在學習部分之前,我們需要對上一部分代碼進行部分修改重塑:
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)。