创建两个着色器程序,第二个程序使用一个不同的片段着色器,输出黄色;再次绘制这两个三角形,让其中一个输出为黄色
在这篇博客中,我们将创建两个着色器程序,其中一个将输出橙色,另一个将输出黄色。然后,我们将绘制两个三角形,分别使用这两个不同的着色器程序。
完整代码
以下是实现代码,包括必要的注释,以帮助你理解每一步。
#include <glad/glad.h>
#include <GLFW/glfw3.h>#include <iostream>void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);// 设置
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char* vertexShaderSource = "#version 330 core\n""layout (location = 0) in vec3 aPos;\n""void main()\n""{\n"" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n""}\0";
const char* fragmentShader1Source = "#version 330 core\n""out vec4 FragColor;\n""void main()\n""{\n"" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n""}\n\0";
const char* fragmentShader2Source = "#version 330 core\n""out vec4 FragColor;\n""void main()\n""{\n"" FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n""}\n\0";int main()
{// glfw: 初始化和配置// ------------------------------glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif// glfw: 创建窗口// --------------------GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "无法创建 GLFW 窗口" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);// glad: 加载所有的 OpenGL 函数指针// ---------------------------------------if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "无法初始化 GLAD" << std::endl;return -1;}// 构建并编译着色器程序// ------------------------------------unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);unsigned int fragmentShaderOrange = glCreateShader(GL_FRAGMENT_SHADER); // 输出橙色的片段着色器unsigned int fragmentShaderYellow = glCreateShader(GL_FRAGMENT_SHADER); // 输出黄色的片段着色器unsigned int shaderProgramOrange = glCreateProgram();unsigned int shaderProgramYellow = glCreateProgram();// 编译顶点着色器glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// 编译第一片段着色器glShaderSource(fragmentShaderOrange, 1, &fragmentShader1Source, NULL);glCompileShader(fragmentShaderOrange);// 编译第二片段着色器glShaderSource(fragmentShaderYellow, 1, &fragmentShader2Source, NULL);glCompileShader(fragmentShaderYellow);// 链接第一个程序对象glAttachShader(shaderProgramOrange, vertexShader);glAttachShader(shaderProgramOrange, fragmentShaderOrange);glLinkProgram(shaderProgramOrange);// 链接第二个程序对象glAttachShader(shaderProgramYellow, vertexShader);glAttachShader(shaderProgramYellow, fragmentShaderYellow);glLinkProgram(shaderProgramYellow);// 设置顶点数据和属性// ------------------------------------------------------------------float firstTriangle[] = {-0.9f, -0.5f, 0.0f, // 左 -0.0f, -0.5f, 0.0f, // 右-0.45f, 0.5f, 0.0f, // 顶部 };float secondTriangle[] = {0.0f, -0.5f, 0.0f, // 左0.9f, -0.5f, 0.0f, // 右0.45f, 0.5f, 0.0f // 顶部 };unsigned int VBOs[2], VAOs[2];glGenVertexArrays(2, VAOs); // 生成多个 VAOglGenBuffers(2, VBOs); // 生成多个 VBO// 第一个三角形设置// --------------------glBindVertexArray(VAOs[0]);glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 第二个三角形设置// ---------------------glBindVertexArray(VAOs[1]);glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);glEnableVertexAttribArray(0);// 渲染循环// -----------while (!glfwWindowShouldClose(window)){// 输入处理// -----processInput(window);// 渲染// ------glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// 使用第一个程序(橙色三角形)glUseProgram(shaderProgramOrange);glBindVertexArray(VAOs[0]);glDrawArrays(GL_TRIANGLES, 0, 3); // 绘制橙色三角形// 使用第二个程序(黄色三角形)glUseProgram(shaderProgramYellow);glBindVertexArray(VAOs[1]);glDrawArrays(GL_TRIANGLES, 0, 3); // 绘制黄色三角形// glfw: 交换缓冲区并获取输入事件// -------------------------------------------------------------------------------glfwSwapBuffers(window);glfwPollEvents();}// 可选:释放所有不再需要的资源// ------------------------------------------------------------------------glDeleteVertexArrays(2, VAOs);glDeleteBuffers(2, VBOs);glDeleteProgram(shaderProgramOrange);glDeleteProgram(shaderProgramYellow);// glfw: 终止,清除之前分配的所有 GLFW 资源// ------------------------------------------------------------------glfwTerminate();return 0;
}// 处理所有输入:查询 GLFW 是否按下/释放了相关键,并作出相应的反应
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow* window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);
}// 当窗口大小改变(由操作系统或用户改变)时,执行此回调函数
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{// 确保视口与新窗口尺寸匹配glViewport(0, 0, width, height);
}