OpenGL Chan视频学习-4 Vertex Buffers and Drawing a Triangle in OpenGL

发布于:2025-05-26 ⋅ 阅读:(53) ⋅ 点赞:(0)

一、视频链接

【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p=5&vd_source=44b77bde056381262ee55e448b9b1973

二、相关网站

docs.gl

三、代码整理

c++

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include<iostream>

int main(void)
{
    GLFWwindow* window;

    //初始化glfw
    if (!glfwInit())
        return -1;

    //创建一个窗口模式的窗口并设置OpenGL上下文
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)//如果窗口创建失败,则终止程序
    {
        glfwTerminate();//释放glfw资源
        return -1;
    }

    //设置当前窗口的上下文,之后所有的OpenGL调用都会在这个上下文中进行
    glfwMakeContextCurrent(window);

    //初始化GLEW
    if (glewInit() != GLEW_OK)
        std::cout << "Error!" << std::endl;

    //打印OpenGL版本信息
    std::cout << glGetString(GL_VERSION) << std::endl;







    //通过GL顶点属性指针的函数告诉OpenGL的数据是如何布局的
    //这里我们告诉OpenGL,position数据是两个float,每个float占4字节
    //第一个float表示x坐标,第二个float表示y坐标
    //由于我们的数据是2D坐标,所以这里的stride为8字节
    // 参数:
    // 1.顶点属性的索引,这里是0
    // 2.数据类型,这里是GL_FLOAT
    // 3.数据类型占用字节数,这里是4
    // 4.是否归一化,这里是GL_FALSE
    // 5.stride,这里是8,表示两个float的大小
    // 6.偏移量,这里是0,表示数据从开头开始
    // 注意:这里的顶点属性指针的设置必须在启用顶点属性数组之前
    //  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, 0);
    //启用顶点属性数组
    // 参数:  
    // 1.顶点属性的索引,这里是0
    //  glEnableVertexAttribArray(0);

    //准备数据
    float position[6] = {
        0.0f, 0.5f,
        - 0.5f, -0.5f,
        0.5f, -0.5f
    };

    //可以将需要的图形(如三角形)绑定缓冲区,传递缓冲区的id给OpenGL,然后通过OpenGL渲染
    //shader语法以字符串的形式给出,再由gl解析后让GPU执行GLSL程序
    unsigned int buffer;
    //功能:生成缓冲区,并将缓冲区绑定到OpenGL的指定目标
    //参数:
    //1.缓冲区数量,表示要生成的缓冲区数量
    //2.指向无符号整数的指针,表示生成的缓冲区id的存储位置
    glGenBuffers(1,&buffer);
    //功能:绑定缓冲区到OpenGL的指定目标
    //参数:
    //1.目标,数组缓冲区,表示绑定到OpenGL的缓冲区
    //2.缓冲区id,表示要绑定的缓冲区的id
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    //功能:将数据写入缓冲区
    //参数:
    //1.目标,数组缓冲区,表示要写入的缓冲区
    //2.数据大小,表示要写入的数据的大小
    //3.数据指针,表示要写入的数据的指针
    //4.写入模式,表示数据写入的模式,这里是静态写入。
    //   静态写入:数据不会被修改,仅仅是一次性写入,写入后缓冲区内容不会改变。
    //   动态写入:数据会被修改,写入后缓冲区内容会改变。
    //   一般情况下,静态写入效率更高。
    glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);

    //渲染循环,直到窗口被关闭
    while (!glfwWindowShouldClose(window))
    {
        //这部分主要:渲染窗口内容
        glClear(GL_COLOR_BUFFER_BIT);

        /*
        //方法一:通过顶点属性指针渲染
        glBegin(GL_TRIANGLES);
        glVertex2f(0.0f, 0.5f);
        glVertex2f(-0.5f, -0.5f);
        glVertex2f(0.5f, -0.5f);
        glEnd();
        */

        /*
        //方法二
        //功能:指定如何从缓冲区中读取数据
        //参数
        //    mode
        //    指定要渲染的原始类型。接受符号常量
        // GL_POINTS、GL_LINE_STRIP、GL_LINE_LOOP、GL_LINES、
        // GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN 和 GL_TRIANGLES。
        //    first
        //    指定在启用的数组中的起始索引。
        //    count
        //    指定要渲染的索引数量。
        glDrawArrays(GL_TRIANGLES, 0, 3);
        */

        /*
        //方法三:通过索引缓冲区渲染
        //功能:指定如何从缓冲区中读取数据
        //参数
        //    mode
        //    指定要渲染的原始类型。符号常量 GL_POINTS、GL_LINE_STRIP、
        // GL_LINE_LOOP、GL_LINES、GL_LINE_STRIP_ADJACENCY、GL_LINES_ADJACENCY、
        // GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN、GL_TRIANGLES、
        // GL_TRIANGLE_STRIP_ADJACENCY、GL_TRIANGLES_ADJACENCY 
        // 和 GL_PATCHES 被接受。
        //    count
        //    指定要渲染的元素数量。
        //    type
        //    指定 indices 中值的类型。必须是 GL_UNSIGNED_BYTE、GL_UNSIGNED_SHORT 
        // 或 GL_UNSIGNED_INT 中的一种。
        //    indices
        //    指定缓冲区当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的数据存储中数组第一个索引的偏移量。
        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
        */
        

        //刷新缓冲区并交换窗口
        glfwSwapBuffers(window);

        //处理窗口事件,如键盘输入、鼠标移动等
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}