Loading

[CG] WebGL Shader中的数据和简单的工作流

1 Shader中的数据

1.1 获取数据的方式

1.1.1 属性(attribute)和缓冲(buffer)

缓冲是发送到GPU的一些二进制数据序列,通常情况下包括位置、法向量、纹理坐标、顶点颜色值等。一下是常用的API(gl代表WebGLRenderingContext)

  • gl.createBuffer(),创建并初始化一个用于储存顶点数据或着色数据的WebGLBuffer对象
  • gl.bindBuffer(target, buffer),target是绑定点,可以理解为将缓冲绑定为当前缓冲,之后的操作就可以在这个缓冲上进行,当要对别的缓冲进行设置操作时,要绑定切换成别的缓冲。
  • gl.bufferData(target, ArrayBufferView srcData, usage, srcOffset, length),创建并初始化WebGLBuffer对象的数据存储区,可以理解为将数据复制进缓冲中。target是绑定点,srcData是将要被复制到数据存储区的数据,usage是存储区使用的方式,例如是否被经常使用?修改?srcOffset初始元素索引的偏移量。
  • gl.deleteBuffer(buffer),用于删除指定的缓冲,若已经删除,则不做操作。
  • gl.isBuffer(buffer),检查缓冲区是否有效。
  • gl.getAttribLocation(program, name),返回给定的WebGLProgram对象中某属性在program中的位置,相当于是索引。

创建缓存,绑定缓存,发送数据,查询属性的索引,一般在初始化部分完成。
接下来就是,告诉gl,我们想从缓冲中提供数据,从哪个缓冲呢?所以要bind一个我们需要缓冲到当前缓冲以便操作,然后将属性和缓冲链接起来,并设定读取、解析的方式。

  • gl.enableVertexAttribArray(index),在使用属性之前要使用此方法进行激活,没有激活的属性不会被使用。这里index是一个GLuint类型的索引值,这个值在初始化的时候一般会获取,这个索引是针对当前使用的program来说的,因为这个索引就是类似于0,1...这样的数字,不是唯一的,所以是针对当前的program来说的。
  • gl.vertexAttribPointer( index, numComponents, typeOfData, normalizeFlag, strideToNextPieceOfData, offsetIntoBuffer);
    将属性与当前gl.ARRAY_BUFFER绑定的缓冲区绑定,并指定如何从缓冲区里读取数据,index是属性的索引,numComponents为1,2,3,4中的一个,指定一个顶点数据由几个component组成,typeOfData是每个数据(component)的类型,normalizeFlag数据要不要归一化,strideToNextPieceOfData,指明顶点属性是不是紧密连续的,中间有没有空隙,一般为0,offset初始的偏移量,一般为0

属性来指明如何从缓冲中读取数据并提供给vertex shader,每次vertex shader会按照规则读取。

1.1.2 全局变量(Uniforms)

全局变量在shader program运行前赋值,在运行过程中全局有效,在一次绘制过程中,传递给shader的值都是一样的。例如Varyings的值是在fragment shader里插值得到的,所以可能每个像素的值都不同。全局变量的设置方式是,先找到全局变量的地址,然后给其设置值

  • gl.getUniformLocation(program, name),从program中找到全局变量的位置
  • gl.uniform[1234][fi][v]()(index, value),设定全局变量的值

全局变量有许多类型,每个类型都对应不同的设置方法。

1.1.3 纹理(Textures)

纹理是一个数据序列,可以在program运行中随意读取其中的数据。 大多数情况存放的是图像数据,但是纹理仅仅是数据序列, 可以随意存放除了颜色数据以外的其它数据。
在着色器中获取纹理信息,可以先创建一个sampler2D类型全局变量,然后用GLSL方法texture2D 从纹理中提取信息。在渲染的时候webGL要求纹理必须绑定到一个纹理单元上

  • uniform sampler2D u_texture
  • texture2D(u_texture, texcoord)
  • gl.getUniformLocation(someProgram, "u_texture")
  • gl.activeTexture(gl.TEXTURE0 + unit),激活指定的纹理
  • gl.bindTexture(target, texture),将纹理绑定到绑定点
  • gl.uniform1i(someSamplerLoc, unit),设定全局变量的值

1.1.4 变量(Varyings)

vertex shaderfragment shader传值的方式,依照渲染的图元是点, 线还是三角形,顶点着色器中设置的可变量会在片断着色器运行中获取不同的插值。在两个shader中,名字要定义成一样。

1.2 vertex shader

  • 属性
  • 全局
  • 纹理
    将顶点转换到裁剪空间的坐标中去,每个顶点会调用一次,设置一个特殊的变量gl_Position,裁剪空间中的坐标值,GPU接收该值,并保存

1.3 fragment shader

  • 全局
  • 纹理
  • 可变量
    基于vertex shader的结果,绘制像素点,每个像素都会调用设置gl_FragColor,定义像素颜色

2 简单的工作流

  • 初始化阶段
    1. 获取htmlcanvas元素
    2. 获取webgl上下文
    3. 获取vertex shaderfragment shader的字符串
    4. 创建和编译shader
    5. 链接两个shader,成为一个program
    6. 获取属性的地址
    7. 创建缓冲
    8. 绑定新建的缓冲到当前缓冲
    9. 给缓冲发送数据
  • 渲染阶段
    1. 从裁剪空间到像素空间
    2. 清空Canvas
    3. 设置我们要使用的program程序
    4. 打开属性
    5. 绑定缓冲到当前缓冲
    6. 将属性绑定到当前缓冲,并设置读取的方式
    7. 画图
posted @ 2020-06-02 17:29  芒果和小猫  阅读(531)  评论(0编辑  收藏  举报