小白学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.mzph.cn/pingmian/38061.shtml

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

相关文章

WEB与低代码:B/S架构在开发中的应用与优势

在互联网迅猛发展的今天&#xff0c;WEB应用已经成为人们日常生活和工作中不可或缺的一部分。随着技术的进步和需求的多样化&#xff0c;开发高效、灵活且易于维护的WEB应用变得尤为重要。B/S架构&#xff08;Browser/Server Architecture&#xff09;作为一种常见的WEB应用架构…

天天生鲜数据库设计

目录 1、用户表2、商品表SKU和SPU的概念区分3、商品表改进4、redis实现购物车模块&#xff0c;redis保存用户最近浏览记录5、订单表 设计表时&#xff0c;出现一对多的情况&#xff0c;可以将对应的“多”单独拿出来重新设计一个表 1、用户表 &#xff08;灰色的部分不存在表…

MySQL之如何处理超大分页

如何处理MySQL超发分页&#xff1f; 可以使用覆盖索引解决 【点击进入】 MySQL超大分页处理 在数据量较大时&#xff0c;如果使用limit分页查询&#xff0c;在查询时&#xff0c;越往后&#xff0c;分页查询效率会越低。 示例&#xff1a; select * from user limit 900000…

仓库管理系统带万字文档基于spingboot vue的前后端分离仓库管理系统java项目java课程设计java毕业设计

文章目录 仓库管理系统一、项目演示二、项目介绍三、万字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档&#xff08;9.9&#xffe5;带走&#xff09; 仓库管理系统 一、项目演示 仓库管理系统 二、项目介绍 基于spingboot和vue的前后端分离仓库管…

华测视频RTK,AR实景导航

华测导航视频测量RTK技术,通过融合卫星导航、惯导与视频摄影测量算法,让“所见即所测”成为现实,让测量工作变得更加智能、高效。 视频测量RTK:智能测绘的新里程碑 华测RTK的性能和广泛应用,在市场中获得了用户的认可,平均每10位用户中即有6位推荐。其视频测量功能通过引入自动…

如何用GPT开发一个基于 GPT 的应用?

原文发自博客&#xff1a;GPT应用开发小记 如何开发一个基于 GPT 的应用&#xff1f;答案就在问题里&#xff0c;那就是用 GPT 来开发基于 GPT 的应用。本文以笔者的一个开源项目 myGPTReader 为例&#xff0c;分享我是如何基于 GPT 去开发这个系统的&#xff0c;这个系统的功能…

【Django】网上蛋糕项目商城-关键字搜索,商品详情功能

概念 上文中已经实现热销和新品的商品列表功能&#xff0c;本文篇幅中实现关键字搜索商品&#xff0c;将商品加入购物车&#xff0c;以及查看商品的详情信息等功能 关键字搜索实现步骤 在head.html头部页面中&#xff0c;鼠标移动至搜索图标会显示隐藏的搜索框进行输入关键信…

吉利银河L6(官方小订送的3M) 对比 威固vk70+ks15

吉利送的号称价值2000的3M效果 撕膜重贴 威固vk70ks15 之后的效果 // 忘记测反射的热量了 可以验证金属膜是反射热而不是吸热 金属膜 手机GPS还能用吗 亲测 能用 太阳能总阻隔率 3M貌似20%出头 威固前档55% 侧后挡高一点不超过60% 夏天真实太阳发热能量 即阻隔率55%到60% …

使用Visual Studio Code记笔记

因为学习需要&#xff0c;记笔记是很有必要的&#xff0c;平常发CSDN&#xff08;都让CSDN是很棒的哈&#xff09;&#xff0c;后来使用VS Code的时候发现了很多插件&#xff0c;觉得做笔记还是相对不错的&#xff0c;主要用到的还是Markdown 主要设计的插件包括&#xff1a; …

PL/SQL入门到实践

