(十五)WebGL中gl.texImage2D函数使用详解

在 WebGL 中,gl.texImage2D 是一个非常关键的函数,用于将图像数据上传到 WebGL 上下文中并作为纹理对象的一部分。它允许你将图像、视频、画布等作为纹理源。理解如何使用 gl.texImage2D 是在 WebGL 中处理纹理的核心之一。

文章目录

      • `gl.texImage2D` 的基本概念
      • 具体场景和代码示例
        • 示例:使用 `gl.texImage2D` 加载和使用纹理
        • 1. HTML 文件
        • 2. JavaScript 部分:加载纹理并应用
      • 3. 代码解析
      • 4. 总结

gl.texImage2D 的基本概念

gl.texImage2D 函数的作用是将图像或像素数据上传到 WebGL 中作为纹理。纹理是 2D 图像,通常用于给 3D 模型的表面贴图,以实现更真实的渲染效果。

其语法如下:

gl.texImage2D(target, level, internalFormat, format, type, image);
  • target:纹理目标,通常使用 gl.TEXTURE_2D
  • level:纹理的细节层级,通常设置为 0(基础纹理层),大于0的值会使用到纹理的多级渐远纹理(mipmap)功能。
  • internalFormat:纹理的内部格式,指定 WebGL 如何存储纹理数据,常见的值有 gl.RGBgl.RGBAgl.LUMINANCE 等。
  • format:纹理数据的格式,定义从图像源中提取的数据类型。通常使用 gl.RGBgl.RGBA,这与图像的颜色深度相关。
  • type:指定数据类型,通常使用 gl.UNSIGNED_BYTE(8 位无符号整数)或其他格式,如 gl.FLOAT
  • image:图像数据源,可以是一个 <img> 元素、<canvas> 元素、<video> 元素,或者是一个 ImageData 对象。

具体场景和代码示例

示例:使用 gl.texImage2D 加载和使用纹理

在这个例子中,我们将一个图片加载为纹理,并将其应用到一个立方体的表面上。这里会展示如何使用 gl.texImage2D 来将图片数据上传为纹理。

1. HTML 文件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebGL - texImage2D 示例</title>
</head>
<body><canvas id="webgl-canvas" width="500" height="500"></canvas><script src="main.js"></script>
</body>
</html>
2. JavaScript 部分:加载纹理并应用
// 获取 WebGL 上下文
const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl');// 立方体的顶点数据
const vertices = new Float32Array([-0.5, -0.5, -0.5, // Front face0.5, -0.5, -0.5,0.5,  0.5, -0.5,-0.5,  0.5, -0.5,-0.5, -0.5,  0.5, // Back face0.5, -0.5,  0.5,0.5,  0.5,  0.5,-0.5,  0.5,  0.5,
]);// 立方体的纹理坐标数据 (u, v)
const texCoords = new Float32Array([0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Front face0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Back face0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Left face0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Right face0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Top face0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Bottom face
]);// 立方体的索引
const indices = new Uint16Array([0, 1, 2, 0, 2, 3,4, 5, 6, 4, 6, 7,0, 1, 5, 0, 5, 4,1, 2, 6, 1, 6, 5,2, 3, 7, 2, 7, 6,3, 0, 4, 3, 4, 7
]);// 创建缓冲区并绑定顶点数据
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// 创建纹理坐标缓冲区并绑定
const texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texCoords, 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 vertexShaderSource = `attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;void main() {gl_Position = a_position;v_texCoord = a_texCoord;}
`;const fragmentShaderSource = `precision mediump float;varying vec2 v_texCoord;uniform sampler2D u_texture;void main() {gl_FragColor = texture2D(u_texture, v_texCoord);}
`;// 编译着色器并链接程序
function compileShader(type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {console.error('Shader compilation failed', gl.getShaderInfoLog(shader));}return shader;
}const vertexShader = compileShader(gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = compileShader(gl.FRAGMENT_SHADER, fragmentShaderSource);const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {console.error('Program linking failed', gl.getProgramInfoLog(shaderProgram));
}gl.useProgram(shaderProgram);// 获取属性和统一变量的位置
const positionLocation = gl.getAttribLocation(shaderProgram, 'a_position');
const texCoordLocation = gl.getAttribLocation(shaderProgram, 'a_texCoord');
const textureLocation = gl.getUniformLocation(shaderProgram, 'u_texture');// 绑定顶点数据
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);// 绑定纹理坐标数据
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(texCoordLocation);// 创建纹理对象并绑定
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);// 使用 texImage2D 上传图片
const image = new Image();
image.onload = () => {// 图片加载完成后将图像上传为纹理gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);gl.generateMipmap(gl.TEXTURE_2D);  // 生成mipmap纹理// 绘制gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);gl.enable(gl.DEPTH_TEST);gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
};
image.src = 'your-texture-image.jpg';  // 这里替换为你的纹理图像路径

