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/7/25 6:28:52 阅读更多 →
AI图书出版系统实战:从架构设计到生产部署完整指南

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

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

2026/7/25 6:28:52 阅读更多 →
智能视频创作技术:从生成式AI到神经渲染的实践

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

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

2026/7/25 6:27:52 阅读更多 →

最新新闻

构建自进化AI知识库与智能编程助手系统

构建自进化AI知识库与智能编程助手系统

1. 项目概述这个项目本质上是在探索如何构建一个能够持续自我进化的知识管理系统,并将其与AI编程助手深度整合。我在实际开发中发现,传统知识库最大的痛点在于内容容易过时,而人工维护成本又太高。通过引入自动化更新机制和智能编码代理&…

2026/7/25 6:42:56 阅读更多 →
UE4手游CPU性能优化实战:Unreal Insights与Simpleperf组合分析指南

UE4手游CPU性能优化实战:Unreal Insights与Simpleperf组合分析指南

1. 项目概述:为什么手游CPU性能优化是场硬仗做手游开发,尤其是用UE4这种重型引擎,最怕的就是玩家在评论区刷“卡成PPT”。CPU性能瓶颈往往是导致这种体验灾难的元凶,但定位它却像大海捞针。引擎逻辑、动画蓝图、物理计算、UI线程&…

2026/7/25 6:42:56 阅读更多 →
程序员必备:大模型技能入门与实战指南

程序员必备:大模型技能入门与实战指南

1. 为什么每个程序员都需要掌握大模型技能? 十年前我刚入行时,程序员的核心竞争力是算法和数据结构。五年前,云计算和微服务架构成为必备技能。而现在,大模型正在重塑整个技术栈的生态位。作为经历过三次技术浪潮的老兵&#xff0…

2026/7/25 6:42:56 阅读更多 →
基于spaCy的中文命名实体识别实战:从新闻文本中提取人物、地点与事件

基于spaCy的中文命名实体识别实战:从新闻文本中提取人物、地点与事件

在实际技术项目中,我们经常需要处理各种非结构化或半结构化的数据,例如来自社交媒体、新闻、活动报道的文本。这些数据通常包含丰富的实体信息,如人名、地点、事件、作品等。如何从一篇简短的新闻报道中,自动、准确地提取出这些关…

2026/7/25 6:42:56 阅读更多 →
小白程序员必看!Agent强化学习技能进化新思路:收藏这技能,一起变强!

小白程序员必看!Agent强化学习技能进化新思路:收藏这技能,一起变强!

文章介绍了AWS AI Labs提出的RESKILL技术,该技术通过将技能生成融入GRPO训练循环,使Agent在训练中自我学习和进化技能,解决了传统离线生成技能与Agent训练脱节导致的偏差问题。RESKILL通过让Agent在训练中自我诊断、评测和决定技能使用&#…

2026/7/25 6:42:56 阅读更多 →
Godot 4 ShaderMaterial实现动态交互水波纹:从原理到工程实践

Godot 4 ShaderMaterial实现动态交互水波纹:从原理到工程实践

1. 项目概述:从静态到动态的交互式水面在游戏和交互式应用中,水面的表现力直接关系到场景的沉浸感。一个静态的、毫无波澜的水面,即便贴图再精美,也显得死气沉沉。而一个能够响应角色脚步、雨滴、甚至玩家点击,泛起层层…

2026/7/25 6:41:56 阅读更多 →

日新闻

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您的…

2026/7/25 0:00:35 阅读更多 →
C++ string类模拟实现:从深拷贝到内存管理的完整指南

C++ string类模拟实现:从深拷贝到内存管理的完整指南

1. 项目概述:为什么我们要“手撕”string类?在C的学习道路上,尤其是从C语言过渡到C的“初阶”阶段,string类绝对是一个绕不开的核心。标准库里的std::string用起来太方便了,、find、substr,几个操作符和函数…

2026/7/25 0:00:35 阅读更多 →
三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

1. 先搞清楚“三角洲寻宝鼠”到底是什么工具从名称来看,“三角洲寻宝鼠”更像是一个资源查找或文件检索类工具,而不是游戏或娱乐软件。这类工具的核心价值在于帮助用户快速定位特定资源,比如文档、图片、压缩包或特定格式的文件。如果你经常需…

2026/7/25 0:00:35 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/25 5:08:22 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/25 5:13:53 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