一、什么是PL/SQL PL/SQL是Procedural Language/Structured Query Language的缩写。PL/SQL是一种过程化编程语言&#xff0c;运行于服务器端的编程语言。PL/SQL是对SQL语言的扩展。PL/SQL结合了SQL语句和过程性编程语言的特性&#xff0c;可以用于编写存储过程、触发器、函数等…

Hallo:分级音频驱动视觉合成肖像动画

团队&#xff1a;百度&#xff08;王井东大佬&#xff09;&#xff0c;复旦&#xff0c;瑞士ETH&#xff0c;南大 文章目录 概要介绍相关工作整体架构流程技术名词解释层次音频驱动的视觉合成训练和推理训练实验设置讨论社会风险和缓解措施小结 概要 肖像图像动画领域&#x…

如何修改PDF文档的作者名称?

要修改一个 PDF 文档的作者名称&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. **使用 Adobe Acrobat**&#xff08;如果有&#xff09;&#xff1a; - Adobe Acrobat 是一个功能强大的 PDF 编辑工具&#xff0c;支持修改文档属性信息&#xff0c;包括作者名称。打开…

一个用于自动复制文本的小工具:Auto_Copy

自动复制工具 这是一个在 Windows 上用于自动复制选中文本到剪贴板的小工具。该工具还允许通过右键单击粘贴剪贴板内容。 灵感来源: 在使用Mobaxterm时,我注意到其软件中具备选中即自动复制和右键直接粘贴的功能。但是,这种选中自动复制的功能仅在软件内部有效。由于这一功能…

什么是无头浏览器?

简而言之&#xff0c;无头浏览器是没有图形用户界面 &#xff08;GUI&#xff09; 的 Web 浏览器。GUI 包括用户与之交互的数字元素&#xff0c;例如按钮、图标和窗口。但是&#xff0c;关于无头浏览器&#xff0c;您需要了解的还有很多。 在本文中&#xff0c;您将了解什么是…

Go语言环境安装 第一个Go程序

Go下载地址 哪个能用用哪个。 https://go.dev/ https://golang.google.cn/&#xff08;Golang官网的官方镜像&#xff09; Windows 使用.msi安装包安装 下载msi文件 安装 双击运行go1.22.4.windows-amd64.msi Next 勾选I accept the terms in the License Agreement&…

Webpack: 持久化缓存大幅提升构建性能

概述 缓存是一种应用非常广泛性能优化技术&#xff0c;在计算机领域几乎无处不在&#xff0c;例如&#xff1a;操作系统层面 CPU 高速缓存、磁盘缓存&#xff0c;网路世界中的 DNS 缓存、HTTP 缓存&#xff0c;以及业务应用中的数据库缓存、分布式缓存等等。 那自然而然的&am…

路径规划 | 基于蜣螂优化算法的栅格地图机器人路径规划(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 路径规划 | 基于蜣螂优化算法的栅格地图机器人路径规划&#xff08;Matlab&#xff09; 1.利用蜣螂算法DBO优化栅格地图机器人路径规划&#xff0c;效果如图所示&#xff0c;包括迭代曲线图、栅格地图等等&#xff5e…

VScode配置

1.设置鼠标悬停提示 1.1 问题描述 打开vscode&#xff0c;按住ctrl鼠标左键不能跳转定义&#xff08;右键没有go to definition&#xff09; 1.2 解决办法 打开设置界面&#xff1a;文件->首选项->设置在搜索框中搜索intelli Sense Engine &#xff08;需要先安装C/C…

【Python】已解决:ModuleNotFoundError: No module named ‘sklearn‘

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named ‘sklearn‘ 一、分析问题背景 在进行机器学习项目时&#xff0c;Scikit-Learn&#xff08;简称sklearn&#xff09;是一…

Linux多进程和多线程(二)-进程间通信-管道用法

进程间通信 关于多进程的通信管道无名管道(匿名管道)创建无名管道示例:创建子进程,父进程通过管道向子进程发送消息无名管道(匿名管道) 的特点 有名管道(命名管道) 创建有名管道需要调⽤ mkfifo() 函数示例:创建两个没有关联关系的进程,通过有名管道通信 注意: 缺点优点 关于判…