小白学webgl合集-WebGL中给图片添加背景

一.实现效果

二.逻辑

为了在WebGL中给图片添加背景,主要的逻辑步骤包括初始化WebGL上下文、编写和编译着色器、创建和绑定缓冲区、加载和配置纹理以及绘制场景。以下是代码逻辑的详细说明:

1. 获取WebGL上下文

首先,通过获取<canvas>元素并调用getContext('webgl')方法来初始化WebGL上下文。

const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');

2. 定义顶点着色器和片段着色器

编写顶点着色器(vertex shader)和片段着色器(fragment shader)。顶点着色器负责处理顶点数据,并将纹理坐标传递给片段着色器;片段着色器则使用纹理坐标来获取纹理颜色,并将其绘制到屏幕上。

const vsSource = `
    attribute vec4 aPosition;
    attribute vec2 aTexCoord;
    varying vec2 vTexCoord;
    void main() {
        gl_Position = aPosition;
        vTexCoord = aTexCoord;
    }
`;

const fsSource = `
    precision mediump float;
    varying vec2 vTexCoord;
    uniform sampler2D uSampler;
    void main() {
        gl_FragColor = texture2D(uSampler, vTexCoord);
    }
`;

3. 初始化WebGL着色器程序

编译和链接着色器程序,然后使用该程序。

const program = initShader(gl, vsSource, fsSource);
gl.useProgram(program);

4. 定义顶点数据和索引数据

定义包含顶点位置和纹理坐标的顶点数据,以及用于绘制四边形的索引数据。顶点数据每个顶点包含5个元素(x, y, z, s, t),其中(x, y, z)是顶点位置,(s, t)是纹理坐标。

const vertices = new Float32Array([
    -1.0,  1.0, 0.0, 0.0, 1.0,
    -1.0, -1.0, 0.0, 0.0, 0.0,
     1.0,  1.0, 0.0, 1.0, 1.0,
     1.0, -1.0, 0.0, 1.0, 0.0,
]);

const indices = new Uint16Array([0, 1, 2, 1, 2, 3]);

const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

5. 获取着色器中的变量位置并启用顶点属性数组

获取着色器中属性和统一变量的位置,并启用顶点属性数组。

const aPosition = gl.getAttribLocation(program, 'aPosition');
const aTexCoord = gl.getAttribLocation(program, 'aTexCoord');
const uSampler = gl.getUniformLocation(program, 'uSampler');

gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 20, 0);
gl.enableVertexAttribArray(aPosition);

gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 20, 12);
gl.enableVertexAttribArray(aTexCoord);

6. 创建纹理对象并加载图片

创建纹理对象,加载图片并配置纹理参数。当图片加载完成时,配置纹理并调用绘制函数。

const texture = gl.createTexture();
const image = new Image();
image.src = '../asset/border.png'; // 这里需要指定背景图片的路径
image.onload = () => {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // 翻转图片Y轴

    // 配置纹理参数
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    // 配置纹理图像
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
    gl.uniform1i(uSampler, 0);

    // 绘制场景
    drawScene();
}

7. 绘制场景

清除颜色缓冲区,激活纹理单元并绑定纹理,绘制包含纹理的四边形。

function drawScene() {
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.activeTexture(gl.TEXTURE0); // 激活纹理单元
    gl.bindTexture(gl.TEXTURE_2D, texture);

    // 绘制背景
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}

三.完整代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>WebGL Background Image</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      canvas {
        margin: 50px auto 0;
        display: block;
        background: yellow;
      }
    </style>
    <script src="test.js"></script>
  </head>
  <body>
    <canvas id="canvas" width="400" height="400"></canvas>
    <script>
      // 获取WebGL上下文
      const canvas = document.getElementById('canvas')
      const gl = canvas.getContext('webgl')

      if (!gl) {
        console.error('Unable to initialize WebGL.')
      } else {
        // 定义顶点着色器和片段着色器
        const vsSource = `
                attribute vec4 aPosition;
                attribute vec2 aTexCoord;
                varying vec2 vTexCoord;
                void main() {
                    gl_Position = aPosition;
                    vTexCoord = aTexCoord;
                }
            `

        const fsSource = `
                precision mediump float;
                varying vec2 vTexCoord;
                uniform sampler2D uSampler;
                void main() {
                    gl_FragColor = texture2D(uSampler, vTexCoord);
                }
            `

        const program = initShader(gl, vsSource, fsSource)
        gl.useProgram(program)

        // 定义顶点数据
        const vertices = new Float32Array([
          -1.0, 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 0.0
        ])

        const indices = new Uint16Array([0, 1, 2, 1, 2, 3])

        const vertexBuffer = gl.createBuffer()
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)

        const indexBuffer = gl.createBuffer()
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW)

        // 获取着色器中的变量位置
        const aPosition = gl.getAttribLocation(program, 'aPosition')
        const aTexCoord = gl.getAttribLocation(program, 'aTexCoord')
        const uSampler = gl.getUniformLocation(program, 'uSampler')

        gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 20, 0)
        gl.enableVertexAttribArray(aPosition)

        gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 20, 12)
        gl.enableVertexAttribArray(aTexCoord)

        // 创建纹理对象
        const texture = gl.createTexture()
        const image = new Image()
        image.src = '../asset/border.png' // 这里需要指定背景图片的路径
        image.onload = () => {
          gl.bindTexture(gl.TEXTURE_2D, texture)
          gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1) // 翻转图片Y轴

          // 配置纹理参数
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

          // 配置纹理图像
          gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image)
          gl.uniform1i(uSampler, 0)

          // 绘制场景
          drawScene()
        }

        // 绘制场景
        function drawScene() {
          gl.clear(gl.COLOR_BUFFER_BIT)

          gl.activeTexture(gl.TEXTURE0) // 激活纹理单元
          gl.bindTexture(gl.TEXTURE_2D, texture)

          // 绘制背景
          gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)
        }
      }
    </script>
  </body>
</html>

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值