Qt OpenGL 绘制三角形(一)
程序员文章站
2023-12-25 08:29:51
...
一、效果图
二、代码
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QMatrix4x4>
class Widget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
private:
QOpenGLShaderProgram *program;
GLuint programId;
GLint matrixLocation,vertexLocation,clorLocation;
int vVerticesLen,triIndexLen,colorsLen;
GLuint verVbo,indexVbo,colorVbo;
QMatrix4x4 projection;
};
#endif // WIDGET_H
#include "widget.h"
//三角形顶点坐标
GLfloat vertex[] = {
-0.5f, 0.0f,
0.5f, 0.0f,
0.0f, 0.5f,
};
//三角形顶点索引
GLuint triIndexs[] = {0, 1, 2};
//三角形顶点颜色
GLfloat colors[] = {1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
};
Widget::Widget(QWidget *parent)
:QOpenGLWidget(parent)
{
}
Widget::~Widget()
{
}
void Widget::initializeGL()
{
initializeOpenGLFunctions();
program = new QOpenGLShaderProgram(this);
if(!program->addShaderFromSourceFile(QOpenGLShader::Vertex, "E:/opengl/opengl/vertexshader.vert")){
qDebug()<<"vert fail";
return;
}
if(!program->addShaderFromSourceFile(QOpenGLShader::Fragment, "E:/opengl/opengl/fragmentshader.frag")){
return;
}
if(!program->link()){
return;
}
if(!program->bind()){
return;
}
// 获取shaderprogram的id号,然后可以通过id号获取一些属性...
programId = program->programId();
// 从shaderprogram里面获取变量标识
matrixLocation = glGetUniformLocation(programId, "matrix");
vertexLocation = glGetAttribLocation(programId, "vPosition");
clorLocation = glGetAttribLocation(programId, "vColor");
// 计算获得数组长度
vVerticesLen = sizeof(vertex)/sizeof(GLfloat);
triIndexLen = sizeof(triIndexs)/sizeof(GLuint);
colorsLen = sizeof(colors)/sizeof(GLfloat);
// 初始化顶点buffer并装载数据到显存
glGenBuffers(1, &verVbo);
glBindBuffer(GL_ARRAY_BUFFER, verVbo);
glBufferData(GL_ARRAY_BUFFER, vVerticesLen * sizeof(GLfloat), vertex, GL_STATIC_DRAW);
// 初始化索引buffer并装载数据到显存
glGenBuffers(1, &indexVbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, triIndexLen * sizeof(GLuint), triIndexs, GL_STATIC_DRAW);
// 初始化颜色buffer并装载数据到显存
glGenBuffers(1, &colorVbo);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
glBufferData(GL_ARRAY_BUFFER, colorsLen * sizeof(GLfloat), colors, GL_STATIC_DRAW);
}
void Widget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// shader传入模型视图矩阵 projection可以理解为建立了一个坐标系空间,可以再这个空间内设置图形
glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, projection.data());
// shader绑定并启用颜色数组buffer
glBindBuffer(GL_ARRAY_BUFFER,colorVbo);
glVertexAttribPointer(clorLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(clorLocation);
// 颜色值rgba,所以每四个float值作为一个颜色值,如果只是希望rgb,取三个值作为颜色值即可!
// shader绑定并启用顶点数组buffer
glBindBuffer(GL_ARRAY_BUFFER, verVbo);
glVertexAttribPointer( vertexLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vertexLocation);
// shader绑定并顶点索引数组buffer - 索引无需启用
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexVbo);
glDrawElements(GL_TRIANGLES, triIndexLen, GL_UNSIGNED_INT,0);
// 解绑buffer、关闭启用顶点、颜色数组
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(vertexLocation);
glDisableVertexAttribArray(clorLocation);
}
void Widget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
// 模型矩阵重置
projection.setToIdentity();
// 透视投影
qreal aspect = qreal(w) / qreal(h ? h : 1);
projection.perspective(60.0f, aspect, 1.0f, 100.0f);
// 增加了模型矩阵,需要做一定偏移量,保证物体刚开始渲染出来时可以被看到!
projection.translate(0.0f, 0.0f, -2.0f);
}
vertexshader.vert
//vertexshader.vert
uniform mat4 matrix;
in vec4 vPosition;
in vec4 vColor;
out vec4 fColor;
void main(void)
{
fColor = vColor;
gl_Position = matrix * vPosition;
}
fragmentshader.frag
//fragmentshader.frag
in vec4 fColor;
void main(void)
{
gl_FragColor = fColor;
}