OpenGL绘制三角形的过程详解,Qt框架

初始化

void initializeGL() override;

1. 初始化
initializeOpenGLFunctions();
2. 定义或导入着色器语言
//顶点着色器
const char* vertexShaderSource = R"(
            #version 450 core
            layout (location = 0) in vec3 aPos;
            void main()
            {
                gl_Position = vec4(aPos, 1.0);
            }
        )";
//片元着色器
const char* fragmentShaderSource = R"(
            #version 450 core
            out vec4 FragColor;
            void main()
            {
                FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }
        )";
3. 导入着色器语言并编译
3.1 获取着色器句柄
//获取顶点着色器句柄
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
3.2 将着色器句柄指向源码(将源码加入到OpenGL中)
//arg1:着色器句柄,arg2:所绑定的源码个数, arg3:源码字符串数组,arg4:字符串长度,若为NULL则将字符串视为以NULL结尾的字符串
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
3.3 编译着色器
glCompileShader(vertexShader);
3.4 检查是否成功编译
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
	glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
	qDebug() << "Vertex shader compilation failed: " << infoLog;
}
4. 将各个管线上的程序连接成整个程序
//着色器程序获取句柄
GLuint shaderProgram = glCreateProgram();
//指定程序句柄与哪些着色器句柄连接
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
//程序连接
glLinkProgram(shaderProgram);
//判断是否出现连接错误
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
	glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
	qDebug() << "Shader program linking failed: " << infoLog;
}
5. 删除着色器
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

循环绘制

void paintGL() override;

绘制数据与功能设置
1. 清空缓冲区
//设置清空所刷新的颜色
glClearColor(1.0, 1.0, 1.0, 1.0);
//清空颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
2. 导入顶点信息
//定义绘制图形的顶点
GLfloat vertices[] = {
	-0.5f, -0.5f, 0.0f,
	0.5f, -0.5f, 0.0f,
	0.0f, 0.5f, 0.0f
};
3. 设置着色器程序
//使用着色器程序
glUseProgram(shaderProgram);
4. 获取VAO和VBO
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
5. 将VAO和VBO绑定到上下文
//当前 顶点数组对象:NULL 顶点缓存对象:NULL 
glBindVertexArray(VAO);
//当前 顶点数组对象:VAO 顶点缓存对象:NULL
//在当前上下文中绑定顶点缓存对象产生层级关系 VAO -> VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//当前 顶点数组对象:VAO 顶点缓存对象:VBO
6. 将顶点数据添加到OpenGL中
//在GPU中开辟内存,创建缓冲区对象,并将数据拷贝到对象中
//因为当前顶点缓存对象上下文为VBO,所以存在层级关系VBO -> vertices
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
7. 设置解析数据的方式,并定义将该数据流入哪个索引
//arg1:流入哪个索引,此索引与着色器中layout(location = %%)中的数字相对应
//arg2, arg3:定义一次读取数据的长度
//arg4:是否进行归一化
//arg5:定义数据之间的间隔
//arg6:数据初始偏移量
//数据读取方式 根据定义读取 [arg6 + arg5 * k, arg6 + arg5 * k + arg2 * arg3)中的数据,arg4决定数据是否归一化,最后将数据输出到着色器中arg1索引接口
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
8. 连通数据之间的读取方式
glEnableVertexAttribArray(0);
9. 清空上下文状态
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
绘制
1. 设置VAO上下文
glBindVertexArray(VAO);
2. 绘制
//按照绘制三角形的方式,从第0个顶点开始,绘制3个顶点,
glDrawArrays(GL_TRIANGLES, 0, 3);
收尾
1. 删除VAO和VBO
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);

完整代码

#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QDebug>

class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core
{
public:
    void initializeGL() override
    {
        initializeOpenGLFunctions();

        // 创建和编译着色器
        const char* vertexShaderSource = R"(
            #version 450 core
            layout (location = 0) in vec3 aPos;
            void main()
            {
                gl_Position = vec4(aPos, 1.0);
            }
        )";

        const char* fragmentShaderSource = R"(
            #version 450 core
            out vec4 FragColor;
            void main()
            {
                FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }
        )";

        GLuint vertexShader, fragmentShader;
        GLint success;
        char infoLog[512];

        // 顶点着色器
        vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
        glCompileShader(vertexShader);

        glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
            qDebug() << "Vertex shader compilation failed: " << infoLog;
        }

        // 片段着色器
        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);
            qDebug() << "Fragment shader compilation failed: " << infoLog;
        }

        // 着色器程序
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
        glLinkProgram(shaderProgram);

        glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
        if (!success)
        {
            glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
            qDebug() << "Shader program linking failed: " << infoLog;
        }

        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
    }

    void paintGL() override
    {
        glClearColor(1.0, 1.0, 1.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);

        // 使用着色器程序
        glUseProgram(shaderProgram);

        // 绘制三角形
        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)
                              , (void*)0);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0);

        glDeleteVertexArrays(1, &VAO);
        glDeleteBuffers(1, &VBO);
    }

private:
    GLuint shaderProgram;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyOpenGLWidget widget;
    widget.resize(800, 600);
    widget.show();

    return app.exec();
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值