首页 > 代码库 > GLSL部分小汇总

GLSL部分小汇总

一、类型限定符:
    const, in, out, uniform
1、in: 指定变量为着色器阶段的一个输入,输入可能是顶点属性(用于顶点着色器)或插值变量(用于片段着色器).
    片段着色器可进一步限制其输入值,但要和in组合使用才有效:
  centroid: 在打开多点采样时,强迫一个片段输入变量的采样位于图元像素的覆盖区域内。
  smooth: 以透视校正的方式插值片段输入变量。
  flat: 不对片段输入插值。
  noperspective: 线性插值片段变量。
2、out: 指定变量为着色器阶段的一个输出.
  顶点着色器可以使用centroid关键字限定其输出值,但必须有一个匹配的centroid片段着色器输入。
3、uniform: 指定这个值从应用程序传递个着色器,并在一个特定的图元中保持为常数值。uniform变量是由顶点着色器和片段着色器
共享的,必须声明为全局变量。
  eg: uniform vec4 baseColor;
    在着色器中,可以通过名字来引用baseColor, 但是为了在应用程序中设置它的值,需要一些额外工作。当GLSL编译器连接到着色
器程序后,它会创建一个表格,其中包含了所有的uniform变量。为了在;应用程序中设置baseColor的值,需要获取baseColor在表
中的索引值:
    GLint glGetUniformLocation(GLuint program, const char* name);
    获取了uniform变量的相关索引值,就可以设置这个变量的值:
    void glUniform2iv(GLuint location TYPE value);
    void glUniform3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *values);
    void glUniformMatrix3fv(GLint location, GLsizei count,
                            GLboolean transpose, const GLfloat *values);
    void glUniformMatrix2X3fv(GLint location, GLsizei count,
                              GLboolean transpose, const GLfloat *values);
    //若transpose是GL_TRUE, values是按行主序指定,若是GL_FALSE,values是按列主序指定的。
eg:
    GLint timeLoc;
    GLfloat timeValue;
    timeLoc = glGetUniformLocation(program, "time");
    glUniform1f(timeLoc, timeValue);
二、多个着色器程序使用同一个uniform值:
1、在着色器中指定uniform变量:
    uniform Matrices{       //除了采样器,所有类型都可放在uniform块中;have to全局uniform块
        mat4 ModelView;
        mat4 Projection;
        mat4 Color;  //注意分号
    };
   uniform块的布局限定符:
   1shared:指定uniform块在多个程序间共享(默认的共享设置)
   2)packed: 布局uniform块以使其使用的内存最小化,这通常不允许跨程序共享
   3)std140: 为uniform块使用OpenGL规范中描述的默认布局
   4)row_major: uniform块中的矩阵按照行主序的方式存储
   5)column_major: 矩阵按照列主序的方式存储(默认的排序)
eg:
     //指定一个单个的uniform块共享,且按照行主序的方式存储矩阵:
     layout (shared, row_major) uniform{...};    //句末分号
     //影响到互殴uniform块的布局:
     layout (packed, column_major) uniform;
2、访问在uniform块中声明的uniform变量:
     在两个uniform块中声明具有相同名称的两个变量将会导致错误,但当访问一个uniform变量时,没必要使用uniform块名。
1)找到指定的uniform块中的各个uniform变量在着色器中的偏移量,先得找到块的索引:
     GLuint glGetUniformBlockIndex(GLuint program, const char* uniformBlockName);
    //若uniformBlockName不是program的一个有效uniform块,将返回GL_INVALID_INDEX
要初始化与uniform块相关的一个缓冲区对象,需要使用glBindBuffer()吧缓冲区对象绑定到GL_UNIFORM_BUFFER目标
初始化了一个缓冲区对象后,需要确定从着色器中留出多大空间来容纳指定的uniform块中的变量:
    glGetActiveUniformBlockiv()请求GL_UNIFORM_BLOCK_DATA_SIZE,返回编译器生成的块的大小。
