温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

WebG多重纹理方法怎么使用

发布时间:2023-04-19 15:38:27 来源:亿速云 阅读:121 作者:iii 栏目:开发技术

今天小编给大家分享一下WebG多重纹理方法怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    激活

    在使用纹理单元之前,得需要激活纹理单元

    activeTexture()

    参数:

    • 指定准备激活的纹理单元:webgl.TEXTURE0、webgl.TEXTURE1...最后的数字表示纹理单元的编号

    绑定

    这一步,需要告诉WebGL系统纹理对象使用的是何种类型的纹理,在对该对象的操作之前,需要先绑定该对象,这和之前的缓冲区对象的数据写操作类似。

    bindTexture(webgl.TEXTURE_2D, texture0)

    参数:

    • webgl.TEXTURE_2D: 二维纹理;webgl.TEXTURE_CUBE_MAP: 立方体纹理

    • texture0:需要绑定指定的纹理对象

    该方法开启纹理对象,以及将纹理对象texture0绑定到纹理单元webgl.TEXTURE0上,之后通过操作纹理单元去操作纹理对象。

    配置

    这儿主要是对纹理对象具体的信息操作了,例如纹理单元类型、尺寸、是否裁剪、纹理的展示方式(放大或缩小)等,下面我们再一一分析。

    texParameteri(target, pname, param)

    参数:

    • target: webgl.TEXTURE_2D或webgl.TEXTURE_CUBE_MAP

    • pname: webgl.TEXTURE_MAG_FILTER纹理放大,例如16x16的纹理图像映射到32x32的像素空间中;webgl.TEXTURE_MIN_FILTER纹理缩小, 应用场景相反;webgl.TEXTURE_WRAP_S纹理水平轴(ST坐标系统)方向填充;webgl.TEXTURE_WRAP_T纹理T轴方向填充。

    • param: webgl.LINEAR线性变换,使用距离像素中心最近的四个点,进行线性平均加权,然后作为新的颜色值; webgl.NEAREST最近的距离优先,新的像素值取中心像素的值;CLAMP_TO_EDGE: 设置纹理 S/T 轴方向上的边缘环绕方式为CLAMP_TO_EDGE,即在超出边缘的部分使用纹理边缘的像素颜色填充. webgl.REPEAT纹理重复补充;webgl.MIRRORED_REPEAT:纹理镜像对称式重复

    会发现参数pname、param中的参数常量分类比较多,对应的分类是

    • pname : TEXTURE_MAG_FILTER、TEXTURE_MIN_FILTER

    • param: NEAREST、LINEAR

    • pname : TEXTURE_WRAP_S、TEXTURE_WRAP_T

    • param: REPEAT、MIRRORED_REPEAT、CLAMP_TO_EDGE

    分配

    纹理对象信息配置好后,接着可以将纹理图像分配给纹理对象

    webgl.texImage2D(target, level, internalformat, format type, image)

    参数:

    • target: webgl.TEXTURE_2D或webgl.TEXTURE_CUBE_MAP

    • level: 指定纹理缓冲区中要加载的纹理级别,一般为 0

    • internalformat: 纹理对象内部数据格式,通常使用webgl.RGBA

    • format: 纹理数据格式,必须与internalformat相同的值

    • type: 纹理数据类型

    • image: 纹理对象中image对象

    其中的纹理数据类型有:

    webgl.UNSIGNED_BYTE: 无符号整型,每个颜色分量占据1字节
    webgl.UNSIGNED_SHORT_5_6_5:RGB
    webgl.UNSIGNED_SHORT_4_4_4:RGBA
    webgl.UNSIGNED_SHORT_5_5_5_1:RGBA

    传递

    经过上面一系列准备后,我们就可以把最终的纹理单元传递给片元着色器了,这儿就用到了方法 webgl.uniform1i(),上篇这个方法已经说过了,就不再说明了。

    主要看看片元着色器中是怎么做的

    uniform sampler2D texture;
    varying vec2 inUV;
    vec4 color1=texture2D(texture, vec2(inUV.x, 1.0 - inUV.y));
    gl_FragColor=color1;
    • 定义了一个可以在外部访问的一种特殊的、专用于纹理对象的数据类型sampler2D,就是对应的纹理单元类型webgl.TEXTURE_2D;如果是webgl.TEXTURE_CUBE_MAP呢,则是samplerCube.

    • 通过uniform1i方法,将纹理对象传递到了片元着色器中的texture变量

    • inUV接收顶点着色器中的顶点的纹理坐标,当然这里的纹理坐标是在外部设置的

    • texture2D()在片元着色器中根据纹理坐标获取纹理图像上的纹素的颜色

    • 把获取到的颜色赋值给片元着色器

    经过对纹理的加载、设置、映射,剩下的就是绘画了。

    webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4)

    代码

    着色器设置

    const VSHADER_SOURCE = `
      attribute vec2 a_position;
      attribute vec2 outUV;
      varying vec2 inUV;
      void main(void){
        gl_Position=vec4(a_position, 0.0, 1.0);
        inUV=outUV;
      }
    `
    const FSHADER_SOURCE = `
      precision mediump float;
      uniform sampler2D texture;
      uniform sampler2D texture1;
      varying vec2 inUV;
      uniform float anim;
      void main(void){
        vec4 color1=texture2D(texture, vec2(inUV.x, 1.0 - inUV.y));
        vec4 color2=texture2D(texture1, vec2(inUV.x + anim, 1.0 - inUV.y));
        gl_FragColor=color1+color2;
      }
    `

    数据缓存区的设置

    const initBuffer = async () => {
      let positions = [
        0.8, -0.8,
        -0.8, -0.8,
        0.8, 0.8,
        -0.8, 0.8,
      ]
      let pointPosition = new Float32Array(positions)
      let aPsotion = webgl.getAttribLocation(webgl.program, "a_position")
      let triangleBuffer = webgl.createBuffer()
      webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
      webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW)
      webgl.enableVertexAttribArray(aPsotion)
      webgl.vertexAttribPointer(aPsotion, 2, webgl.FLOAT, false, 0, 0)
      var texCoords = [
        1, 0,
        0, 0,
        1, 1,
        0, 1,
      ]
      const attribOutUV = webgl.getAttribLocation(webgl.program, "outUV")
      let texCoordBuffer = webgl.createBuffer()
      webgl.bindBuffer(webgl.ARRAY_BUFFER, texCoordBuffer)
      webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(texCoords), webgl.STATIC_DRAW)
      webgl.enableVertexAttribArray(attribOutUV)
      webgl.vertexAttribPointer(attribOutUV, 2, webgl.FLOAT, false, 0, 0)
      uniformTexture = webgl.getUniformLocation(webgl.program, "texture")
      uniformTexture1 = webgl.getUniformLocation(webgl.program, "texture1")
      texture0 = await initTexture('/web-gl/landscape.png')
      texture1 = await initTexture("/web-gl/fog.png")
    }

    主要是设置顶点坐标和纹理坐标的数据

    纹理对象的初始化

    const initTexture = (imageSrc: string): Promise<WebGLTexture> => {
      return new Promise((resolve, reject) => {
        let textureHandle = webgl.createTexture()
        const image = new Image()
        image.onload = function () {
          webgl.bindTexture(webgl.TEXTURE_2D, textureHandle)
          webgl.texParameteri(
            webgl.TEXTURE_2D,
            webgl.TEXTURE_WRAP_S,
            webgl.CLAMP_TO_EDGE
          )
          webgl.texParameteri(
            webgl.TEXTURE_2D,
            webgl.TEXTURE_WRAP_T,
            webgl.CLAMP_TO_EDGE
          )
          webgl.texParameteri(
            webgl.TEXTURE_2D,
            webgl.TEXTURE_MIN_FILTER,
            webgl.LINEAR
          )
          webgl.texImage2D(
            webgl.TEXTURE_2D,
            0,
            webgl.RGBA,
            webgl.RGBA,
            webgl.UNSIGNED_BYTE,
            image
          )
          resolve(textureHandle)
        }
        image.onerror = reject
        image.src = imageSrc
      })
    }

    这儿需要使用异步方法,因为需要在image.onload方法中返回设置信息数据后的纹理对象。 在 webgl 的纹理加载中,由于图片是异步加载的,因此我们需要使用 Promise 来处理加载完毕后的回调函数。

    绘制和动态变化

    const updateCount = () => {
      count = count + 0.001
      if (count >= 1.14) {
        count = -1.0
      }
    }
    const draw = () => {
      webgl.clearColor(0.0, 1.0, 1.0, 1.0)
      webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT)
      webgl.enable(webgl.DEPTH_TEST)
      //纹理变动
      uniformAnim = webgl.getUniformLocation(webgl.program, "anim");
      updateCount()
      webgl.uniform1f(uniformAnim, count);
      webgl.activeTexture(webgl.TEXTURE0)
      webgl.bindTexture(webgl.TEXTURE_2D, texture0)
      webgl.uniform1i(uniformTexture, 0)
      webgl.activeTexture(webgl.TEXTURE1)
      webgl.bindTexture(webgl.TEXTURE_2D, texture1)
      webgl.uniform1i(uniformTexture1, 1)
      webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4)
      requestAnimationFrame(draw)
    }

    以上就是“WebG多重纹理方法怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI