📅  最后修改于: 2023-12-03 15:06:52.860000             🧑  作者: Mango
在OpenGL中使用着色器可以实现更加高级的渲染效果。在本文中,我们将讨论如何使用OpenGL渲染三角形,并使用着色器为其添加颜色。
在开始使用OpenGL渲染三角形之前,需要设置OpenGL环境。下面是一个示例:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
int main() {
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Initialize GLEW */
if (glewInit() != GLEW_OK)
std::cout << "Error initializing GLEW" << std::endl;
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
以上代码创建了一个窗口,并将其设置为当前的OpenGL上下文。
创建三角形有两种方法:使用顶点数组和使用顶点缓冲区对象(VBO)。在本文中,我们将使用顶点数组。
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
以上代码创建了一个具有三个顶点的三角形,并将其存储在顶点数组中。然后使用 glGenVertexArrays 函数和 glGenBuffers 函数分别生成顶点数组对象和缓冲区对象,并绑定它们。
使用 glBindVertexArray 函数和 glBindBuffer 函数将缓冲区绑定到当前的顶点数组对象中。然后使用 glBufferData 函数将顶点数组复制到缓冲区中。
使用 glVertexAttribPointer 函数配置顶点属性指针,并使用 glEnableVertexAttribArray 函数启用它。
使用 glBindVertexArray 函数将当前的顶点数组对象解绑。
着色器是用于渲染图形的编程语言,它们通过将输入顶点转换为输出颜色来渲染图形。在本文中,我们将编写顶点着色器和片段着色器。
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position.x, position.y, position.z, 1.0f);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
" color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\0";
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);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
以上代码分别定义了顶点着色器和片段着色器。顶点着色器将每个输入顶点转换为带有四个分量的裁剪空间坐标(即 gl_Position 变量)。片段着色器将输出单个颜色,我们使用 vec4 类型的 color 变量表示其 RGBA 值。
使用 glCreateShader 函数创建顶点着色器对象和片段着色器对象,并使用 glShaderSource 函数将着色器源代码附加到着色器对象上。然后使用 glCompileShader 函数编译着色器。
使用 glCreateProgram 函数创建着色器程序对象,并使用 glAttachShader 函数将顶点着色器和片段着色器附加到着色器程序上。然后使用 glLinkProgram 函数链接着色器程序。
使用 glDeleteShader 函数删除顶点着色器和片段着色器对象。
现在我们准备好渲染三角形了。使用以下代码在窗口中绘制三角形:
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
使用 glUseProgram 函数指定要使用的着色器程序。使用 glBindVertexArray 函数指定要使用的顶点数组对象,并使用 glDrawArrays 函数绘制三角形。然后使用 glBindVertexArray 函数将当前的顶点数组对象解绑。
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position.x, position.y, position.z, 1.0f);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
" color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\0";
int main() {
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Initialize GLEW */
if (glewInit() != GLEW_OK)
std::cout << "Error initializing GLEW" << std::endl;
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
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);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}