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

news2025/1/20 13:04:21

在 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 face
   0.5, -0.5, -0.5,
   0.5,  0.5, -0.5,
  -0.5,  0.5, -0.5,
  -0.5, -0.5,  0.5, // Back face
   0.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 face
  0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Back face
  0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Left face
  0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Right face
  0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // Top face
  0.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.coloradmin.cn/o/2279366.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

51c自动驾驶~合集47

我自己的原文哦~ https://blog.51cto.com/whaosoft/13083194 #DreamDrive 性能爆拉30%&#xff01;英伟达&#xff1a;时空一致下的生成重建大一统新方案~ 从自车的驾驶轨迹中生成真实的视觉图像是实现自动驾驶模型可扩展训练的关键一步。基于重建的方法从log中生成3D场景…

AI 编程工具—Cursor AI 对话模式详解 内嵌对话模式

AI 编程工具—Cursor AI 对话模式详解 内嵌对话模式 前面我们已经学习了Cursor 的两种工作模式,也就是Chat、Composer 更多细节可以看之前的文章 Cursor 对话模式详解 Chat、Composer 与 Normal/Agent 模式 这一节我们按一下最后一种模式,也就是内嵌对话模式 内嵌对话模式…

国产编辑器EverEdit - 合并行

1 合并行 1.1 应用场景 在编写代码或其他场景下&#xff0c;有时需要把多行的内容缩减成一行&#xff0c;或者纯粹减少行数进行合并&#xff0c;比如&#xff1a;下面的字典的定义&#xff0c;每个元素占了一行&#xff0c;有点浪费&#xff0c;现在需要把它们缩减行数。 typ…

postman请求参数化

一、使用环境变量(Environment Variables)进行参数化 1、在请求中使用环境变量 在请求的url、请求头(Headers)、请求体(Body)等部分都可以使用环境变量。 URL 部分示例 点击 Postman 界面右上角的 “眼睛” 图标(Environment Quick Look)打开环境管理窗口单击Edit将变…

[JavaWeb]央视新闻排版

私用学习笔记 一.设置颜色 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>【新思想引领新征程…

Transform论文阅读之Attention Is All You Need(一)and Vit

摘要&#xff1a; 这篇论文的摘要介绍了一种名为Transformer的新型神经网络架构&#xff0c;该架构完全基于自注意力机制&#xff0c;用于解决序列转换任务。Transformer在机器翻译任务中取得了领先的性能&#xff0c;并且相比基于循环或卷积神经网络的传统架构&#xff0c;Tr…

【神经网络基础】

目录 一、神经网络的构成 1.1什么是神经网络&#xff1f; 1.2 激活函数 1.2.1 Sigmoid 1.2.2 Tanh 1.2.3 ReLU 1.2.4 softmax 1.2.5 其他激活函数 1.2.6 选择激活函数 1.3 参数初始化 1.4 模型构建 二、损失函数 2.1 分类问题 2.1.1多分类&#xff08;多分类交叉…

【Linux】Linux入门(2)常见指令

目录 Linux下的文件ls 指令 --- 展示目录pwd指令 --- 显示当前目录cd 指令 --- 改变工作目录touch指令 --- 创建普通文件stat指令 --- 查看文件属性mkdir指令 --- 创建目录rmdir指令 --- 删除目录rm指令 --- 同时删除文件或目录man指令 --- 访问帮助手册cp指令 复制文件或目录m…

202509读书笔记|《飞花令·山》——两岸猿声啼不住,轻舟已过万重山

202509读书笔记|《飞花令山》——两岸猿声啼不住&#xff0c;轻舟已过万重山 《飞花令山》素心落雪编著&#xff0c;飞花令得名于唐代诗人韩翃《寒食》中的名句“春城无处不飞花”&#xff0c;类似于行酒令&#xff0c;是文人们的一种雅致的娱乐活动。 一直都比较喜欢看诗词&a…

GRGDSPC;H-Gly-Arg-Gly-Asp-Ser-Pro-Cys-OH;是一种末端巯基化的细胞粘附肽;91575-26-7

