当前位置: 首页 > article >正文

WebGL 添加背景图

1. 纹理坐标(st坐标)简介

ST纹理坐标(也称为UV坐标)是一种二维坐标系统,用于在三维模型的表面上精确地定位二维纹理图像。这种坐标系统通常将纹理的左下角映射到(0,0),而右上角映射到(1,1)。

  • S坐标(U坐标):通常对应纹理图像的水平方向,即纹理的宽度。
  • T坐标(V坐标):通常对应纹理图像的垂直方向,即纹理的高度。

1.1 纹理坐标的工作原理

  • 纹理坐标的范围通常是从0.0到1.0,其中(0.0, 0.0)代表纹理的左下角,而(1.0, 1.0)代表右上角。
  • 在WebGL中,纹理坐标系统的t轴(垂直轴)与传统图像文件的y轴方向相反,这意味着当你在WebGL中使用纹理时,通常需要翻转图像的Y轴以确保正确的映射。
  • 这可以通过设置gl.UNPACK_FLIP_Y_WEBGL为1来实现。

2. 基本步骤

​​​​2.1 创建纹理对象

  • 使用gl.createTexture()创建一个新的纹理对象。
  • 可以通过 gl.deleteTexture(textrue)来删除纹理对象。
 const texture = gl.createTexture();

2.2 翻转图片Y轴

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); 

2.3 开启纹理单元

gl.activeTexture(gl.TEXTURE0)

2.4绑定纹理对象

使用gl.bindTexture(type, texture)将纹理对象绑定到纹理单元上。type 参数有以下两种:

  • gI.TEXTURE_2D:二维纹理
  • gI.TEXTURE_CUBE_MAP:立方体纹理
gl.bindTexture(gl.TEXTURE_2D, texture);

2.5 配置纹理参数

设置纹理的过滤方式(gl.TEXTURE_MIN_FILTER和gl.TEXTURE_MAG_FILTER)、包裹方式(gl.TEXTURE_WRAP_S和gl.TEXTURE_WRAP_T)等参数。

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);

2.6 上传纹理图像数据

使用gl.texImage2D(type, level,internalformat, format,dataType, image)将图像数据上传到纹理对象中。

2.6.1 type参数:
  • gI.TEXTURE_2D:二维纹理
  • gI.TEXTURE_CUBE_MAP:立方体纹理
2.6.2 level参数:
  • 默认为0
2.6.3 internalformat参数
  • gI.RGB
  • gI.RGBA
  • gI.ALPHA
  • gI.LUMINANCE 使用物体表面的红绿蓝 分量的加权平均值来计算
  • gI.LUMINANCE ALPHA
2.6.4 format参数
  • format 纹理的内部格式,必须和internalformat 相同
2.6.5 dataType参数
  • 9I.UNSIGNED_BYTE
  • gI.UNSIGNED_SHORT_5_6_5
  • gI.UNSIGNED_SHORT_4_4_4_4
  • gI.UNSIGNED_SHORT_5_5_5_1
 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

3. 实例代码

以下是一个简单的WebGL示例,展示了如何给一个简单的四边形添加背景图:

