QML 传递给 GLSL Shader中Uniform变量的工作原理详解
QML/QtQuick3D如何将数据传递给GLSL着色器?
例如
// 在Shader代码中直接使用 pos.x += (c0 + c1 * pos.z + c2 * pos.z * pos.z + c3 * pos.z * pos.z * pos.z);中c0,c1,c2,c3在着色器中没有声明但是又可以直接使用,为什么?
一般使用这类变量需要在GLSL中定义Uniform变量
// 标准GLSL写法 uniform float c0; uniform float c1; uniform float c2; uniform float c3; void main() { pos.x += (c0 + c1 * pos.z + c2 * pos.z * pos.z + c3 * pos.z * pos.z * pos.z); }Uniform特点:
- 全局常量:整个渲染过程中值不变
- CPU设置:由应用程序传递到GPU
- 所有顶点共享:每个顶点看到的值相同
但是在qml中可以省略这个声明,是因为QtQuick3D的自动Uniform注入机制
// TrackMaterial.qmlCustomMaterial{id:idMaterial property real c0:0.0// QML属性property real c1:0.0property real c2:0.0property real c3:0.0property vector3d p0:Qt.vector3d(0,0,0)property color trackColor:"#00FF00"property int type:1vertexShader:"shaders/track.vert"}自动生成:
// 自动插入到着色器前面uniform float c0;// 对应 property real c0uniform float c1;// 对应 property real c1uniform float c2;// 对应 property real c2uniform float c3;// 对应 property real c3uniform vec3 p0;// 对应 property vector3d p0uniform vec4 trackColor;// 对应 property color trackColoruniform int type;// 对应 property int type// 然后才是着色器代码 in vec3 attr_pos; ... void main() { // 现在可以直接使用 c0, c1,c2,c3, p0, trackColor, type }QtQuick3D会自动:
扫描QML中的
property生成对应的
uniform声明将值传递到着色器
以下是对应表单
| QML类型 | GLSL类型 | 示例 |
|---|---|---|
real/double | float | property real c0: 0.0→uniform float c0; |
int | int | property int type: 1→uniform int type; |
vector2d | vec2 | property vector2d pos: Qt.vector2d(0,0)→uniform vec2 pos; |
vector3d | vec3 | property vector3d p0: Qt.vector3d(0,0,0)→uniform vec3 p0; |
vector4d | vec4 | property vector4d data: Qt.vector4d(...)→uniform vec4 data; |
color | vec4 | property color clr: "#FF0000"→uniform vec4 clr; |
matrix4x4 | mat4 | property matrix4x4 mat→uniform mat4 mat; |