【GRGDSPC 简介】 GRGDSPC 是一种含 7 个氨基酸的多肽&#xff0c;且末端巯基化的细胞粘附肽。化学结构 是H-GLY-ARG-GLY-ASP-SER-PRO-CYS-OH&#xff0c;氨基酸序列为甘氨酸-精氨酸-甘氨酸-天冬氨酸-丝氨酸-脯氨酸-半胱氨酸&#xff0c;C端为羟基&#xff0c;是一种末端巯基化…

抖音ip属地不准是什么原因?可以改吗

在数字化时代&#xff0c;社交媒体平台如抖音已成为人们日常生活的重要组成部分。随着各大平台对用户隐私和数据安全的日益重视&#xff0c;IP属地的显示功能应运而生。然而&#xff0c;不少抖音用户在使用过程中发现&#xff0c;显示的IP属地与实际位置存在偏差&#xff0c;这…

.Net Core微服务入门全纪录(四)——Ocelot-API网关(上)

系列文章目录 1、.Net Core微服务入门系列&#xff08;一&#xff09;——项目搭建 2、.Net Core微服务入门全纪录&#xff08;二&#xff09;——Consul-服务注册与发现&#xff08;上&#xff09; 3、.Net Core微服务入门全纪录&#xff08;三&#xff09;——Consul-服务注…

Zemax 中的二向色分束器和荧光波偏移

二向色分光镜是一种专用光学元件&#xff0c;用于根据光的波长将一束光分成两束独立的光。“二向色”是指该元件根据光的波长选择性地透射或反射光的性质。 在大多数情况下&#xff0c;二向色分束器由一种对不同波长的光具有不同折射率的材料制成。分束器的表面涂有一层薄膜&a…

DevUI 2024 年度运营报告:开源生态的成长足迹与未来蓝图

在当今数字化飞速发展的时代&#xff0c;开源已成为推动技术创新与协作的重要力量。DevUI 作为开源领域的重要一员&#xff0c;其发展历程与成果备受关注。值此之际&#xff0c;GitCode 精心整理了 DevUI 年度运营报告&#xff0c;为您全面呈现 DevUI 社区在过去一年里的开源之…

3 前端(中):JavaScript

文章目录 前言&#xff1a;JavaScript简介一、ECMAscript&#xff08;JavaScript基本语法&#xff09;1 JavaScript与html结合方式&#xff08;快速入门&#xff09;2 基本知识&#xff08;1&#xff09;JavaScript注释&#xff08;和Java注释一样&#xff09;&#xff08;2&am…

rocketmq基本架构

简介 Name server 负责broker注册、心跳&#xff0c;路由等功能&#xff0c;类似Kafka的ZKname server节点之间不互相通信&#xff0c;broker需要和所有name server进行通信。扩容name server需要重启broker&#xff0c;不然broker不会和name server建立连接producer和consum…

ToDesk设置临时密码和安全密码都可以当做连接密码使用

ToDesk 在各领域办公都已经是非常常见了 为了安全 ToDesk 设置了连接密码&#xff0c;想连接 需要输入远程码和连接密码 我们刚打开 系统默认给我们用的是临时密码&#xff0c;安全性确实很强 和定时Tokey一样&#xff0c;固定时间切换。 但是 如果我们要经常连接这个电脑&a…

mysql 系统学习1

Linux C/C 操作MySQL - Henkk - 博客园

事件委托,其他事件,电梯导航,固定导航

事件委托改造 tab 栏切换 tab栏切换&#xff1a;前边的案例是 for 循环遍历每个 li 注册鼠标进入事件&#xff0c;给添加了 active类的 a 删除掉 active类&#xff0c;然后给点击的 a 添加上 active类&#xff08;也就是将已经有的 active 类删除掉&#xff0c;为当前点击到的…

mongoose 支持https踩坑纪实

简述 mongoose是C编写的嵌入式web服务&#xff0c;它能够支持https协议&#xff0c;可以简单的部署&#xff0c;但要做到完美部署&#xff0c;不是那么容易。 部署方法 本人使用的是最新的7.16版&#xff0c;以前版本似乎是要通过修改 头文件中的 MG_ENABLE_SSL 宏定义&…