02 光照

etherovo / 2023-05-11 / 原文

一、颜色

  • 对光源和物体写不同的shader
    • 物体:反射颜色是自身反射率与光源颜色的乘积
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0);
};

#version 330 core

out vec4 fragColor;


uniform vec4 vexColor;
uniform sampler2D texture1;
uniform sampler2D texture2;

uniform vec3 lightColor;
uniform vec3 objectColor;


void main()
{
	fragColor = vec4(lightColor*objectColor,1.0f);
}
  • 光源:自身颜色
#version 330 core
layout(location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0);
};
#version 330 core

out vec4 fragColor;

void main()
{
	fragColor = vec4(1.0,1.0,1.0,1.0);
}
  • 因为shader不同,所以需要对这两部分分别做shader以及program的操作,在本文中便是定义两个不同的Shader对象。
Shader ourShader("res/shader/cubeVertex.shader", "res/shader/cubeFragment.shader");
Shader lightShader("res/shader/lightVertex.shader", "res/shader/lightFragment.shader");
  • 两个部分都是使用立方体,所以VBO与EBO可以共享,但是VAO需要分别设置,因为VAO包含着节点指针函数,这与shader的输入变量相关。对于VBO与EBO的数据,自然也是只需要一次传输。
unsigned int VBO;
	glGenBuffers(1, &VBO);
	unsigned int EBO;
	glGenBuffers(1, &EBO);
	unsigned int lightVAO;
	glGenVertexArrays(1, &lightVAO);
	unsigned int VAO;
	glGenVertexArrays(1, &VAO);

	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
	glEnableVertexAttribArray(2);

	glBindVertexArray(lightVAO);
	glBindBuffer(GL_ARRAY_BUFFER,VBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
  • 在绘制的时候,对这两个物体需要进行两次流程,相应的program、VAO、以及绘制图形(比如节点数量等)均不同,需要按照自己的需求来设置。
  • 相应的,对program的uniform操作也各不相同。
  • 此外,另一个重要的地方是,二者的view matrix和projection matri是一样的,因此只需要定义一次而公用,但是model matrix显然是不一样的。
ourShader.use();
ourShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
ourShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
		
glBindVertexArray(VAO);

glm::mat4 view = camera.ViewMatrix();
ourShader.setMat4("view", glm::value_ptr(view));
glm::mat4 projection = glm::perspective(glm::radians(camera.Fov), (float)SCR_WIDTH/(float)SCR_HEIGHT, 0.1f, 100.0f);
ourShader.setMat4("projection", glm::value_ptr(projection));
for (int i = 0; i != 10; i++)
{
	glm::mat4 model;
	model = glm::translate(model, cubePositions[i]);
	float angle = 20.0f * (i+1);
	model = glm::rotate(model, (float)glfwGetTime() * glm::radians(angle), glm::vec3(0.0f, 1.0f, 1.0f));
	ourShader.setMat4("model", glm::value_ptr(model));
	glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
		}

lightShader.use();
glBindVertexArray(lightVAO);
glm::vec3 lightPos = glm::vec3(0.0f, 1.0f, 0.0f);
glm::mat4 lightModel;
lightModel = glm::translate(lightModel, lightPos);
lightModel = glm::scale(lightModel, glm::vec3(0.2f, 0.2f, 0.2f));
lightShader.setMat4("model", glm::value_ptr(lightModel));
lightShader.setMat4("view", glm::value_ptr(view));
lightShader.setMat4("projection", glm::value_ptr(projection));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);