/** @type {HTMLCanvasElement} */
        const ctx = document.getElementById('canvas')
        const gl = ctx.getContext('webgl')
        // 顶点着色器源码
        const vertexShaderSource = `
            attribute vec4 aPosition;
            attribute vec4 aTex;
            varying vec2 vTex;

            void main() {
                gl_Position = aPosition;
                vTex = vec2(aTex.x, aTex.y);
            }`

        // 片源着色器源码
        const fragmentShaderSource = `
            precision lowp float;
            uniform sampler2D uSampler;
            varying vec2 vTex;

            void main() {
                gl_FragColor = texture2D(uSampler, vTex);
            }`
        const program = initShader(gl, vertexShaderSource, fragmentShaderSource);
        const aPosition = gl.getAttribLocation(program, 'aPosition');
        const aTex = gl.getAttribLocation(program, 'aTex');
        const uSampler = gl.getUniformLocation(program, 'uSampler');//赋值

        const points = 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,
        ])
        const buffer = gl.createBuffer();
        const BYTES = points.BYTES_PER_ELEMENT; // 偏移字节
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
        gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, BYTES * 4, 0);
        gl.enableVertexAttribArray(aPosition);
        gl.vertexAttribPointer(aTex, 2, gl.FLOAT, false, BYTES * 4, BYTES * 2);
        gl.enableVertexAttribArray(aTex);

        const img = new Image();
        img.onload = function () {
            // 创建纹理对象并加载图片
            const texture = gl.createTexture();
            // 翻转图片Y轴
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            // 开启一个单元纹理
            gl.activeTexture(gl.TEXTURE0)
            // 绑定纹理对象
            gl.bindTexture(gl.TEXTURE_2D, texture);
            // 配置纹理参数
            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, img);
            gl.uniform1i(uSampler, 0);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
        img.src = './images/img2.png';

4.效果如下

 

5. 添加多张背景图 

  • 添加几张图,就定义几个sampler2D 
// 片源着色器源码
const fragmentShaderSource = `
    precision lowp float;
    uniform sampler2D uSampler;
    uniform sampler2D uSampler1;
    varying vec2 vTex;

    void main() {
    vec4 c1 = texture2D(uSampler, vTex);
    vec4 c2 = texture2D(uSampler1, vTex);
    texture2D(uSampler1, vTex);
        gl_FragColor = c1 * c2;
    }`
  • 将创建纹理的过程封装方法
// 封装函数
        function getImage(location, url, index) {
            // Promise
            return new Promise(resolve => {
                const img = new Image();
                img.onload = function () {
                    // 创建纹理对象并加载图片
                    const texture = gl.createTexture();
                    // 翻转图片Y轴
                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
                    // 开启一个单元纹理
                    gl.activeTexture(gl[`TEXTURE${index}`])
                    // 绑定纹理对象
                    gl.bindTexture(gl.TEXTURE_2D, texture);
                    // 配置纹理参数
                    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, img);
                    gl.uniform1i(location, index);

                    resolve();
                }
                img.src = url;
            });
        }
        Promise.all([getImage(uSampler, "./images/img.png", 0), getImage(uSampler1, "./images/img2.png", 1)]).then(() => {
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        })

效果如下 


http://www.kler.cn/news/363730.html

相关文章:

  • K8S系列-Kubernetes网络
  • Python小游戏11——扑克牌消消看小游戏
  • 新脉集团携手中宏大数据 共推县域乡村振兴与数据资产化
  • 富格林:可信操作助力有效追损
  • 力扣第246题“中心对称数”
  • 基于DSP设计的多通道DC/DC数字电源系统
  • SQL 自学:游标(Cursors)的理解与应用
  • 线性可分支持向量机的原理推导 9-19基于拉格朗日函数L(w,b,α) 对b求偏导 公式解析
  • 如何在分布式环境中实现高可靠性分布式锁
  • 恋爱脑讲编程:Rust 的生命周期概念
  • 在 Spring MVC 应用程序中使用 WebMvcTest 注释有什么用处?
  • 第5.2章|25考研复试综合素质面试最常见问题50问【附上完整答案】超详细考研机械复试面试经验总结全流程 考研复试调剂问题看这一篇就够了!
  • MySql数据库中的表的操作
  • 【学习笔记】MongoDB 概念
  • ElasticSearch分片
  • 聚铭网络入选工信部《工业互联网与电力行业融合应用参考指南》推荐企业
  • 项目:负载均衡式在线 OJ
  • qt QNetworkProxy详解
  • git的安装以及入门使用
  • 手机照片怎么转换成jpg格式?分享6种图片格式转换方法
  • 【C语言】编译和链接(编译环境和运行环境)
  • Qt 中实现 HTTPS 请求的方法
  • ExecuteReader()简介
  • 输电线路杆塔基础沉降
  • Oracle Expdp按条件导出-指定表数据
  • 写一个 qq自动回话的程序