当绘图时,GPU 执行着色器。
OpenGL 着色器以 OpenGL 着色器语言(GLSL)编写,该语言和C语言很像,但有所区别。
着色器的源代码放在着色器对象中并进行编译,然后多个着色器对象链接在一起形成一个着色器程序对象。每个着色器程序对象都可以包含多个着色器阶段的多个着色器。
顶点着色器
下面是一个顶点着色器的代码:
#version 450 core
void main(void)
{
gl_Position = vec4(0.0f, 0.0f, 0.5f, 1.0f);
}
第一行的意思是:着色器编译器使用着色器语言的4.5版本,且所有 OpenGL 核心模式。
gl_Position 在顶点着色器中表示顶点的输出位置。这里表示裁剪空间的中心,即窗口的正中央。
裁剪空间
在一个顶点着色器运行的最后,OpenGL期望所有的坐标都能落在一个给定的范围内,且任何在这个范围之外的点都应该被裁剪掉(Clipped)。被裁剪掉的坐标就被忽略了,所以剩下的坐标就将变为屏幕上可见的片段。
片段着色器
#version 450 core
out vec4 color;
void main(void)
{
color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
out 关键字声明 color 作为一个输出变量。在片段着色器中,输出变量的值会发送到窗口或者屏幕。这里赋给一个表示颜色的向量,顺序为 RGBA。
完整代码
#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H
#include <QOpenGLWidget>
class openglWidget : public QOpenGLWidget
{
Q_OBJECT
public:
openglWidget(QWidget * parent = nullptr);
virtual ~openglWidget();
protected:
virtual void paintGL();
void initializeGL();
private:
GLuint rendering_program;
GLuint vertex_array_object;
};
#endif // OPENGLWIDGET_H
#include "openglwidget.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
openglWidget::openglWidget(QWidget *parent)
:QOpenGLWidget(parent)
{
}
openglWidget::~openglWidget()
{
QOpenGLExtraFunctions * funs = QOpenGLContext::currentContext()->extraFunctions();
funs->glDeleteVertexArrays(1, &vertex_array_object);
funs->glDeleteProgram(rendering_program);
funs->glDeleteVertexArrays(1, &vertex_array_object);
}
void openglWidget::initializeGL()
{
QOpenGLShader vertex = QOpenGLShader(QOpenGLShader::Vertex);
vertex.compileSourceCode(R"(#version 450 core
void main(void)
{
gl_Position = vec4(0.0f, 0.0f, 0.5f, 1.0f);
gl_PointSize = 30.0f; //点的大小
})") ;
if(!vertex.isCompiled())
{
qDebug()<<"顶点着色器编译错误:"<<vertex.log();
}
QOpenGLShader fragment = QOpenGLShader(QOpenGLShader::Fragment,this);
fragment.compileSourceCode(R"(#version 450 core
out vec4 color;
void main(void)
{
color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
})") ;
if(!fragment.isCompiled())
{
qDebug()<<"颜色着色器编译错误:"<<fragment.log();
}
QOpenGLShaderProgram shaderProgram;
shaderProgram.addShader(&vertex);
shaderProgram.addShader(&fragment);
if(!shaderProgram.bind())
{
qDebug()<<"着色器程序绑定错误:"<<shaderProgram.log();
}
rendering_program = vertex.shaderId();
vertex_array_object = vertex.shaderId();//顶点数组对象,用于向顶点着色器提供输入
QOpenGLExtraFunctions * funs = QOpenGLContext::currentContext()->extraFunctions();
funs->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);//使用顶点着色器中定义的点的大小
funs->glBindVertexArray(rendering_program);//将资源绑定到上下文
funs->glBindVertexArray(vertex_array_object);
}
void openglWidget::paintGL()
{
QOpenGLExtraFunctions * funs = QOpenGLContext::currentContext()->extraFunctions();
funs->glClearColor(0.2f,0.2f,0.3f,1.0f);
funs->glUseProgram(rendering_program);//使用参数为红色的颜色着色器进行渲染
funs->glDrawArrays(GL_POINTS,0,1);//参数1:绘制点,参数3:渲染的顶点个数-1
}
|