WebGL 纹理完整教程:原理、场景 + 可直接运行 Demo一、WebGL 纹理核心概念1. 纹理是什么纹理就是一张图片,把像素数据贴到几何体表面(类似贴纸),WebGL 通过纹理单元、纹理对
WebGL 纹理完整教程原理、场景 可直接运行 Demo一、WebGL 纹理核心概念1. 纹理是什么纹理就是一张图片把像素数据贴到几何体表面类似贴纸WebGL 通过纹理单元、纹理对象、采样器、UV 坐标配合使用。 核心四要素纹理对象 (Texture)存储图片像素缓存纹理单元 (Texture Unit)GPU 并行纹理槽位默认至少 16 个gl.TEXTURE0 ~ gl.TEXTURE15UV 坐标贴图坐标范围[0,1](0,0) 图片左上角(1,1) 右下角纹理参数缩放过滤、环绕模式2. 关键纹理参数环绕模式图片超出 UV 0~1 时gl.REPEAT重复平铺默认gl.CLAMP_TO_EDGE拉伸边缘像素gl.MIRRORED_REPEAT镜像重复过滤模式缩放贴图时放大TEXTURE_MAG_FILTERgl.LINEAR线性模糊平滑gl.NEAREST像素块马赛克缩小TEXTURE_MIN_FILTER多配合 Mipmapgl.LINEAR_MIPMAP_LINEAR三线性画质最好gl.NEAREST硬像素二、纹理常见应用场景2D/3D 模型贴图人物皮肤、墙体、地板、道具外观UI 界面游戏按钮、图标、背景面板帧缓冲 FBO 渲染纹理离屏渲染、镜面反射、阴影贴图、后期滤镜模糊 / 调色数据纹理把数组数据存纹理GPU 并行计算GPGPU视频纹理播放视频贴到模型播放器、虚拟大屏文字纹理字体图集贴图渲染文字环境贴图天空盒、反射球环境光三、完整可运行 Demo贴图矩形 本地图片纹理功能绘制一个带图片纹理的全屏矩形包含完整纹理创建、图片异步加载、着色器 UV 采样逻辑 复制全部代码保存为.html直接浏览器打开即可。html预览!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleWebGL Texture Demo/title style canvas { border: 1px solid #000; } /style /head body canvas idwebglCanvas width600 height400/canvas script // 1. 获取Canvas与WebGL上下文 const canvas document.getElementById(webglCanvas); const gl canvas.getContext(webgl) || canvas.getContext(experimental-webgl); if (!gl) alert(浏览器不支持WebGL); // 着色器代码 // 顶点着色器传递顶点坐标 UV贴图坐标 const vertexShaderSource attribute vec2 a_Position; attribute vec2 a_Uv; varying vec2 v_Uv; void main() { gl_Position vec4(a_Position, 0.0, 1.0); v_Uv a_Uv; } ; // 片元着色器纹理采样sampler2D读取纹理 const fragmentShaderSource precision mediump float; uniform sampler2D u_Texture; varying vec2 v_Uv; void main() { // 根据UV从纹理采样像素颜色 gl_FragColor texture2D(u_Texture, v_Uv); } ; // 工具函数编译着色器、链接程序 function createShader(gl, type, source) { const shader gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error(着色器编译失败, gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } function createProgram(gl, vsSource, fsSource) { const vs createShader(gl, gl.VERTEX_SHADER, vsSource); const fs createShader(gl, gl.FRAGMENT_SHADER, fsSource); const program gl.createProgram(); gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error(程序链接失败, gl.getProgramInfoLog(program)); return null; } gl.useProgram(program); return program; } // 初始化着色器程序 const program createProgram(gl, vertexShaderSource, fragmentShaderSource); // 顶点数据矩形 UV坐标 // 格式[x,y, u,v] 四个顶点两个三角组成矩形 const vertices new Float32Array([ -1.0, 1.0, 0.0, 0.0, // 左上 -1.0, -1.0, 0.0, 1.0, // 左下 1.0, 1.0, 1.0, 0.0, // 右上 1.0, -1.0, 1.0, 1.0 // 右下 ]); const buffer gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // 绑定顶点属性 const a_Position gl.getAttribLocation(program, a_Position); const a_Uv gl.getAttribLocation(program, a_Uv); const stride 4 * Float32Array.BYTES_PER_ELEMENT; // 一组4个浮点数 // 位置每组前2个 gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, stride, 0); gl.enableVertexAttribArray(a_Position); // UV每组后2个偏移2个浮点数 gl.vertexAttribPointer(a_Uv, 2, gl.FLOAT, false, stride, 2 * Float32Array.BYTES_PER_ELEMENT); gl.enableVertexAttribArray(a_Uv); // 创建纹理对象核心逻辑 function createTexture(gl) { const texture gl.createTexture(); // 绑定到当前激活纹理单元 TEXTURE0 gl.bindTexture(gl.TEXTURE_2D, texture); // 设置纹理环绕模式 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); // 临时填充1x1白色像素避免图片未加载时黑屏报错 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255,255,255,255])); return texture; } // 加载图片到纹理 function loadTexture(gl, texture, imgUrl) { const img new Image(); img.crossOrigin anonymous; // 解决跨域图片报错 img.onload () { gl.bindTexture(gl.TEXTURE_2D, texture); // 上传图片像素到GPU纹理 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); render(); // 图片加载完成重绘 }; img.src imgUrl; } // 渲染函数 function render() { gl.clearColor(0.2, 0.2, 0.2, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); // 激活0号纹理单元 gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture); // 把采样器u_Texture绑定到0号纹理单元 gl.uniform1i(gl.getUniformLocation(program, u_Texture), 0); // 绘制两个三角形共4顶点 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } // 启动流程 const texture createTexture(gl); // 替换成你自己的图片链接本地图片直接放同目录 loadTexture(gl, texture, https://picsum.photos/id/237/400/300); render(); /script /body /html四、关键 API 分步解析1. 创建纹理js运行const texture gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); // 绑定2D纹理目标2. 设置纹理参数必写否则缩放会黑块js运行// S水平方向T垂直方向环绕 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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);3. 上传图片数据到 GPUjs运行gl.texImage2D( gl.TEXTURE_2D, 0, // mip层级 gl.RGBA, // GPU内部存储格式 gl.RGBA, // 图片像素格式 gl.UNSIGNED_BYTE, // 像素数据类型 img // Image/Video/Canvas数据源 );4. 激活纹理单元 传入着色器js运行// 激活第0个纹理槽 gl.activeTexture(gl.TEXTURE0); // 绑定纹理对象到当前激活单元 gl.bindTexture(gl.TEXTURE_2D, texture); // 片元着色器sampler2D变量 纹理单元编号0 gl.uniform1i(u_TextureLoc, 0);5. 着色器采样glsluniform sampler2D u_Texture; // 纹理采样器 varying vec2 v_Uv; // 插值UV坐标 // 采样获取像素颜色 vec4 color texture2D(u_Texture, v_Uv);五、拓展常用纹理拓展用法1. Mipmap 优化远距离贴图图片尺寸是 2 的幂512/1024/2048时开启js运行gl.generateMipmap(gl.TEXTURE_2D); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);2. 多纹理叠加双纹理单元js运行// 纹理1绑定TEXTURE0 gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, tex1); gl.uniform1i(texLoc1, 0); // 纹理2绑定TEXTURE1 gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, tex2); gl.uniform1i(texLoc2, 1);片元着色器混合两张贴图glslvec4 col1 texture2D(u_Tex1, v_Uv); vec4 col2 texture2D(u_Tex2, v_Uv); gl_FragColor mix(col1, col2, 0.5);3. Video 视频纹理直接传入video标签到texImage2D渲染循环每帧更新纹理。4. FBO 渲染纹理离屏渲染创建纹理绑定帧缓冲把 3D 场景渲染到纹理再贴到模型实现镜面、特效。六、常见踩坑点图片跨域黑屏设置img.crossOrigin anonymous图片服务器允许跨域UV 超出范围拉伸异常修改TEXTURE_WRAP_S/T为CLAMP_TO_EDGE缩小贴图出现黑块没设置TEXTURE_MIN_FILTER过滤参数Mipmap 报错图片宽高必须是 2 的整数次幂图片加载前黑屏先填充 1x1 临时像素纹理

相关新闻

UE5模板序列:跨关卡复用动画与逻辑的高效解决方案

UE5模板序列:跨关卡复用动画与逻辑的高效解决方案

1. 项目概述:为什么跨关卡复用模板序列是UE开发者的必修课在虚幻引擎(UE5/UE4)的项目开发中,尤其是涉及到大型开放世界、多章节叙事或者重复性玩法机制时,我们经常会遇到一个头疼的问题:辛辛苦苦在某个关卡…

2026/9/29 14:15:22 阅读更多 →
AI图书出版系统实战:从架构设计到生产部署完整指南

AI图书出版系统实战:从架构设计到生产部署完整指南

如果你正在探索如何将AI技术真正落地到内容创作领域,特别是想了解从零搭建一个AI驱动的图书出版系统会遇到哪些实际挑战,那么这篇文章正是为你准备的。过去一年,AI内容生成技术看似成熟,但真正将其应用到严肃出版领域时&#xff0…

2026/10/6 20:22:55 阅读更多 →
智能视频创作技术:从生成式AI到神经渲染的实践

智能视频创作技术:从生成式AI到神经渲染的实践

1. 智能视频创作的技术演进脉络2026年视频创作领域正在经历一场由底层技术驱动的范式转移。过去三年间,三个关键技术突破彻底改变了行业格局:首先是神经渲染技术从实验室走向工业化,使得实时生成影视级画质成为可能;其次是多模态大…

2026/10/4 3:18:11 阅读更多 →

最新新闻

AI 资讯日报 | 2026年10月5日:DeepSeek将中美顶尖模型差距缩至3%,Gemini 4 Argon百万Token输出,阿里确认Qwen 4训练中,智能体安全治理升温

AI 资讯日报 | 2026年10月5日:DeepSeek将中美顶尖模型差距缩至3%,Gemini 4 Argon百万Token输出,阿里确认Qwen 4训练中,智能体安全治理升温

一、模型与产品1. 谷歌发布Gemini 4 Argon旗舰模型:百万Token输出,主打长周期复杂工作流谷歌正式推出新一代旗舰大模型Gemini 4 Argon,单轮最大输出Token上限由上代6.4万提升至100万,可独立完成跨数万行代码迁移等长链路工程任务&…

2026/10/7 14:07:02 阅读更多 →
多智能体系统设计:协调器、专门化 Agent 与通信机制

多智能体系统设计:协调器、专门化 Agent 与通信机制

多智能体系统设计:协调器、专门化 Agent 与通信机制 以前 AI 的主流范式是单个模型与单个用户交互:系统接收指令、处理信息、输出结果。这套架构推动了巨大进步,但也暴露了一个随着任务复杂化而日益明显的问题——现实世界的问题解决很少靠单…

2026/10/7 14:07:02 阅读更多 →
全球人工智能治理对话日内瓦开幕:联合国框架下的 AI 治理新纪元

全球人工智能治理对话日内瓦开幕:联合国框架下的 AI 治理新纪元

全球人工智能治理对话日内瓦开幕:联合国框架下的 AI 治理新纪元 2026 年 7 月 6 日,首届全球人工智能治理对话在瑞士日内瓦正式开幕。这是联合国大会根据 2025 年决议设立的首个全球性 AI 治理平台,约 1500 名代表出席。 一、历史性时刻 联合…

2026/10/7 14:07:02 阅读更多 →
合规是底线:从接口服务风险案例看企业选 API 平台的三条红线

合规是底线:从接口服务风险案例看企业选 API 平台的三条红线

一位 API 接口服务经营者发帖披露,自己因经营相关业务被刑事立案、羁押三十七天后取保候审。这个案例给行业敲响警钟:API 接入服务的"中间商"模式,两头都要扛合规风险。对企业用户来说,选平台就是选合规——三条红线必须…

2026/10/7 14:07:02 阅读更多 →
把值写进类型:C++ 模板进阶的非类型参数、特化与分离编译

把值写进类型:C++ 模板进阶的非类型参数、特化与分离编译

&#x1f3c6;浮世尘弦&#xff1a;个人主页 ⭐个人专栏&#xff1a;《C语言》、《数据结构与算法》、《C》 &#x1f48e;&#xff1a;非淡薄无以明志&#xff0c;非宁静无以致远 前言 前面我们学习了使用类型模板参数template<class T>编写与类型无关的通用代码&#x…

2026/10/7 14:07:01 阅读更多 →
影刀RPA新手教程:微博热搜与话题数据定时采集入门

影刀RPA新手教程:微博热搜与话题数据定时采集入门

影刀RPA新手教程&#xff1a;微博热搜与话题数据定时采集入门 想每天自动记录微博热搜榜和话题阅读量&#xff0c;人工盯又累又容易忘&#xff0c;这就是很多人学影刀RPA后想做的第一个定时采集项目。但新手在定时任务上摔的跟头&#xff0c;比在采集指令上多得多&#xff1a;任…

2026/10/7 14:06:01 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:15:40 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 5:29:09 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 8:21:32 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 11:43:46 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →