[Qt和GLSL的笔记4] GLSL基本语法和数据类型

来源:互联网 发布:c语言计算闰年switch 编辑:程序博客网 时间:2024/06/08 08:51

时间:2017年4月21日(大三下学期)

作者:RyuZhihao123 (Northwest A&F University,985/211)


Qt和GLSL开发4 - GLSL基本语法和数据类型

写在前面:

       虽然说这一部分是GLSL中比较常见的内容。但是在下面的文章里,我有添加一些关于Qt中如何使用的方法和小例子,比如如何使用Qt设置uniform变量的值等等。在其他平台上使用过GLSL的可能会看起来比较简单,只需要关心在Qt中相应的使用方法就好。

      这个是在下文中使用到的Qt代码的下载链接:

        http://download.csdn.net/detail/mahabharata_/9822537

一、数据类型

1. GLSL的基本数据类型

      float、int、bool等等,和C语言类似。

2. GLSL的向量vec:

      vec2、vec3、vec4: 长度为2,3,4的float向量。

      bvec2、bvec3、bvec4:长度为2,3,4的bool向量。

      ivec2、ivec3、ivec4:长度为2,3,4的int向量。

      注:长度为4的vec4,可能有不同的含义。它可能表示坐标(x、y、z、w),也可以是颜色(r、g、b、a),还可以是纹理坐标(s、t、p、q)。这个时候,我们可以使用不同的成员来访问其值,也就是说我们允许下面的代码:

vec4 a = vec4(1,2,3,4);a.x = 2; a.y = 1; a.z = 2; a.w = 3;  // 代表坐标a.r = 2; a.g = 1; a.b = 2; a.a = 3;  // 代表颜色a.s = 3; a.t = 1; a.p = 2; a.q = 3;  // 代表纹理

3. GLSL的矩阵mat:

      mat2: 2x2的float矩阵

      mat3:3x3的float矩阵

      mat4:4x4的float矩阵

4. GLSL的纹理采样器sampler:

      sampler1D - 一维纹理

      sampler2D - 二维纹理

      此外,还有sampler3D、samplerCube、sampler1DShadow、sampler2DShadow等。

5. GLSL允许声明、访问数组。但是不能边声明边初始化。

6. GLSL允许定义结构体

struct point{    vec3 pos;    vec3 dir;};

二、变量

1. 对于基本数据类型的变量,使用和C语言一样。

2. 对于向量和矩阵类型的赋值和初始化,也和C语言差不多。

3. [特殊] GLSL提供的使用的选择子(selector),可以简化我们的操作并让代码更简洁。例如:

vec4 a = vec4(1,2,3,4);vec2 av2 = a.xy;  // 仅仅获取a的xy信息vec3 ac3 = a.rbb; // 仅仅获取a的rbb信息。


三、变量修饰符(所有变量均不可以跨shader访问)

总共四种:constvaryinguniformattribute

1. const:

     声明一个常量。

2. varying:

     用于从顶点shader向片段shader传递信息。在顶点着色器中声明并可写可读,在片段着色器中可读不可写(这个可以参考我前面给的例子~~)。

3. uniform:

     用于从OpenGL主程序向shader传递信息。在两个shader中只读。

     在Qt中:通过QGLShaderProgram::setUniformValue()函数指定。

     Qt函数:QGLShaderProgram::setUniformValue(char* name, Type value);

           第一个参数为一个字符串,其值为shader中的uniform变量的名字。表示是哪个uniform变量。

           第二个参数为一个具体的值,含义是该uniform变量的值被设置为value。

[Uniform - 穿插的一个例子] 一个颜色不断变化的小球:

代码链接:http://download.csdn.net/detail/mahabharata_/9822537

其中,片段着色器代码为:

