基于Qt的OpenGL可编程管线学习(1)- 绘制一个三角形

0、写在前面的话

        这里只是学习的时候做的笔记记录方便日后的查看,如果有大神看到觉得有问题的地方希望能给予指出,方便日后的学习,谢谢!

我是用的Qt版本为Qt5.6,开发环境为Qt Creator


1、QOpenGLWidget

在Qt开发环境下,使用OpenGL的可编程管线绘制一个三角形

效果如下图所示:


这里使用QOpenGLWidget进行绘制的,在QOpenGLWidget中需要重写

void initializeGL(void);
void resizeGL(int w, int h);
void paintGL(void);

这三个函数,initializeGL()函数为初始化窗口调用的函数,resizeGL()函数改变窗口大小时调用,paintGL()是每一帧绘制的函数。


2、创建Program,加载Shader

使用OpenGL的shader绘制三角形,就要创建一个shader的程序,Qt中实现了QOpenGLShader、QOpenGLShaderProgram类,方便程序的创建和添加Shader。使用代码如下,本例中程序加载两个shader(vertex shader 和fragment shader):

// 创建一个GPU程序
    GLuint createGPUProgram(QString nVertexShaderFile, QString nFragmentShaderFile);
    QOpenGLShader *m_VertexShader;
    QOpenGLShader *m_FragmentShader;
    QOpenGLShaderProgram *m_Program;


createGPUProgram()函数实现如下:

GLuint OpenGLWidget::createGPUProgram(QString nVertexShaderFile, QString nFragmentShaderFile)
{
  
    m_VertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
    bool isOK = m_VertexShader->compileSourceFile(nVertexShaderFile);
    if (!isOK)
    {
  
        delete m_VertexShader;
        m_VertexShader = nullptr;
        return 0;
    }
    m_FragmentShader = new QOpenGLShader(QOpenGLShader::Fragment);
    if (!m_FragmentShader->compileSourceFile(nFragmentShaderFile))
    {
  
        delete m_VertexShader;
        delete m_FragmentShader;
        m_FragmentShader = nullptr;
        return 0;
    }
    m_Program = new QOpenGLShaderProgram(this);
    m_Program->addShader(m_VertexShader);
    m_Program->addShader(m_FragmentShader);
    m_Program->link();
    return m_Program->programId();
}
其中Vertex shader和fragment shader的内容如下:


3、shader内容

在OpenGL的Shader使用,GLSL语言,与C语言很类似。下面是关于GLSL的一些简单的介绍:

attribute CPU与Shader传递数据,只能在CPU与Vertex Shader之间使用。

uniform 可用于CPU与任意Shader传递数据,一般用于传递矩阵等较大的数据。

varying 可用于Shader间传递数据。

本例子中,数据是CPU->Vertex Shader->Fragmen Shader顺序传递,Vertex shader是处理数据,Fragment shader会终的转换为像素的处理。最后通过OpenGL渲染到屏幕输出。


Vertex Shader:

attribute vec3 pos;
attribute vec4 color;
 
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
 
varying vec4 M_Color;
 
void main()
{
 
        M_Color = color;
        gl_Position = P * V * M * vec4(pos, 1.0);
}
 由于OpenGL中为列向量和矩阵,这里需要使用矩阵左乘的形式。Vertex shader对应一个点的调用。 

其中,M为传递的模型矩阵、V为视图矩阵、P为投影矩阵。

Fragment Shader:

varying vec4 M_Color;
 
void main()
{
 
        gl_FragColor = M_Color;
}
 

4、为Shader中传入数据

为attribute中和uniform中的数据赋值,需要获取Shader中的Location

// 获取Uniform ID & Attribute ID
    m_MLocationMat = OpenGLCore->glGetUniformLocation(programId, "M");
    m_VLocationMat = OpenGLCore->glGetUniformLocation(programId, "V");
    m_PLocationMat = OpenGLCore->glGetUniformLocation(programId, "P");
    m_PosVector = OpenGLCore->glGetAttribLocation(programId, "pos");
    m_ColorVector = OpenGLCore->glGetAttribLocation(programId, "color");

其中OpenGLCore为

OpenGLCore = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
使用OpenGL3.2的核心,programId为QOpenGLShaderProgram的programId。


顶点数据如下:

struct VertexInfo
{
  
    float pos[3];
    float color[4];
};

    VertexInfo nVertexInfo[3];
    nVertexInfo[0].pos[0] = 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值