小白学webgl合集-WebGL中给图片添加背景

一.实现效果

二.逻辑

为了在WebGL中给图片添加背景,主要的逻辑步骤包括初始化WebGL上下文、编写和编译着色器、创建和绑定缓冲区、加载和配置纹理以及绘制场景。以下是代码逻辑的详细说明:

1. 获取WebGL上下文

首先,通过获取<canvas>元素并调用getContext('webgl')方法来初始化WebGL上下文。

const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');

2. 定义顶点着色器和片段着色器

编写顶点着色器(vertex shader)和片段着色器(fragment shader)。顶点着色器负责处理顶点数据,并将纹理坐标传递给片段着色器;片段着色器则使用纹理坐标来获取纹理颜色,并将其绘制到屏幕上。

const vsSource = `attribute vec4 aPosition;attribute vec2 aTexCoord;varying vec2 vTexCoord;void main() {gl_Position = aPosition;vTexCoord = aTexCoord;}
`;const fsSource = `precision mediump float;varying vec2 vTexCoord;uniform sampler2D uSampler;void main() {gl_FragColor = texture2D(uSampler, vTexCoord);}
`;

3. 初始化WebGL着色器程序

编译和链接着色器程序,然后使用该程序。

const program = initShader(gl, vsSource, fsSource);
gl.useProgram(program);

4. 定义顶点数据和索引数据

定义包含顶点位置和纹理坐标的顶点数据,以及用于绘制四边形的索引数据。顶点数据每个顶点包含5个元素(x, y, z, s, t),其中(x, y, z)是顶点位置,(s, t)是纹理坐标。

const vertices = new Float32Array([-1.0,  1.0, 0.0, 0.0, 1.0,-1.0, -1.0, 0.0, 0.0, 0.0,1.0,  1.0, 0.0, 1.0, 1.0,1.0, -1.0, 0.0, 1.0, 0.0,
]);const indices = new Uint16Array([0, 1, 2, 1, 2, 3]);const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

5. 获取着色器中的变量位置并启用顶点属性数组

获取着色器中属性和统一变量的位置,并启用顶点属性数组。

const aPosition = gl.getAttribLocation(program, 'aPosition');
const aTexCoord = gl.getAttribLocation(program, 'aTexCoord');
const uSampler = gl.getUniformLocation(program, 'uSampler');gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 20, 0);
gl.enableVertexAttribArray(aPosition);gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 20, 12);
gl.enableVertexAttribArray(aTexCoord);

6. 创建纹理对象并加载图片

创建纹理对象,加载图片并配置纹理参数。当图片加载完成时,配置纹理并调用绘制函数。

const texture = gl.createTexture();
const image = new Image();
image.src = '../asset/border.png'; // 这里需要指定背景图片的路径
image.onload = () => {gl.bindTexture(gl.TEXTURE_2D, texture);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // 翻转图片Y轴// 配置纹理参数gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);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.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);gl.uniform1i(uSampler, 0);// 绘制场景drawScene();
}

7. 绘制场景

清除颜色缓冲区,激活纹理单元并绑定纹理,绘制包含纹理的四边形。

