OpenGL核心理解:Uniform

简介:

着色器的变量主要包含如下:

  • 顶点属性(Vertex Attributes):
    • 顶点着色器:输入
  • 统一变量(Uniform Variables):
    • 所有着色器:输入
  • 采样器(Samplers):
    • 片段着色器:输入
  • Varying Variables:
    • 顶点着色器:输出
    • 片段着色器:输入

这里我们要介绍的是统一变量

一. Uniform 是什么

统一变量是着色器程序(Program)特定的变量,在整个着色器程序的执行过程中(单次渲染:各种着色器),和多个物体执行中(多次渲染),都可以访问并可以保持一致(如果不主动设置,如多个物体的渲染中光源属性)。之所以叫统一,主要区别于其他变量:

  • 顶点属性:仅顶点着色器可以访问,每次渲染数据基本不同(每物体顶点不同)
  • Varying Variables:由顶点着色器创建,输出到片段着色器,每片段着色器不同
  • 采样器:属于 Uniform

二. Uniform 有什么作用

统一变量主要用于为各种渲染类型(着色器)提供控制与输入

  • 控制
    • 开关:用于切换功能开启。比如gamma矫正,模糊效果的开关。。。
    • 摄像机: 用于控制镜头。比如模型,视图,投影矩阵。。。
  • 输入
    • 材质:用于表达材质的属性。比如粗糙度,金属度。。。
    • 光源属性:用于表述光源的性质。比如位置,强度,颜色。。。

三. 什么时候使用?

一般在场景的初始时需要使用uniform,用于光源设置。更新时需要设置的情况如下:

  • 操作摄像机时
  • 渲染物体,或动态材质变化时
  • 动态光源变化时

四. 如何使用?

  • 单项设置
    1. 获取位置:单项设置需要在着色器程序(Program)编译后,根据着色器中的变量名称获取相应位置,使用函数 glGetUniformLocation
    2. 同步数据(内存->显存):根据获取的位置,按照数据类型同步数据,使用函数 glUniform*,如 glUniform1f
  • 批量同步(使用 统一变量块:Uniform Block)
    1. 获取位置:需要在着色器程序(Program)编译后,根据 统一变量块 在着色器中的名称获取索引,使用函数 glGetUniformBlockIndex
    2. 绑定到统一变量缓冲(类似于顶点缓冲,是显存中的一块数据),使用函数 glUniformBlockBinding 将着色器的 统一变量块 绑定到指定序号的统一变量缓冲中
    3. 同步数据:这里区别于单项设置,是将数据同步到缓冲中。由于是绑定,可以多个着色器绑定到同一缓冲中,所以只需要操作一次,并且可以整块数据同步。使用函数 glBufferSubData

五. 实例

  • 单项设置
    1. 先在着色器中添加变量
        uniform mat4 project;
    
    1. 根据添加的名称在代码中获取位置, program 是已编译的着色器程序
        int32_t location = glGetUniformLocation(program, "project");
    
    1. 同步数据,这里使用了 glm
        glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(project));
    
  • 批量同步
    • 批量同步有些复杂,首先它需要在显存创建缓冲区,并且同步数据时需要选择数据的布局方式,不同的布局数据的对齐方式不同,这就导致了同步数据时方案的不同,这里我使用了std140 (内存中的变量对齐与显存中变量对齐存在差异)
      • 它的每个成员变量都有一个基础偏移(距离结构体起始地址的偏移量),和一个基础对齐(变量占用的空间需要对齐)。
      • 根据基础偏移量计算基础对齐(就是说成员变量的顺序会影响每个变量占用的空间大小),方法是将基础偏移舍入到基础对齐的整数倍(下一个变量的偏移量等于当前变量基础对齐的N倍,细节请查询参考手册)。
      • 统一变量缓冲块的对齐,假如想使用一个缓冲存储多块(还可以创建多个缓冲,但都使用0号统一变量块),它也会产生一个对齐。可以通过查询系统信息获取对齐大小
          GLint BlockAlienment = 0;
          glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &BlockAlienment);
      
  • 项目链接
    • Opengl教程
      • 该项目需要使用 premake 生成VS项目, 如果不了解可以看下前文链接

参考手册:OpenGL 官方手册

前文链接:c++ 轻量跨平台构建系统 Premake

你可能感兴趣的:(图形渲染,OpengGL)