3. 代码解析

  • gl.createTexture:创建一个纹理对象。

  • gl.bindTexture(gl.TEXTURE_2D, texture):将创建的纹理对象绑定为当前活动的纹理。

  • gl.texImage2D:将图片上传为纹理,image.onload 确保在图片加载完成后才会上传到 WebGL 中。这里将图片的像素数据传给 WebGL。

    • 第一个参数 gl.TEXTURE_2D:指定纹理目标为 2D 纹理。
    • 第二个参数 0:纹理的细节层级,通常设置为 0 表示基础纹理。
    • 第三个参数 gl.RGB:纹理的内部格式(存储格式)。
    • 第四个参数 gl.RGB:纹理的像素格式(图像格式)。
    • 第五个参数 gl.UNSIGNED_BYTE:指定数据类型,这里是 8 位无符号整数。
    • 第六个参数 image:图片元素,作为纹理数据源。
  • gl.generateMipmap:生成多级渐远纹理,提升纹理渲染性能并防止远离摄像机时纹理过于模糊。

  • 纹理渲染:在片元着色器中,texture2D 函数根据纹理坐标从上传的纹理中采样像素并进行渲染。

4. 总结

gl.texImage2D 是 WebGL 中上传纹理的核心方法,它将图像数据或像素数据上传为纹理对象,允许在渲染时将纹理映射到几何体表面。理解如何使用 gl.texImage2D 并正确处理纹理数据,是开发 WebGL 应用的基础之一。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/4061.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hadoop•用Web UI查看Hadoop状态词频统计

听说这里是目录哦 通过Web UI查看Hadoop运行状态&#x1f407;一、关闭防火墙二、在物理计算机添加集群的IP映射三、启动集群四、进入HDFS的Web UI 词频统计&#x1f9a9;1、准备文本数据2、在HDFS创建目录3、上传文件4、查看文件是否上传成功5、运行MapReduce程序6、查看MapRe…

国产编辑器EverEdit -重复行

1 重复行 1.1 应用场景 在代码或文本编辑过程中&#xff0c; 经常需要快速复制当前行&#xff0c;比如&#xff0c;给对象的多个属性进行赋值。传统的做法是&#xff1a;选中行-> 复制-> 插入新行-> 粘贴&#xff0c;该操作有4个步骤&#xff0c;非常繁琐。 那有没…

LabVIEW桥接传感器数据采集与校准程序

该程序设计用于采集来自桥接传感器的数据&#xff0c;执行必要的设置&#xff08;如桥接配置、信号采集参数、时间与触发设置&#xff09;&#xff0c;并进行适当的标定和偏移校正&#xff0c;最终通过图表呈现采集到的数据信息。程序包括多个模块&#xff0c;用于配置通道、触…

redis-排查命中率降低问题

1.命中率降低带来的问题 高并发系统&#xff0c;当命中率低于平常的的运行情况&#xff0c;或者低于70%时&#xff0c;会产生2个影响。 有大量的请求需要查DB&#xff0c;加大DB的压力&#xff1b;影响redis自身的性能 不同的业务场景&#xff0c;阈值不一样&#xff0c;一般…

edge浏览器恢复旧版滚动条

1、地址栏输入edge://flags 2、搜索Fluent scrollbars.&#xff0c;选择disabled&#xff0c;重启即可

【算法】算法基础课模板大全——第一篇

由于本文章内容太长&#xff0c;导致文章不能以一篇博客形式发布出来&#xff0c;所以我将分为两篇博客进行发布。 【算法】算法基础课模板大全——第一篇 【算法】算法基础课模板大全——第二篇 此笔记适用于AcWing网站的算法基础课&#xff0c;所有的资源链接、代码模板全部来…

Top期刊算法!RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测

Top期刊算法&#xff01;RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测 目录 Top期刊算法&#xff01;RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于RIME-CNN-BiLSTM-Attention、CNN-BiLSTM-Attention、R…

日志收集Day002

