美文网首页
《WebGL 编程指南》笔记 —— 第五章 颜色与纹理

《WebGL 编程指南》笔记 —— 第五章 颜色与纹理

作者: fehysunny | 来源:发表于2017-10-01 11:20 被阅读351次

    本章主要内容:
    (1) 将顶点的其他(非坐标)数据 —— 如颜色等 —— 传入顶点着色器
    (2)发生在顶点着色器和片元着色器之间的从图形到片元的转化,又称图元光栅化(rasterzation process)
    (3)将图形(或称纹理)映射到图形或三维对象的表面上。

    1. 将顶点坐标传入着色器,步骤:
      (1)创建缓冲区对象。
      (2)将缓冲区对象绑定到tartget上。
      (3)将顶点坐标数据写入缓冲区对象。
      (4)将缓冲区对象分配给对应的 attribute 变量。
      (5)开启 attribute 变量。
    使用两个缓冲区对象向顶点着色器传输数据
    1. 交错组织(interleaving):将顶点坐标尺寸数据打包到同一缓冲区对象中。

    2. gl.vertexAttribPointer()

    gl.vertexAttribPointer()
    1. varying 变量: 从顶点着色器向片元着色器中传入数据。
      varying 变量只能是float(以及相关的vec2,vec3,vec4,mat2,mat3,mat4)。

    2. 在顶点着色器和片元着色器之间,有两个步骤:
      [1] 图形装配过程:将孤立的顶点坐标装配成几何图形。几何图形的类别由gl.drawArray() `函数的第一个参数决定。
      输入数据:gl_Position
      [2] 光栅化过程:将装配好的几何图形转为片元。

    顶点着色器和片元着色器之间的图形装配和光栅化

    步骤:
    (1)根据 gl.drawArrays()的参数n,将执行顶点着色器n次(执行顶点着色器结果:将坐标传入并存储在装配区)
    (2)开始装配图形。使用传入的点坐标,根据 gl.drawArrays()的第一个参数信息(如:gl.TRANGLES)来决定如何装配。
    (3)光栅化

    几何图形装配和光栅化过程
    1. 颜色内插(interpolation)
    颜色值的内插
    1. 纹理映射(texture mapping):根据纹理图像,为之前光栅化后的每个片元涂上合适的颜色。
      纹素(texels, texture elements):组成纹理图像的像素。每一个纹素的颜色都是用RGBRGBA格式编码。
    纹素
    1. 在WebGL中,要进行纹理映射,需遵循以下四步:
      (1)准备好映射到几何图形上的纹理图像。
      (2)为几何图形配置纹理映射方式。
      (3)加载纹理图像,对其进行一些配置,以在WebGL中使用它。
      (4)在片元着色器中将相应的纹素从纹理中抽取出来,并将纹素的颜色赋给片元。

    2. 纹理坐标
      纹理坐标是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色。
      WebGL系统中的纹理坐标系统是二维的。
      WebGL中使用s和t命名纹理坐标。(st坐标系统)

    WebGL的纹理坐标系统
    1. 将纹理图像粘贴到几何图形上
      在WebGL中,我们通过纹理图像的纹理坐标与几何图形顶点坐标间的映射关系,来确定怎样将纹理图像贴上去。
    将纹理图像映射到顶点上
    1. 纹理映射过程详解
      步骤:
      (1)顶点着色器中接收定点的纹理坐标,光栅化后传递给片元着色器。
      (2)片元着色器根据片元的纹理坐标,从纹理图像中抽取出纹素颜色,赋给当前片元。
      (3)设置顶点的纹理坐标(initVertexBuffers()
    var verticesTexCoords = new Float32Array([
      -0.5,  0.5,   0.0, 1.0,
      -0.5, -0.5,   0.0, 0.0,
       0.5,  0.5,   1.0, 1.0,
       0.5, -0.5,   1.0, 0.0,    
    ]) 
    

    将顶点坐标和纹理坐标写入缓冲区对象,将其中的顶点坐标分配给a_Position变量并开启之。

    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
    gl.enableVertexAttribArray(a_Position);
    

    获取a_TexCoord变量的存储位置,将缓冲区中的纹理坐标分配给该变量更开启。

    var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
    gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
    gl.enableVertexAttribArray(a_TexCoord);
    

    (4)准备待加载的纹理图像,令浏览器读取它(initTextures())
    initTextures() => 配置和加载问题
    调用gl.createTexture()创建纹理对象

    var texture = gl.createTexture();
    
    gl.createTexture()

    同样,也可以使用gl.deleteTeture()来删除一个纹理对象。如果试图删除一个已经被删除的纹理对象,不会报错也不会产生任何影响。

    gl.deleteTeture()

    调用gl.getUniformLocation()从片元着色器中获取uniform变量u_Sampler(取样器)的存储位置,该变量用来接收纹理图像

    var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
    

    创建image对象

    var image = new Image();
    

    注册图像加载事件的响应函数

    image.onload = function(){ loadTexture(gl, n, texture, u_Sampler, image); };
    

    浏览器开始加载图像

    image.src = '../resources/sky.jpg';
    

    (5)监听纹理图像的加载事件,一旦加载完成,就在WebGL系统中使用纹理(loadTexture())。

    loadTexture() => 配置纹理供WebGL使用

    对纹理图像进行y轴翻转(WebGL纹理坐标中的t轴的方向和PNG、BMP、JPG等格式图片的坐标系统的Y轴方向是相反的。)

    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
    
    图像坐标系统和WebGL纹理坐标系统 gl.pixelStorei()

    开启0号纹理单元
    WebGL通过纹理单元的机制来同时使用多个纹理。
    每个纹理单元有一个单元编号来管理一张纹理图像。
    系统支持的纹理单元格数取决于硬件和浏览器的WebGL实现,但是在默认情况下,WebGL至少支持8个纹理单元。
    在使用纹理单元之前,还需要调用gl.aactiveTexture()来激活它。

    gl.activeTexture(gl.TEXTURE0);
    
    gl.activeTexture()

    绑定纹理对象(设置纹理的类型)

    gl.bindTexture(gl.TEXTURE_2D, texture);
    
    纹理类型 gl.bindTexture() 将纹理坐标绑定到目标上

    配置纹理对象的参数 => 设置纹理图像映射到图形上的具体方式

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    
    gl.texParameteri() param 参数值 四种纹理参数及它们锁产生的效果 纹理参数及它们的默认值

    配置纹理图像 => 将纹理图像分配给纹理对象,同时允许你告诉WebGL系统关于该图像的一些特性。

    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
    
    gl.texImage2D() 纹素数据的数据格式

    format标示纹理数据的格式,必须根据纹理图像的格式来选择这个参数
    JPG => gl.RGB
    PNG => gl.RGBA
    BMP => gl.RGB
    gl.LUMUNANCEgl.LUMINANCE_ALPHA 通常用在灰度图像上等等
    流明(luminance)标示我们感知到的物体表面的亮度。通常使用物体表面红、蓝颜色分量指的加权平均来计算流明。

    纹理数据的数据格式

    type参数制定了纹理数据类型。通常使用gl.UNSIGNED_BYTE数据类型。

    分配后的WebGL系统:

    将图像分配给纹理对象

    将0号纹理传递给着色器中的取样器变量

    gl.uniform1i(u_Sampler, 0);
    
    uniform sampler2D u_Sampler;
    
    专用于纹理的数据类型

    分配给unform变量后的WebGL系统:

    将纹理单元分配给uniform变量

    绘制矩形

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    

    从顶点着色器向片元着色器传输纹理坐标

    var VSHADER_SOURCE =
      'attribute vec4 a_Position;\n' +
      'attribute vec2 a_TexCoord;\n' +
      'varying vec2 v_TexCoord;\n' +
      'void main() {\n' +
      '  gl_Position = a_Position;\n' +
      '  v_TexCoord = a_TexCoord;\n' +
      '}\n';
    

    在片元着色器中获取纹理像素颜色(texture2D())

     gl_FragColor = texture2D(u_Sampler, v_TexCoord);
    
    texture2D()

    相关文章

      网友评论

          本文标题:《WebGL 编程指南》笔记 —— 第五章 颜色与纹理

          本文链接:https://www.haomeiwen.com/subject/lbgoextx.html