OpenGL学习2——绘制三角形

2021-06-13  本文已影响0人  蓬篙人

1. OpenGL图形管道简介

2. OpenGL图形管道编程

2.1 顶点输入

// 一个三角形的顶点数据,因为是一个2D三角形,所以z坐标都为0
float vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};
// 创建顶点缓冲区对象
unsigned int VBO;
glGenBuffers(1, &VBO);
// 绑定顶点缓冲区对象到GL_ARRAY_BUFFER类型的缓冲区
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// vertices是我们前面创建的顶点数据
// glBufferData: 拷贝用户定义的数据到当前绑定的缓冲区
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

2.2 顶点着色器(vertex shader)

// 版本:OpenGL 3.3, 核心模式
#version 330 core
layout (location = 0) in vec3 aPos;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
1. 每个着色器都从版本声明开始
2. in关键字:声明输入顶点属性。(示例只有位置信息)
3. 顶点着色器通过将位置数据设置给预定义变量`gl_Position`来设置着色器的输出。

2.3 片元着色器(fragment shader)

#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
1. 使用`out`关键字定义输出变量。
const char* fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{"
    "    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\0";
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
    glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 着色器程序对象错误检查
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
    glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::PROGRAM::LINK_FAILED\n" << infoLog << std::endl;
}
// 链接完着色器程序我们可以直接删除着色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glUseProgram(shaderProgram);

2.4 链接顶点属性

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
1. 第一个参数指定我们要配置的顶点属性,对应我们在顶点着色器中指定的`location`。
2. 第二个参数指定顶点属性的大小。
3. 第三个参数指定数据的类型。
4. 第四个参数指定是否标准化(normalized)数据。
5. 第五个参数为步长(stride),指定连续顶点属性之间的间距。
6. 最后一个参数是缓冲区中数据的偏移量(offset)。 
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);

2.5 元素缓冲区对象

// 顶点数据
float vertices[] = {
     0.5f,  0.5f, 0.0f,  // 右上角
     0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f,
    -0.5f,  0.5f, 0.0f
};
// 索引数据
unsigned int indices[] = {
    0, 1, 3,   // 第一个三角形
    1, 2, 3    // 第二个三角形
};
// 1. 创建元素缓冲区对象
unsigned int EBO;
glGenBuffers(1, &EBO);
// 2. 绑定元素缓冲区对象
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// 3. 拷贝索引数组到元素还钱给OpenGL使用
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 设置线框模式(wireframe mode)
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// 绘制元素
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
线框模式矩形渲染界面

3. 个人小结

上一篇 下一篇

猜你喜欢

热点阅读