光照之颜色
在学习部分之前,我们需要对上一部分代码进行部分修改重塑:
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)。