1.ES的常见术语 索引(index)&#xff1a; 用户写入ES集群的逻辑单元。 分片(shard): 一个索引最少一个分片。 将索引的数据分布式的存储在ES集群。 副本(replica): 一个分片可以有0个或多个副本。 为同一个分片数据提供数据冗余。 文档(docment): …

微服务入门:从零开始构建你的微服务架构

微服务是一种软件开发架构风格&#xff0c;它把一个大的应用程序拆分成一系列小的服务。这些小的服务各自独立运行在自己的进程中&#xff0c;并通过轻量级的通信机制&#xff08;比如HTTP API&#xff09;进行交互。要通俗地理解微服务&#xff0c;可以从以下几个方面入手&…

Ubuntu 22.04 TLS 忘记root密码,重启修改的解决办法

1.想办法进入这个界面&#xff0c;我这里是BIOS引导的是按Esc按一下就行&#xff0c;UEFI的貌似是按Shift不得而知&#xff0c;没操作过。下移到Advanced options for Ubuntu&#xff0c;按enter 2.根据使用的内核版本&#xff0c;选择带「recovery mode」字样的内核版本&#…

电子电气架构 --- ECU故障诊断指南

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

Linux(DISK:raid5、LVM逻辑卷)

题目: DISK 添加4块大小均为10G的虚拟磁盘,配置raid-5磁盘。创建LVM命名为/dev/vg01/lv01,大小为20G,格式化为ext4,挂在到本地目录/webdata,在分区内建立测试空文件disk.txt。[root@storagesrv ~]# yum install mdadm -y [root@storagesrv ~]# mdadm -C -n 3 -l 5 -a y…

差异基因富集分析(R语言——GOKEGGGSEA)

接着上次的内容&#xff0c;上篇内容给大家分享了基因表达量怎么做分组差异分析&#xff0c;从而获得差异基因集&#xff0c;想了解的可以去看一下&#xff0c;这篇主要给大家分享一下得到显著差异基因集后怎么做一下通路富集。 1.准备差异基因集 我就直接把上次分享的拿到这…

软件测试——期末复习

文章目录 前言软件缺陷软件开发的过程软件测试黑盒测试等价类划分判定表法因果图法边界值分析法 白盒测试配置测试兼容性测试外国语言测试易用性测试自动化测试和测试工具缺陷轰炸和beta测试 前言 由于本人拖延症严重而且成绩较差&#xff0c;所以才在考试结束将近一个星期后&…

嵌入式硬件篇---基本组合逻辑电路

文章目录 前言基本逻辑门电路1.与门&#xff08;AND Gate&#xff09;2.或门&#xff08;OR Gate&#xff09;3.非门&#xff08;NOT Gate&#xff09;4.与非门&#xff08;NAND Gate&#xff09;5.或非门&#xff08;NOR Gate&#xff09;6.异或门&#xff08;XOR Gate&#x…

数据结构漫游记:动态实现栈(stack)

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

微信小程序-base64加解密

思路&#xff1a;先创建一个base64.js的文件&#xff0c;这个文件可以作为专门加解密的文件模块&#xff0c;需要时就引用&#xff1b;创建好后&#xff0c;引用base64.js里的加解密函数。 注意&#xff1a;引用模块一定要引用正确的路径&#xff0c;否则会报错。 base64.js:…

RabbitMQ--延迟队列

&#xff08;一&#xff09;延迟队列 1.概念 延迟队列是一种特殊的队列&#xff0c;消息被发送后&#xff0c;消费者并不会立刻拿到消息&#xff0c;而是等待一段时间后&#xff0c;消费者才可以从这个队列中拿到消息进行消费 2.应用场景 延迟队列的应用场景很多&#xff0c;…

口令攻击和钓鱼攻击

口令攻击和钓鱼攻击 1、实验说明 口令攻击和钓鱼攻击是生活中两种较为常见的攻击方式&#xff0c; 通过对攻击过程的复现&#xff0c; 能够让学生对其有直观的认识&#xff0c; 进而思考相应的防范措施。 2、实验目的 &#xff08;1 &#xff09;能够了解实验规范和实验所需…

考前64天 学习笔记 - 形成“习惯体系”进行最小启动

从2025年1月18日到3月22日还剩64天 一、备考心态 这几天摆烂&#xff0c;并没有怎么学&#xff0c;败在了游戏和短视频上。 每分每秒都在抵御其他诱惑 科学表明&#xff1a;人在做自己不喜欢的事情&#xff0c;意志力最多能挺25分钟 如何稳定自己的心态&#xff0c;答案就在…