WebGL 添加背景图

news/2024/10/24 15:01:00/

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) {// Promisereturn 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.ppmy.cn/news/1541615.html

相关文章

python 结构作业

基础练习 练习目标 if-else判断语句 while循环语句 01. 计算车费 题目描述 小红打车,起步价8元(3公里), 每公里收费 2 元,她打车行驶了 n 公里,计算车费 输入描述 输入一个公里数 输出描述 输出应付车费 示例 输入: 5 …

使用gpt2-medium基座说明模型微调

预训练与微调的背景 预训练:在大规模数据集上训练模型,以捕捉通用的特征和模式。例如,GPT-2 模型在大量文本上进行训练,学习语言的基本结构和语法。微调:在特定领域或任务的数据上对预训练模型进行训练,以…

1024程序员节祝福

1024程序员节祝福 在每年的10月24日,我们迎来了属于程序员的节日——1024程序员节。这个特殊的日子,既是对广大程序员辛勤工作的致敬,也是对他们在科技创新和数字时代进步中做出贡献的认可。在这个值得庆祝的日子里,我想对所有程…

力扣每日一题3185. 构成整天的下标对数目 II

今天的题目没啥好说的,就是昨天的题目的进阶版,用昨天题解的最终版就可以直接过了 今天的就不写思路了,有需要就看昨天的就好了 力扣每日打卡挑战 3184. 构成整天的下标对数目 I class Solution { public:int countCompleteDayPairs(vecto…

WPF+Mvvm项目入门完整教程-基于SqlSugar的数据库实例(三)

目录 数据库实现创建数据库类库资源获取 在上一节中,我们实现了主页UI框架和基础菜单功能,本节主要实现数据库的类库创建、数据功能接口以及泛型方法实现。本例使用的数据库为 MySql数据库,ORM框架采用 SqlSugar 实现。 数据库实现 创建数据…

【计算机网络 - 基础问题】每日 3 题(四十九)

✍个人博客:https://blog.csdn.net/Newin2020?typeblog 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞…

百度开源语音识别强大工具PaddleSpeech从0到1快速上手:安装、部署、Debug与测试详尽指南

目录 Introduction 导言PaddleSpeech安装部署和测试环境要求:安装参考:安装整体过程如下:使用代码示例:Bug处理模型选择性能测试 参考资料其它资料下载 Introduction 导言 在当今快速发展的人工智能领域,语音识别技术…

JavaScript 在网页设计中的四大精彩案例:画布时钟、自动轮播图、表单验证与可拖动元素

在网页开发中,JavaScript 发挥着至关重要的作用,为网页带来丰富的交互性和动态效果,极大地提升了用户体验。本文将通过几个具体案例展示 JavaScript 的强大魅力。 一、美丽的画布时钟 这是一个使用 JavaScript 在网页上创建美丽画布时钟的案…