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)。

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