目录
前言
概念 GLSL :OpenGL Shading Languange
写shader的语言。
配合:
- QOpenGLShader使用
- QOpenGLShaderProgram使用
一、典型shader程序结构
#version version_name
int type in_variable_name_1;
int type2 in_variable_name_2;
out type3 out_variable_name_3;
uniform type uniform_name;
void main()
{
out_variable_name_3 = XXX;
}
in: 表示从外部输入到本shader中
out:本shader的数据要向后传递
二、 对shader处理数据的自己思考
1. VBO(buffer缓冲)
就是一个连续内存,就是从左到右一直下去
VBO图示(就是连续内存,毫无意义)
2.VAO(Array)
2.1 VAO解释了连续内存如何切块、换行
2.2 则VAO把VBO转换成了数据库表
2.3 每一行都对应一个显卡核心(CORE)= 每个核心运行一个shader (运行main函数)
2.4 VAO保证有16个4分量的顶点的属性
(也就是一行最多64个值,对应一行)
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&nAtrributes); // 或多多少个属性
此图中的core 就可以直接理解一个shader的运行实例
3.解释shader:
#version 330 core
layout(location=0) in vec3 aPos
layout (location=1) in vec3 aRgb;
void main(){}
a. location=0 <-- VAO.Attrib(0)
b. in 表示传递到后面变量接着
三、 类型
1.基础数据类型
类似c++ :int float double uint bool
2.向量
类型 | 例子 | 说明 |
---|---|---|
vecn | vec4 | float * 4 前面没有类型=float |
bvecn | bvec4 | bool*4 |
ivecn | ivec2 | int*2 |
uvecn | uvec2 | uint*2 |
dvecn | dvec2 | double*2 |
3.vec的swizzling(重组),展开
vec2 vect = vec2(0.5,0.7);
vec4 result = vec4(vect,0,0); // vect自动展开了
vec4 otherresult = vec4(result.xyz,1.0); result.xyz // 展开
vec4 otherresult2 = vec4(result.xx,1.0,1.0); //result.xx展开两个数组
四、shader的链接
vertextColor
1.在顶点着色器上声明为out – 要输出到后面
2. 在片段着色器上声明为in – 从前面输入过来的
五 使用资源来添加外部shader
图 | 解释 |
---|---|
![]() | 文件:新建文件和项目–q资源文件 |
![]() | 输入资源名称res, 生成res.qrc文件 |
![]() | 添加->添加前缀 – >前缀 /shader |
![]() | 添加-添加文件-选择文件 |
![]() | 加入外部文件后 |
![]() | 编辑框可以添加各种程序 |
六 一个使用多个Attrib的代码样例
主要理解
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,6sizeof(float),(void)0);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,6sizeof(float),(void)(3*sizeof(float)));
一行中:前面坐标,后面颜色
float vertices[] = {
//右上三角形
0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f, //右上
0.5f,-0.5f,0.0f, 0.0f,1.0f,0.0f, //右下
-0.5f,-0.5f,0.0f,0.0f,0.0f,1.0f, //左下
-0.5f,0.5f,0.0f, 1.0f,0.5f,0.0f //左上
}; //只有四个点了
#include "zlopenglwidget.h"
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShader>
#include <qDebug>
float vertices[] = {
//右上三角形
0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f, //右上
0.5f,-0.5f,0.0f, 0.0f,1.0f,0.0f, //右下
-0.5f,-0.5f,0.0f,0.0f,0.0f,1.0f, //左下
-0.5f,0.5f,0.0f, 1.0f,0.5f,0.0f //左上
}; //只有四个点了
//float vertices[] = {
// //右上三角形
// 0.5f,0.5f,0.0f, //右上
// 0.5f,-0.5f,0.0f, //右下
// -0.5f,-0.5f,0.0f, //左下
// -0.5f,0.5f,0.0f //左上
// }; //只有四个点了
//EBO
unsigned int indices[]=
{
0,1,3, //右上三角形 右上 - 右下 - 左上
1,2,3 //左下三角形 右下 - 左下-左上
};
zlOpenGLWidget::zlOpenGLWidget(QWidget *parent)
:QOpenGLWidget(parent)
{
}
GLuint VAO,VBO,EBO;
void zlOpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
//绑定VBO和VAO对象
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
//如果data不是空的,则使用此数据初始化数据存储,跨域内存-显存
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
//告知显卡如何解析缓冲力的属性值
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,6*sizeof(float),(void*)0);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,6*sizeof(float),(void*)(3*sizeof(float)));
//开启VAO管理第一个属性值
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER,0);
glGenBuffers(1,&EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
glBindVertexArray(0);
vShader = new QOpenGLShader(QOpenGLShader::Vertex);
vShader->compileSourceFile(":/shader/vertex.shader");
fShader = new QOpenGLShader(QOpenGLShader::Fragment);
fShader->compileSourceFile(":/shader/fragment.shader");
program.addShader(vShader);
program.addShader(fShader);
if(!program.link())
{
qDebug()<<"Error";
}
}
void zlOpenGLWidget::resizeGL(int w, int h)
{
Q_UNUSED(w);
Q_UNUSED(h);
}
void zlOpenGLWidget::paintGL()
{
glClearColor(0.f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
program.bind ();
glBindVertexArray(VAO);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
//glDrawArrays(GL_TRIANGLES,0,6);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
}