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

(十四)WebGL纹理坐标初识

纹理坐标是 WebGL 中将 2D 图像(纹理)应用到 3D 物体表面的重要概念。在 WebGL 中,纹理坐标通常使用一个二维坐标系,称为 uv 坐标,它们决定了纹理图像如何映射到几何体上。理解纹理坐标的核心就是明白它们如何将二维纹理贴图应用到三维物体的表面。

文章目录

      • 纹理坐标的基本概念
      • 纹理坐标的作用
      • 代码示例:立方体纹理映射
        • 1. HTML 文件
        • 2. JavaScript 部分:WebGL 纹理坐标示例
      • 3. 代码解析
      • 4. 纹理坐标的作用

纹理坐标的基本概念

纹理坐标(u, v)是一个标准的二维坐标系统,用于描述纹理图像中每个像素(即纹理元素,Texel)的位置。uv 是纹理的归一化坐标,即它们的值通常位于 [0, 1] 区间:

  • u坐标:控制纹理图像的水平位置,u = 0 是纹理的最左侧,u = 1 是纹理的最右侧。
  • v坐标:控制纹理图像的垂直位置,v = 0 是纹理的底部,v = 1 是纹理的顶部。

例如,在纹理坐标 (u=0.5, v=0.5) 处表示纹理图像的中心。
在这里插入图片描述

纹理坐标的作用

在 WebGL 中,每个顶点都有一个对应的纹理坐标。顶点着色器负责将这些坐标传递到片元着色器,片元着色器利用纹理坐标来从纹理图像中获取相应的像素颜色,从而将图像“映射”到几何体表面。

代码示例:立方体纹理映射

下面是一个带有纹理坐标的立方体的简单例子,展示了如何将纹理图像映射到立方体的每个面。

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 纹理坐标示例</title>
</head>
<body><canvas id="webgl-canvas" width="500" height="500"></canvas><script src="main.js"></script>
</body>
</html>
2. JavaScript 部分:WebGL 纹理坐标示例
// 获取 WebGL 上下文
const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl');// 立方体顶点坐标 (x, y, z)
const vertices = new Float32Array([-0.5, -0.5, -0.5, // 前面0.5, -0.5, -0.5,0.5,  0.5, -0.5,-0.5,  0.5, -0.5,-0.5, -0.5,  0.5, // 后面0.5, -0.5,  0.5,0.5,  0.5,  0.5,-0.5,  0.5,  0.5,
]);// 立方体的纹理坐标 (u, v)
// 每个顶点的纹理坐标。注意 u/v 范围是 [0, 1]
const texCoords = new Float32Array([0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // 前面0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // 后面0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // 左面0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // 右面0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // 上面0.0, 0.0,  1.0, 0.0,  1.0, 1.0,  0.0, 1.0,  // 下面
]);// 立方体的索引,用于绘制每个面
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);
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);
};
image.src = 'your-texture-image.jpg';  // 这里使用你自己的纹理图片路径// 清除画布并绘制
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);

3. 代码解析

  • 纹理坐标(texCoords):每个顶点都有对应的纹理坐标,texCoords

数组定义了每个面四个顶点的纹理坐标。在这个例子中,(u, v) 范围是 [0, 1],代表纹理图像的左下角 (0, 0) 到右上角 (1, 1)。

  • 着色器

    • 顶点着色器:将顶点位置和纹理坐标传递到片元着色器。
    • 片元着色器:根据纹理坐标,从纹理图像中采样颜色。
  • 纹理加载:在 image.onload 中加载图片,并将其绑定为 WebGL 的纹理。在加载完成后,WebGL 会自动生成多级渐远纹理(mipmap),提高纹理渲染的效率和质量。

  • 绘制:使用 gl.drawElements 绘制立方体的每个面。每个面由两个三角形组成,纹理坐标确保了纹理图像正确地映射到每个面。

4. 纹理坐标的作用

纹理坐标使得 WebGL 能够将一个 2D 图像(纹理)正确地映射到 3D 对象的表面。当你需要将图片或其他 2D 图像添加到你的 3D 模型时,理解和使用纹理坐标是非常重要的。纹理坐标的映射关系决定了纹理如何在模型表面分布,例如,是否是平铺、是否有旋转、是否有缩放等。

http://www.lryc.cn/news/523500.html

相关文章:

  • 【机器学习】制造业转型:机器学习如何推动工业 4.0 的深度发展
  • Nginx安装配置Mac使用Nginx访问前端打包项目
  • 国自然面上项目|基于组合机器学习算法的病理性近视眼底多模态影像资料自动化定量分析研究|基金申请·25-01-18
  • 03_UI自适应
  • Python在DevOps中的应用:自动化CI/CD管道的实现
  • API接口技术推动电商数据处理的自动化
  • Nginx反向代理架构介绍
  • .Net Core微服务入门系列(一)——项目搭建
  • WPF 实现可视化操作数据库的程序全解析
  • python mysql库的三个库mysqlclient mysql-connector-python pymysql如何选择,他们之间的区别
  • 如何将数据库字符集改为中文,让今后所有的数据库都支持中文
  • Low-Level 大一统:如何使用Diffusion Models完成视频超分、去雨、去雾、降噪等所有Low-Level 任务?
  • EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成
  • Docker Compose的使用
  • [STM32 HAL库]串口空闲中断+DMA接收不定长数据
  • 三、华为交换机 Hybrid
  • 如何通过 Apache Airflow 将数据导入 Elasticsearch
  • Android Studio:Linux环境下安装与配置
  • token是用来鉴权的,那session是用来干什么的?
  • 基于 WEB 开发的二手车辆销售管理系统设计与实现
  • wordpress的火车头商品发布接口
  • 浙江安吉成新照明电器:Acrel-1000DP 分布式光伏监控系统应用探索
  • 总结3..
  • 信息奥赛一本通 1168:大整数加法
  • 3.3 OpenAI GPT-4, GPT-3.5, GPT-3 模型调用:开发者指南
  • 横盘出击的三种经典走势形态,买点以及需要注意的问题技术详解
  • 处理没有提示的字符串、计算相隔天数应用题
  • 【LeetCode】力扣刷题热题100道(31-35题)附源码 搜索二维矩阵 岛屿数量 腐烂的橙子 课程表 实现 Trie (前缀树)(C++)
  • react使用react-redux状态管理
  • 04_角色创建窗口