2)获取uniform块索引后,需要把一个帧缓冲区对象和该块联系起来:
    void glBindBufferRange(GLenum target, GLuint index, GLuint buffer,
                           GLintptr offset,GLsizeiptr size);
    void glBindBufferBase(GLenum target, GLuint index, GLuint buffer);//所有的缓冲区存储都用于uniform块
    //target: GL_UNIFORM_BUFFER(用于uniform块),GL_TRANSFORM_FEEDBACK_BUFFER(用于变换反馈)
  指定一个特定名称的uniform块绑定到一个缓冲区对象,在调用glLinkProgram()之前调用glUniformBlockBind():
    GLint glUniformBlockBind(GLuint program, GLuint uniformBlockIndex, Gluint uniformBlockBinding);
    //如果有多个着色器程序要共享一个uniform快,可采用此方法,它避免了为每个程序分配一个不同的块索引。
3)uniform变量在一个具名的uniform块中的布局由指定的布局限定符来控制,这在编译和连接uniform块的时候进行。如果使用默认的
布局指定,需要确定uniform块中的每个变量的offset和数据存储size:
    //获取一个特定的具名uniform变量的索引:
    void glGetUniformIndices(Gluint program, GLsizei uniformCount,
                             const char** uniformNames,GLuint *uniformIndices);
    //获取这个特定索引的offset和size:
     void glGetActiveUniformsiv(GLuint program?, GLsizei uniformCount?, const GLuint *uniformIndices?,
                                GLenum pname?, GLint *params?);
三、计算不变性:
    GLSL并不保证不同的着色器中的两个相同的计算将产生完全相同的结果,使用invariant关键字,强制在着色器之间实行这种类型
的不变性。invariant限定符可以应用于顶点着色器的任何输出varying变量:
    invariant gl_Position;
    invariant centroid varying vec3 color;
//varying变量用于把顶点着色器的数据传递给片段着色器,不变性变量必须在顶点和片段着色器中都声明为invariant
四、GLSL函数的访问限定符:
    GLSL不能返回数组,不存在指针和引用的概念。函数的参数访问限定符:
    in: 值复制到函数中,默认。
    const in: 只读,复制到函数中。
    out: 值从函数中复制出来,在传递给函数之前未初始化。
    inout: 值复制到函数中,并从函数中复制出来。
五、GLSL支持在顶点着色器(可选)和片段着色器(必须)中使用纹理对象。
    为了使用纹理图像,GLSL把一个在OpenGL应用程序中配置的活动纹理单元与着色器中的一个变量相关联。这个变量允许着色器
程序访问纹理图像的数据,相关的纹理图像的维数必须与采样器的类型相匹配。采样器名称:
   [is]smapler[123]D  //访问1/2/3D纹理图像
   usample[123]D
   [is]samplerCube  //访问立方体纹理图像(对于反射贴图)
   usamplerCube
   [is]sampler[12]DArray  //访问1/2D纹理图像的一个数组
   usampler[12]DArray
   [is]sampler2DRect        //访问一个2D纹理矩形
   usampler2DRect
   sampler[12]DShadow       //访问1/2D阴影纹理
   samplerCubeShadow        //访问立方体阴影纹理
   sampler1/2DArrayShadow     //访问1/2阴影纹理的一个数组
   sampler2DRectShadow      //访问2D阴影纹理矩形
   [is]samplerBuffer         //访问纹理缓冲区
   usamplerBuffer
    采样器必须在着色器中声明为uniform变量,它们的赋值必须来自OpenGL应用程序。可作为函数参数。
    采样器在着色器中使用之前必须分配一个纹理单位,并且只能通过glUniform1i()、glUniform1iv()初始化(把采样器应该
使用的纹理单位的索引作为参数)。
  eg:
    GLint texSampler;
    texSampler = glGetUniformLocation(program, "tex ");
    glUniform1i(texSampler, 2);    //设置"tex " 使用GL_TEXTURE2

当在GLSL着色器内部对一幅纹理图像进行采样时,需要使用已经声明并与一个纹理单位相关联的采样器变量。
eg:     //在一个GLSL着色器内部对纹理进行采样
    uniform sampler2D tex;
    void main(){
        gl_FragColor = gl_Color * texture2D(tex, gl_TexCoord[0].st);
    }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


GLSL部分小汇总