function drawScene() {gl.clear(gl.COLOR_BUFFER_BIT);gl.activeTexture(gl.TEXTURE0); // 激活纹理单元gl.bindTexture(gl.TEXTURE_2D, texture);// 绘制背景gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}

三.完整代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>WebGL Background Image</title><style>* {margin: 0;padding: 0;}canvas {margin: 50px auto 0;display: block;background: yellow;}</style><script src="test.js"></script></head><body><canvas id="canvas" width="400" height="400"></canvas><script>// 获取WebGL上下文const canvas = document.getElementById('canvas')const gl = canvas.getContext('webgl')if (!gl) {console.error('Unable to initialize WebGL.')} else {// 定义顶点着色器和片段着色器const vsSource = `attribute vec4 aPosition;attribute vec2 aTexCoord;varying vec2 vTexCoord;void main() {gl_Position = aPosition;vTexCoord = aTexCoord;}`const fsSource = `precision mediump float;varying vec2 vTexCoord;uniform sampler2D uSampler;void main() {gl_FragColor = texture2D(uSampler, vTexCoord);}`const program = initShader(gl, vsSource, fsSource)gl.useProgram(program)// 定义顶点数据const vertices = new Float32Array([-1.0, 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 0.0])const indices = new Uint16Array([0, 1, 2, 1, 2, 3])const vertexBuffer = gl.createBuffer()gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)gl.bufferData(gl.ARRAY_BUFFER, vertices, 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 aPosition = gl.getAttribLocation(program, 'aPosition')const aTexCoord = gl.getAttribLocation(program, 'aTexCoord')const uSampler = gl.getUniformLocation(program, 'uSampler')gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 20, 0)gl.enableVertexAttribArray(aPosition)gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 20, 12)gl.enableVertexAttribArray(aTexCoord)// 创建纹理对象const texture = gl.createTexture()const image = new Image()image.src = '../asset/border.png' // 这里需要指定背景图片的路径image.onload = () => {gl.bindTexture(gl.TEXTURE_2D, texture)gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1) // 翻转图片Y轴// 配置纹理参数gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)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.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image)gl.uniform1i(uSampler, 0)// 绘制场景drawScene()}// 绘制场景function drawScene() {gl.clear(gl.COLOR_BUFFER_BIT)gl.activeTexture(gl.TEXTURE0) // 激活纹理单元gl.bindTexture(gl.TEXTURE_2D, texture)// 绘制背景gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)}}</script></body>
</html>

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

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

相关文章

汽车电子工程师入门系列——CAN 规范系列通读

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

互联网大厂核心知识总结PDF资料

我们要敢于追求卓越&#xff0c;也能承认自己平庸&#xff0c;不要低估3&#xff0c;5&#xff0c;10年沉淀的威力 hi 大家好&#xff0c;我是大师兄&#xff0c;大厂工作特点是需要多方面的知识和技能。这种学习和积累一般人需要一段的时间&#xff0c;不太可能一蹴而就&…

Java | Leetcode Java题解之第206题反转链表

题目&#xff1a; 题解&#xff1a; class Solution {public ListNode reverseList(ListNode head) {if (head null || head.next null) {return head;}ListNode newHead reverseList(head.next);head.next.next head;head.next null;return newHead;} }

【Qt】QMessageBox 各种对话框的默认显示效果

1. 函数原型 void about(QWidget *parent, const QString &title, const QString &text)void aboutQt(QWidget *parent, const QString &title QString())QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &…

ONLYOFFICE 8.1版本桌面编辑器测评:重塑办公效率的巅峰之作

在数字化办公日益普及的今天&#xff0c;一款高效、便捷且功能强大的桌面编辑器成为了职场人士不可或缺的工具。ONLYOFFICE 8.1版本桌面编辑器凭借其卓越的性能和丰富的功能&#xff0c;成功吸引了众多用户的目光。今天&#xff0c;我们将对ONLYOFFICE 8.1版本桌面编辑器进行全…

v0.9.6 开源跨平台个人知识管理工具 TidGi-Desktop

在这个信息爆炸的时代&#xff0c;知识管理变得尤为重要。太记(TidGi)&#xff0c;一款基于太微(TiddlyWiki)的知识管理桌面应用&#xff0c;正是为了满足人们对信息整理、知识管理和个人隐私保护的需求而设计的。它不仅能够帮助用户高效地管理和整理信息&#xff0c;还能够自动…

C语言 | Leetcode C语言题解之第205题同构字符串

题目&#xff1a; 题解&#xff1a; struct HashTable {char key;char val;UT_hash_handle hh; };bool isIsomorphic(char* s, char* t) {struct HashTable* s2t NULL;struct HashTable* t2s NULL;int len strlen(s);for (int i 0; i < len; i) {char x s[i], y t[i]…

ElementUI的基本搭建

目录 1&#xff0c;首先在控制终端中输入下面代码&#xff1a;npm i element-ui -S 安装element UI 2&#xff0c;构架登录页面&#xff0c;login.vue​编辑 3&#xff0c;在官网获取对应所需的代码直接复制粘贴到对应位置 4&#xff0c;在继续完善&#xff0c;从官网添加…

“论软件系统架构评估”写作框架,软考高级论文,系统架构设计师论文

论文真题 对于软件系统&#xff0c;尤其是大规模的复杂软件系统来说&#xff0c;软件的系统架构对于确保最终系统的质量具有十分重要的意义&#xff0c;不恰当的系统架构将给项目开发带来高昂的代价和难以避免的灾难。对一个系统架构进行评估&#xff0c;是为了:分析现有架构存…

定时触发-uniapp + uniCloud 订阅消息实战教程(三)

上一节已经对云函数有了一定的了解,但是,为了发送订阅消息,只会云函数还是差了那么一点意思,所以接下来的这一节,将带领大家熟悉一下定时触发。 熟悉定时触发 如果云函数需要定时/定期执行,即定时触发,您可以使用云函数定时触发器。已配置定时触发器的云函数,会在相应…

基于C语言的Jacobi迭代和Gauss-Seidel迭代的方程组求解实现

文章目录 Jacobi迭代方法介绍Gauss-Seidel迭代方法介绍具体代码实现示例题目实现效果 Jacobi迭代方法介绍 Jacobi迭代法是一种简单的迭代求解方法&#xff0c;适用于严格对角占优矩阵。其基本思想是利用当前迭代步的已知解来更新下一个迭代步的解。在C语言实现中&#xff0c;我…

什么是入侵检测系统:综合指南

在网络安全领域&#xff0c;入侵检测系统 (IDS) 长期以来一直是防御威胁的基石。但由于技术在不断发展&#xff0c;绕过它们的技术也在不断发展&#xff0c;因此评估它们是否足以保护系统是至关重要的。 在这篇综合指南中会深入探讨了 IDS 的复杂性&#xff0c;彻底了解了其功…

策略模式(Strategy Pattern)

策略模式 &#xff08;Strategy Pattern&#xff09; 定义 它是将定义的算法家族、分别封装起来&#xff0c;让它们之间可以相互替换&#xff0c;从而让算法的变化不会影响到使用算法的用户。 可以避免多重分支的 if-else、switch语句。 属于行为型模式。 适用场景 如果系…

Redis-在springboot环境下执行lua脚本

文章目录 1、什么lua2、创建SpringBoot工程3、引入相关依赖4、创建LUA脚本5、创建配置类6、创建启动类7、创建测试类 1、什么lua “Lua”的英文全称是“Lightweight Userdata Abstraction Layer”&#xff0c;意思是“轻量级用户数据抽象层”。 2、创建SpringBoot工程 3、引入相…

.net core 的 winform 的 浏览器控件 WebView2

在.NET Core WinForms应用程序中&#xff0c;没有直接的“浏览器控件”&#xff0c;因为WinForms不支持像WebBrowser控件那样的功能。但是&#xff0c;你可以使用WebView2控件&#xff0c;它是一个基于Chromium的浏览器内核&#xff0c;可以在WinForms应用程序中嵌入Web内容。 …

数据结构速成--查找

由于是速成专题&#xff0c;因此内容不会十分全面&#xff0c;只会涵盖考试重点&#xff0c;各学校课程要求不同 &#xff0c;大家可以按照考纲复习&#xff0c;不全面的内容&#xff0c;可以看一下小编主页数据结构初阶的内容&#xff0c;找到对应专题详细学习一下。 目录 …

YonBIP 获取项目代码配置(图文)

项目开发文件在本地环境重新部署后&#xff0c;开发端机器需要重新部署&#xff0c;在此记录一下操作过程。 1. 新建项目目录&#xff0c;在目录下点鼠标右键&#xff0c;选 Git Bash Here 2. 开始下载代码&#xff0c;根据代码量多少&#xff0c;几分钟就能下载完成。 3. 下载…

ONLYOFFICE 8.1版本桌面编辑器深度体验:创新功能与卓越性能的结合

ONLYOFFICE 8.1版本桌面编辑器深度体验&#xff1a;创新功能与卓越性能的结合 随着数字化办公的日益普及&#xff0c;一款高效、功能丰富的办公软件成为了职场人士的必备工具。ONLYOFFICE团队一直致力于为用户提供全面而先进的办公解决方案。最新推出的ONLYOFFICE 8.1版本桌面编…

6月28日PolarDB开源社区长沙站,NineData联合创始人周振兴将带来《数据库DevOps最佳实践》主题分享

6月28日&#xff08;周五&#xff09;&#xff0c;PolarDB 开源社区将来到湖南长沙&#xff0c;与湖南的开发者朋友们一起进行数据库技术交流&#xff01;NineData 联合创始人周振兴受邀参加&#xff0c;并将带来《数据库 DevOps 最佳实践》的主题分享。 本次活动议程&#xff…

2024年机动车签字授权人题库,助你冲刺!绝对不会让你后悔!

61.&#xff08;&#xff09;使汽车按驾驶人选定的方向行驶。 A.传动系统 B.行驶系统 C.转向系统 D.制动系统 答案&#xff1a;C 62.&#xff08;&#xff09;使汽车各总成及部件安装在适当的位置&#xff0c;对全车起支承作用以保证汽车正常行驶。 A.传动系统 B.行驶系…