#核心模式OpenGL GLSL程序
GLSL程序简介和在QT中向GLSL程序变量传递数据
包含基本数据类型 int、float、double、uint、bool
两种容器类型
标识符 | 含义 |
---|---|
vecn | n个float |
bvecn | booleans |
ivecn | integers |
uvecn | unsigned integers |
dvecn | double components |
向量可以使用重组(swizzling),例如
vec2 vect = vec2(0.5, 0.7);
vec4 result = vec4(vect, 0.0, 0.0);
vec4 otherResult = vec4(result.xyz, 1.0)
发送方着色器声明一个输出,out
接收方着色器声明一个输入,in
类型名字一致的变量,会在链接程序对象完成时,被OpenGL链接到一起
为了定义顶点数据管理方式,使用location一元数据指定输入变量。设置属性位置值,在glsl中的属性前面添加layout,例如:
layout(location = 0) in vec3 aPos;
在cpu中通过这个序号与gpu中的属性建立联系,以下为问答方式,询问aPos的序号。(QT封装函数操作)
GLint glGetAttribLocation( GLuint program,
const GLchar * name);
shaderProgram.bind();
GLint posLocation = shaderProgram.attributeLocation("aPos");
告诉显卡如何解释缓冲里的属性
glVertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE,
sizeof(float) * 2, (void*)0);
另一种方式,由程序绑定
推荐使用上一种方式,在着色器中设置
shaderProgram.bind();
GLint posLocation = 2;
shaderProgram.bindAttributeLocation("aPos",posLocation);
glVertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE,
sizeof(float) * 2, (void*)0);
glEnableVertexAttribArray(posLocation);
另一种从cpu向gpu着色器发送数据的方式。
全局的,可以被任意着色器在任意阶段访问
uniform vec4 ourColor;
注意!如果没有使用这个变量,这个变量会被编译器优化掉,会导致一些问题。
QT中有一个初步的封装
shaderProgram.setUniformValue("ourColor", val0, val1, val2, val3);
通用方法为
int colorLocation = glGetUniformLocation(shaderProgram, "ourColor");
glUseProgram(shaderProgram);
glUniform4f(colorLocation,val0, val1, val2, val3);//根据变量类型使用不同函数
glUniform是个c库,不支持重载,不同变量类型需要使用不同的函数。QT中已经封装好了,不需要考虑变量类型。
例子,通过QT信号槽动态改变函数
#include <QTimer>
private:
QTimer timer;
public slots:
void on_timout();
//构造函数
timer.start(100);
connect(&timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
void on_timout()
{
makeCurrent();
int timeValue = QTime::currentTime().second();
float greenval = (sin(timeValue) / 2.0f) + 0.5f;
shaderProgram.setUniformValue("ourColor", 0.0f, greenval, 0.0f, 1.0f);
doneCurrent();
update();
}