varying vec4 v_position;varying float v_cosin;uniform float time;  // 从 OpenGL主程序获取的值。当前时间。void main(void){    // 预设的颜色(随时间变化)    float r = 1.0*cos(time)*cos(time);    float g = 1.0*sin(time);    float b = 1.0*cos(time)*sin(time);    // glFragColor表示该片段的最终颜色。    gl_FragColor = vec4(v_cosin * r, v_cosin * g, v_cosin * b, 1.0f);}
相应的在opengl主程序的时间槽函数中不断修改(uniform)time的值:
void Widget::slot_time(){    program.setUniformValue("time",elapsed);  // 修改(uniform float) time变量;    elapsed+=0.03;    updateGL();}


4. attribute:

       用于从OpenGL主程序向shader传递信息。仅是只能在vertex shader中使用的可读不可写变量。(不能再fragment shader中声明attribute变量,也不能使用)

       在Qt中,通过QGLShaderProgram::setAttributeValue()使用。用法和前面的uniform类似。


说明:uniform和attribute变量:

      1. 其实两者除了attribute在片段着色器中不可用以外,本质上没有什么太大区别。

      2. 但是习惯上,用attribute表示顶点的顶点坐标、纹理坐标、顶点颜色。其他信息如参数、材质、变换矩阵等等大多用unifrom表示。

例如:

uniform mat4 u_matViewProjection;  // 矩阵uniform float time;                // 参数attribute vec4 a_position;         // 顶点坐标attribute vec2 a_texCoord0;        // 纹理坐标varying vec2 v_texCoord;  // 传递给片段着色器的纹理坐标void main(void){    gl_Position = u_matViewProjection * a_position;    v_texCoord = a_texCoord0;}

四、內建变量和函数(build-in variables and functions)

1. 內建变量需要从opengl主程序通过特定函数传入):

    attribute vec4 gl_Vertex;                             // 由glVertex()指定的顶点坐标(未进行投影、模型视图变换)

    attribute vec4 gl_Color;                              // 由glColor()指定的顶点颜色

    attribute vec4 glSecondaryColor;             // 顶点的辅助颜色

    attribute vec3 gl_Normal;                          // 由glNormal()指定的顶点法向量

    attribute vec4 gl_MultiTexCoord[0-N];     // 顶点纹理坐标(N = gl_MaxTextureCoords)

    attribute float gl_FogCoord;                      // 顶点的雾坐标(深度)

    注意,在Qt中,我们可以使用QGLShaderProgram::setAttributeValue()为自定义的attribute变量传值。


    uniform mat4 gl_ModelViewMatrix;                      // 模型视图矩阵(model-view matrix)

                     --- 通过gluLookAt()及glTranslate()等模型视图矩阵变换的当前状态决定。

    uniform mat4 gl_ProjectMatrix;                              // 投影矩阵(project matrix)

                     --- 通过gluPerspective()等函数决定

    uniform mat4 gl_ModelViewProjectionMatrix;     // 模型视图-投影矩阵

    uniform mat3 gl_NormalMatrix;                             // 法向量变换到视空间的矩阵

    uniform float gl_NormalScale;                               // 普通缩放因子

    当然,在Qt中,我们也可以拥有QGLShaderProgram::setUniform()为自定义的uniform变量传值。 


说明:

         1. 这里仅仅列出了一部分GLSL的内置变量,其他内置变量可以再Google或者下面的博客中找到:

              http://blog.csdn.net/dancing_night/article/details/50897510

         2. 关于GLSL的內建函数,可以再下面的链接中获取到相关内容:

              http://blog.csdn.net/hgl868/article/details/7876257

         3. 如何在顶点着色器中获取经过变换后的顶点、法向量(常用写法):

varying vec4 v_normal;   // 变换后的法向量varying vec4 v_position; // 变换后的坐标void main(void){    // 顶点着色器的唯一输出:gl_Position;    gl_Position = gl_ProjectionMatrix*gl_ModelViewMatrix*gl_Vertex;    v_position = gl_Position;    v_normal = gl_NormalMatrix*gl_Normal; }

     

3 0