创建两个着色器程序,第二个程序使用一个不同的片段着色器,输出黄色;再次绘制这两个三角形,让其中一个输出为黄色
在这篇博客中,我们将创建两个着色器程序,其中一个将输出橙色,另一个将输出黄色。然后,我们将绘制两个三角形,分别使用这两个不同的着色器程序。
完整代码
以下是实现代码,包括必要的注释,以帮助你理解每一步。
#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); // 生成多个 VAO
glGenBuffers(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);
}