这节,绘画一个三个形和矩形。
效果如下:
这节加入了着色器shader和着色语言GLSL(OpenGL shader language)。
https://doc.qt.io/qt-5/qopenglshaderprogram.html
https://blog.csdn.net/hankern/article/details/85316476
Shader其实就是一段执行在GPU上的程序,此程序使用OpenGL ES SL语言来编写。它是一个描述顶点或像素特性的简单程序。在opengles中常用的shader有两种:vertex shader和fragment shader。Geometry Shader(几何着色器)是继Vertex Shader和Fragment Shader之后,由Shader Model 4引入的新的着色器。还有一个compute Shader由Shader Model 5引入的提供通用计算能力的着色器。
Qt5中着色器为
#include <QOpenGLShaderProgram>
主要代码
polygonwindow.h
#ifndef POLYGONWINDOW_H
#define POLYGONWINDOW_H
#include <QOpenGLShaderProgram>
#include "openglwindow.h"
// QOpenGLShaderProgram
// The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used.
// Header: #include<QOpenGLShaderProgram>
// QT += gui
// Since Qt5.0
// Inherits: QObject
class PolygonWindow : public OpenGLWindow
{
Q_OBJECT
public:
explicit PolygonWindow(QWindow *parent = 0);
~PolygonWindow();
protected:
void initialize();
void render();
private:
void initGeometry();
private:
// 着色器
QOpenGLShaderProgram *m_program;
GLuint m_posAttr;
GLuint m_vboIds[2];
};
#endif // POLYGONWINDOW_H
polygonwindow.cpp
#include "polygonwindow.h"
PolygonWindow::PolygonWindow(QWindow *parent) :
OpenGLWindow(parent), m_program(NULL)
{
}
PolygonWindow::~PolygonWindow()
{
glDeleteBuffers(2,&m_vboIds[0]);
}
void PolygonWindow::initialize()
{
initGeometry();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepthf(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
m_program = new QOpenGLShaderProgram(this);
// Compiles the contents of fileName as a shader of the specified type and adds it to this shader program.
// Returns true if compilation was successful, false otherwise.
// The compilation errors and warnings will be made available via log().
m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader/vertshader.glsl");
m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader/fragshader.glsl");
// Links together the shaders that were added to this program with addShader().
// Returns true if the link was successful or false otherwise.
// If the link failed, the error messages can be retrieved with log().
m_program->link();
// Returns the location of the attribute name within this shader program's parameter list.
// Returns -1 if name is not a valid attribute for this shader program.
m_posAttr = m_program->attributeLocation("posAttr");
}
void PolygonWindow::render()
{
// GL_COLOR_BUFFER_BIT: 当前可写的颜色缓冲
// GL_DEPTH_BUFFER_BIT: 深度缓冲
// GL_ACCUM_BUFFER_BIT: 累积缓冲
// GL_STENCIL_BUFFER_BIT: 模板缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Binds this shader program to the active QOpenGLContext and makes it the current shader program.
// Any previously bound shader program is released.
// This is equivalent to calling glUseProgram() on programId().
// Returns true if the program was successfully bound; false otherwise.
// If the shader program has not yet been linked, or it needs to be re-linked, this function will call link().
m_program->bind();
// Sets this matrix to the identity.
m_modelView.setToIdentity();
m_modelView.translate(-1.5f, 0.0f, -6.0f);
// Sets the uniform variable at location in the current context to value.
m_program->setUniformValue("mvpMatrix", m_projection * m_modelView);
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
// Enables the vertex array at location in this shader program so that the value set
// by setAttributeArray() on location will be used by the shader program.
m_program->enableAttributeArray(m_posAttr);
// Sets an array of vertex values on the attribute at location in this shader program,
// starting at a specific offset in the currently bound vertex buffer.
// The stride indicates the number of bytes between vertices.
// A default stride value of zero indicates that the vertices are densely packed in the value array.
m_program->setAttributeBuffer(m_posAttr, GL_FLOAT, 0, 3);
// 在OpenGl中所有的图形都是通过分解成三角形的方式进行绘制。
// 1.GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接
// 2.GL_TRIANGLE_FAN:以V0V1V2,V0V2V3,V0V3V4,……的形式绘制三角形
// 3.GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。这个方法可以保证从相同的方向上所有三角形均被绘制。以V0V1V2,V1V2V3,V2V3V4……的形式绘制三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
m_modelView.translate(3.0f, 0.0f, 0.0f);
m_program->setUniformValue("mvpMatrix", m_projection * m_modelView);
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
m_program->enableAttributeArray(m_posAttr);
m_program->setAttributeBuffer(m_posAttr, GL_FLOAT, 0, 3);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_program->release();
}
void PolygonWindow::initGeometry()
{
// https://blog.csdn.net/qq_36383623/article/details/85123077
// 用来生成缓冲区对象的名称。
glGenBuffers(2, &m_vboIds[0]);
GLfloat triangleVertices[] = {
0.0f, 1.0f, 0.0f,
-1.0f,-1.0f, 0.0f,
1.0f,-1.0f, 0.0f,
};
// bind a named buffer object
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
// https://blog.csdn.net/qq_24283329/article/details/75453013
//void glBufferData(GLenum target,
// GLsizeiptr size,
// const GLvoid * data,
// GLenum usage);
//
//target
//Specifies the target buffer object.
//The symbolic constant must be
//GL_ARRAY_BUFFER,
//GL_ELEMENT_ARRAY_BUFFER,
//GL_PIXEL_PACK_BUFFER, or
//GL_PIXEL_UNPACK_BUFFER.
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
GLfloat quadVertices[] = {
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f,-1.0f, 0.0f,
-1.0f,-1.0f, 0.0f
};
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
}
多谢,亲爱的美美。