返回
OpenGL渲染技巧-光照效果下的甜甜圈
IOS
2023-09-19 07:07:26
光照效果概述
光照效果是计算机图形学中非常重要的一部分,它可以使渲染出的物体更加逼真,更接近真实世界中的物体。光照效果可以通过模拟真实世界中的光线来实现,包括光线的方向、颜色和强度。
实现光照效果
在OpenGL中,可以使用光照着色器来实现光照效果。光照着色器是一种特殊的着色器,它可以根据光源的位置、方向、颜色和强度来计算出物体表面的颜色。
甜甜圈模型渲染
为了演示光照效果,我们将使用OpenGL实现一个甜甜圈模型的渲染。甜甜圈模型是由OpenGL提供实现的,我们可以通过调用相应的OpenGL函数来绘制甜甜圈模型。
代码示例
// 顶点着色器代码
const char *vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aNormal;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"out vec3 fragPos;\n"
"out vec3 Normal;\n"
"void main()\n"
"{\n"
" fragPos = vec3(model * vec4(aPos, 1.0));\n"
" Normal = mat3(transpose(inverse(model))) * aNormal;\n"
" gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
"}\n";
// 片段着色器代码
const char *fragmentShaderSource =
"#version 330 core\n"
"in vec3 fragPos;\n"
"in vec3 Normal;\n"
"uniform vec3 lightPos;\n"
"uniform vec3 lightColor;\n"
"uniform vec3 objectColor;\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" // 计算光线方向
" vec3 lightDir = normalize(lightPos - fragPos);\n"
" // 计算表面法线方向
" vec3 normal = normalize(Normal);\n"
" // 计算漫反射光照强度
" float diffuse = max(dot(lightDir, normal), 0.0);\n"
" // 计算最终颜色
" FragColor = vec4(diffuse * objectColor, 1.0);\n"
"}\n";
// 主函数
int main()
{
// 初始化GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// 创建窗口
GLFWwindow *window = glfwCreateWindow(800, 600, "甜甜圈渲染", NULL, NULL);
if (window == NULL)
{
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 加载并编译着色器
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 创建着色器程序
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 设置光源位置和颜色
glm::vec3 lightPos = glm::vec3(1.0f, 1.0f, 1.0f);
glm::vec3 lightColor = glm::vec3(1.0f, 1.0f, 1.0f);
// 设置物体颜色
glm::vec3 objectColor = glm::vec3(1.0f, 0.0f, 0.0f);
// 获取着色器中的uniform变量的位置
GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
GLint lightPosLoc = glGetUniformLocation(shaderProgram, "lightPos");
GLint lightColorLoc = glGetUniformLocation(shaderProgram, "lightColor");
GLint objectColorLoc = glGetUniformLocation(shaderProgram, "objectColor");
// 创建甜甜圈模型
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// 创建顶点缓冲对象
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 填充顶点数据
// ...
// 启用顶点属性
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)(3 * sizeof(float)));
// 创建索引缓冲对象
GLuint ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
// 填充索引数据
// ...
// 设置模型、视图和投影矩阵
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projection = glm::perspective(45.0f, 800.0f / 600.0f, 0.1f, 100.0f);
// 渲染循环
while (!glfwWindowShouldClose(window))
{
// 清空颜色缓冲和深度缓冲
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 使用着色器程序
glUseProgram(shaderProgram);
// 设置uniform变量
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glUniform3fv(lightPosLoc, 1, glm::value_ptr(lightPos));
glUniform3fv(lightColorLoc, 1, glm::value_ptr(lightColor));
glUniform3fv(objectColorLoc, 1, glm::value_ptr(objectColor));
// 绘制甜甜圈模型
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// 交换缓冲
glfwSwapBuffers(window);
glfwPollEvents();
}
// 释放资源
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ibo);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
运行效果
运行代码后,您将看到一个甜甜圈模型,模型上应用了光照效果,看起来更加逼真。您还可以通过修改光源的位置、方向、颜色和强度来改变甜甜圈模型的渲染效果。