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

WebGL笔记:WebGL中绘制圆点,设定透明度,渲染动画

WebGL 绘制圆点

  • 基于片元着色器来画圆形
  • 片元着色器在屏幕中画图是基于一个个的像素的
  • 每次画一个像素时,都会执行片元着色器中的main方法
  • 那么,我们就可以从这一堆片元中(n个像素点)找出属于圆形的部分
  • 片元的位置叫做 gl_PointCoord (一个点中片元的坐标位)
    • 比如,一个点的宽高都是1 , 片元的 x,y 位置在 0 - 1 之间
    • 点的中心点的坐标位置是(0.5, 0.5), 如果片元到中心的位置 小于 0.5
    • 那么可以认为这个片元是在圆内的,这样,只渲染圆内的片元,圆外的片元就不再渲染
  • 文档:
    • https://registry.khronos.org/OpenGL-Refpages/gl4/html/gl_PointCoord.xhtml
    • https://registry.khronos.org/OpenGL-Refpages/gl4/
<script id="fragmentShader" type="x-shader/x-fragment">precision mediump float;uniform vec4 u_FragColor;void main() {float dist = distance(gl_PointCoord, vec2(0.5, 0.5));if(dist < 0.5) {gl_FragColor = u_FragColor;} else {discard;}}
</script>
  • distance 是计算两个点之间距离的函数
  • discard 丢弃,即不会一个片元进行渲染
  • 其他参考上篇文章,来画出圆形

WebGL 中与CSS配合展示背景图

  • 在 css 中设置背景图
    #canvas {background: url("./bg.jpg");background-size: cover;background-position: right bottom;
    }
    
  • 在 js 刷底色的时候, 给一个透明色, 这样才能看见canvas的css背景
    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    

WebGL中片元透明度的设定

  • 一般来说,绘制图形,让图形有一定的颜色,并且有一定的透明度,光是使用 uniform4fv 设置是不行的
  • 还需要做两件事:
    gl.enable(gl.BLEND); // 开启片元的颜色合成功能
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // 设置片元的合成方式
    
  • 之后正常使用uniform4fv进行渲染即可
    
    const arr = new Float32Array([0.87, 0.91, 1, a]);
    gl.uniform4fv(u_FragColor, arr);
    

WebGL中设置图形的动画

  • 所谓的动画,就是一帧一帧的图像变化累计的结果,如果我们想要使用代码实现动画,还需要了解一下概念
    • 关键帧:可以说这是动画中的里程碑,连续两个关键帧之间,我们可以用数学来实现渐变
    • 时间轨:一次动画执行完成所需要的时间轨道,包含不同的关键帧,通过关键帧,对其中目标对象的状态进行插值计算
    • 补间动画:一个物体不同关键帧,即连续相邻的两个关键帧之间的状态进行差值运算,得到当前过渡时间的不同画面,来实现平滑过渡
    • 合成:不同物体所表示的多个时间轨的集合
  • 对动画进行封装
    • 框架层面,我们要针对合成对象做设计:画布上可能会有多个对象做动画运动
    • 运动层面,我们要对时间轨做计算:针对每个对象,在一个完整动画的时间轨上应如何补全关键帧之间的间隔渲染

1 )框架层面的设计

export default class Compose {constructor() {this.parent = null // 当前对象parent置空,这是一个编程习惯this.children = [] // 用于存储多个对象}add(obj) {obj.parent = this // 当前对象和当前工具建立关系this.children.push(obj) // 将当前对象加入子队列数组}// 这里是工具的updateupdate(t) {// 内部调用每个对象的update方法实现动画this.children.forEach(ele => {ele.update(t)})}
}

2 )时间轨的设计

export default class Track {constructor(target) {this.target = target // 当前对象this.parent = null // 父对象,合成对象,默认为空this.start = 0 // 开始时间默认是0this.timeLen = 5 // 一个时间轨的长度,也就是完成一次完整动画所需要的时间,单位毫秒this.loop = false // 是否循环播放动画this.keyMap = new Map() // 关键帧的集合}// 当前对象的每一帧运动函数update(t) {const { keyMap, timeLen, target, loop } = thislet time = t - this.start // 当前时间距离开始时间的时间长度// 如果开启循环,则加入取余操作,将当前时间循环递增,不让超过自身设定if(loop) {time = time % timeLen}for(const [key,fms] of keyMap.entries()) {const last = fms.length - 1 // 最后一项if(time < fms[0][0]) {// 在第一个关键帧之前的设置为第一个关键帧的状态target[key] = fms[0][1]} else if(time > fms[last][0]) {// 时间在最后一个关键帧之后设定为最后一个关键帧的状态target[key] = fms[last][1]} else {// 在各个中间态实行数学计算状态渐变,即:补间状态target[key] = getValBetweenFms(time, fms, last)}}}
}// 补间状态计算函数
function getValBetweenFms(time,fms,last) {for(let i = 0; i < last; i++) {const fm1 = fms[i]const fm2 = fms[i+1]if(time >= fm1[0] && time <= fm2[0]) {const delta = {x: fm2[0] - fm1[0],y: fm2[1] - fm1[1],}const k = delta.y / delta.xconst b = fm1[1] - fm1[0] * kreturn k * time + b}}
}
  • 上述 keyMap 关键帧集合,这里是一个对象的关键帧集合,结构如下,
    [['对象属性1',[[时间1,属性值], //关键帧[时间2,属性值], //关键帧]],['对象属性2',[[时间1,属性值], //关键帧[时间2,属性值], //关键帧]],
    ]
    
  • time 当前时间
  • fms 某个属性的关键帧集合
  • last 最后一个关键帧的索引位置
  • 其实现思路如下
    • 遍历所有关键帧
    • 判断当前时间在哪两个关键帧之间
    • 基于这两个关键帧的时间和状态,求点斜式
    • 基于点斜式求本地时间对应的状态
  • 这里 y = kx + b 这个公式是一般公式(推荐),还可以用其他曲线公式来处理动画

3 )应用

const compose = new Compose()
const stars = [] // 点数据的集合
canvas.addEventListener('click', function(event) {const { x, y } = getPosByMouse(event,canvas) // 获取当前坐标,这里具体实现可看之前博客代码,只是做了个函数封装const a = 1const s = Math.random() * 5 + 2const obj = { x, y, s, a } // x坐标,y坐标,s尺寸,a透明度stars.push(obj)const track = new Track(obj)track.start = new Date()track.keyMap = new Map([['a', [[500, a],[1000, 0],[1500, a],]]])track.timeLen = 2000track.loop = truecompose.add(track)
})

渲染方法如下,参考之前博客代码

function render(){gl.clear(gl.COLOR_BUFFER_BIT);stars.forEach(({x,y,s,a}) => {gl.vertexAttrib2f(a_Position,x,y);gl.vertexAttrib1f(a_PointSize,s);gl.uniform4fv(u_FragColor, new Float32Array([0.87,0.92,1, a]));gl.drawArrays(gl.POINTS, 0, 1);})
}

用请求动画帧驱动动画,连续更新数据,渲染视图

!(function ani() {compose.update(new Date())render()requestAnimationFrame(ani) // 重复执行
})()

相关文章:

WebGL笔记:WebGL中绘制圆点,设定透明度,渲染动画

WebGL 绘制圆点 基于片元着色器来画圆形片元着色器在屏幕中画图是基于一个个的像素的每次画一个像素时&#xff0c;都会执行片元着色器中的main方法那么&#xff0c;我们就可以从这一堆片元中(n个像素点)找出属于圆形的部分片元的位置叫做 gl_PointCoord (一个点中片元的坐标位…...

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过命令行管理华为云云耀云服务器

华为云云耀云服务器L实例评测 &#xff5c; 实例使用教学之简单使用&#xff1a;通过命令行管理华为云云耀云服务器 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云耀云服务…...

微信小程序 课程签到系统

目录 前端页面展示主页面我的课程个人中心评论功能签到功能课程绑定超级管理员页面 前端文件结构文件结构app.json前端架构和开发工具前端项目地址 后端后端架构后端项目地址 注意事项 前端页面展示 主页面 登录页面&#xff1a; 账号是&#xff1a;用户名或者手机号 密码是&a…...

如何用Postman做接口自动化测试

前言 什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来。 本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&#xff0c;已经开发完成…...

支付宝电脑网站支付,异步通知

一&#xff1a;异步通知是支付宝回调商户的服务器&#xff0c;所以这个地址需要通过外网访问&#xff0c;在真实项目中都会有对应的服务器&#xff0c;但是在测试中只有使用内网穿透工具 推荐使用NATAPP-内网穿透 基于ngrok的国内高速内网映射工具 配置好内网穿透之后不要忘记…...

【广州华锐互动】奶牛养殖难产助产3D沉浸式教学平台

在传统的奶牛难产助产教学中&#xff0c;主要依赖理论知识和2D图像来进行教学。然而&#xff0c;这种教学方式往往无法全面、真实地展示奶牛难产的各种情况&#xff0c;教学效果也不尽如人意。随着科技的发展&#xff0c;3D互动教学的出现&#xff0c;为奶牛难产助产教学带来了…...

IDEA社区版,真香!

IDEA&#xff08;IntelliJ IDEA&#xff09;是众多 Java 开发者的首选。 商业版的昂贵 IDEA 商业版&#xff08;IntelliJ IDEA Ultimate&#xff09;功能非常强大&#xff0c;能够满足 Java 开发的所有需求&#xff0c;但其高昂的价格…… 此时只能感叹&#xff0c;不是不想用…...

SpringBoot实现全局异常处理

1.全局异常处理介绍 1.1 简介 全局异常处理器即把错误异常统一处理的方法&#xff0c;可以在多个地方使用&#xff0c;而不需要为每个地方编写单独的处理逻辑。它可以帮助开发人员更好地管理异常&#xff0c;并提供一致的错误处理方式。 1.2 优点 1.全局异常处理可以提高代码…...

Day05-循环高级和数组

循环高级 1.无限循环 概念&#xff1a; 又叫死循环。循环一直停不下来。 for格式&#xff1a; for(;;){System.out.println("循环执行一直在打印内容"); } 解释&#xff1a; 初始化语句可以空着不写&#xff0c;表示循环之前不定义任何的控制变量。 条件判断…...

从代码操作层面解释什么是“面相对象编程”?

起因&#xff1a; 今天开了一个小会&#xff0c;会上朋友给我们说了一个事&#xff0c;Java项目上他开发一个小功能 用了很多代码&#xff0c;项目经理发现代码太多&#xff0c;说要优化一下&#xff0c;然后亲自帮同事优化&#xff0c;结果是查库的代码少了至少10条sql&#x…...

【MySQL】SQL优化、char、varchar、外键约束、排查慢sql等重点知识汇总

目录 SQL语句 char和varchar比较 SQL语句如何优化 说一下你理解的外键约束 如何排查慢 sql SQL语句 对库操作 创建数据库 create database 数据库名 删除数据库 drop database 数据库名 显示所有数据库 show databases 选中数据库 use 数据库名 对表操作 创建表…...

git管理常用命令

1、下载代码 git clone 地址2、软件代码提交 1、查看工程中被修改的文件&#xff1a;git status 2.将不需要提交的文件回退&#xff1a;git check <文件路径> 3.更新工程到最新&#xff1a;git pull 4.将本地代码添加到暂存区&#xff1a;git add <将要提交的文件路…...

Python 逢七拍手小游戏2.0

"""逢七拍手游戏介绍&#xff1a;逢七拍手游戏的规则是&#xff1a;从1开始顺序数数&#xff0c;数到有7&#xff0c;或者是7的倍数时&#xff0c;就拍一手。例如&#xff1a;7、14、17......70......知识点&#xff1a;1、循环语句for2、嵌套条件语句if/elif/e…...

基于微信小程序的在线小说阅读系统,附数据库、教程

1 功能简介 Java基于微信小程序的在线小说阅读系统 微信小程序的在线小说阅读系统&#xff0c;系统的整体功能需求分为两部分&#xff0c;第一部分主要是后台的功能&#xff0c;后台功能主要有小说信息管理、注册用户管理、系统系统等功能。微信小程序主要分为首页、分类和我的…...

216. 组合总和 III

找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 示例 1: 输入: k 3, n 7 输出: [[1,2,4]] 解释: …...

【Java】数组的深浅拷贝问题(二维数组举例)(136)

深拷贝和浅拷贝&#xff1a; 对于数组来说&#xff0c;深拷贝就是相当于拷贝了数组的对象&#xff08;基本数据类型&#xff09;&#xff0c;也就是数组当中的内容。而浅拷贝就是拷贝的是数组的地址&#xff08;引用类型&#xff09;&#xff0c;浅拷贝只是复制了对象的引用地…...

【轮趣-科大讯飞】M260C 环形六麦测试 2 - ROS1功能测试与唤醒、语音识别程序解析

所有内容请看&#xff1a; 博客学习目录_Howe_xixi的博客-CSDN博客https://blog.csdn.net/weixin_44362628/article/details/126020573?spm1001.2014.3001.5502原文在飞书&#xff0c;请联系我获取阅读链接&#xff0c;我太懒了...

油猴(篡改猴)学习记录

第一个Hello World 注意点:默认只匹配了http网站,如果需要https网站,需要自己添加match https://*/*代码如下 这样子访问任意网站就可以输出Hello World // UserScript // name 第一个脚本 // namespace http://tampermonkey.net/ // version 0.1 // descri…...

LeetCode 面试题 05.08. 绘制直线

文章目录 一、题目二、Java 题解 一、题目 已知一个由像素点组成的单色屏幕&#xff0c;每行均有 w 个像素点&#xff0c;所有像素点初始为 0&#xff0c;左上角位置为 (0,0)。 现将每行的像素点按照「每 32 个像素点」为一组存放在一个 int 中&#xff0c;再依次存入长度为 le…...

机器人中的数值优化|【六】线性共轭梯度法,牛顿共轭梯度法

机器人中的数值优化|【六】线性共轭梯度法&#xff0c;牛顿共轭梯度法 往期回顾 机器人中的数值优化|【一】数值优化基础 机器人中的数值优化|【二】最速下降法&#xff0c;可行牛顿法的python实现&#xff0c;以Rosenbrock function为例 机器人中的数值优化|【三】无约束优化…...

FastestDet---原理介绍

1.测试指标 2.算法定位 FastestDet是设计用来接替yolo-fastest系列算法,相比于业界已有的轻量级目标检测算法如yolov5n, yolox-nano, nanoDet, pp-yolo-tiny, FastestDet和这些算法根本不是一个量级,FastestDet无论在速度还是参数量上,都是要小好几个数量级的,但是精度自然…...

ORACLE 在内存管理机制上的演变和进化

截止目前&#xff0c;计算机内存仍然被认为是我们可以获得的最快速度的物理存储设备。 将频繁访问的数据尽可能地置于内存中&#xff0c;已成为当前各种软件和应用程序提高数据访问性能&#xff0c;减少访问延迟的最为有效的途径。 然而&#xff0c;内存作为关键的计算资源&am…...

Linux ❀ 进程出现process information unavailable时的消除方法

[rootmaster ~]# jps 74963 -- process information unavailable 78678 Jps [rootmaster ~]# cd /tmp/hsperfdata_redhat/ # redhat为启动该java进程的用户ps -ef | grep $pid查找 [rootmaster hsperfdata_redhat]# ll total 32 -rw------- 1 redhat redhat 32768 Sep 27 15:…...

ps智能填充功能平替:alpaca的安装和使用

为了解决ps beta 智能填充无法使用的问题&#xff0c;需要用alpaca来平替&#xff0c;下面是安装教程&#xff1a; 安装方法&#xff1a; 1、下载插件。 alpaca插件汉化-夸克网盘https://pan.quark.cn/s/1168b447a44e#/list/share 2、 根据使用的PS版本&#xff0c;选择对应文件…...

【前端打怪升级日志之ES6篇】玩转函数

学习资料 阮一峰老师《ECMAScript 6 入门》— 函数的扩展 总结应用 1. 函数参数默认值与对象解构赋值默认值的结合使用 // 场景&#xff1a;方法调用时传参希望只传第二个参数 // 方案1&#xff1a; function foo({x1,y2}){console.log(x,y); } foo({}) //1 2 foo({x:2}) /…...

网址静态码手机制作教程,附图文详解!

网址的静态码是如何生成的呢&#xff1f;静态码是二维码的一种常用类型&#xff0c;一般常见的静态码类型主要是文本或者网址&#xff0c;那么在电脑制作静态码的方法相信很多小伙伴都知道怎么做&#xff0c;那么手机上制作的方法&#xff0c;大家感兴趣吗&#xff1f;下面来给…...

服务器性能测试监控平台export+prometheus(普罗米修斯)+grafana搭建

1. export 数据采集工具 简介&#xff1a; export是prometheus是的数据采集组件的总称&#xff0c;它可以将采集到的数据转为prometheus支持的格式 node_export: 用来监控服务器硬件资源的采集器&#xff0c;端口号为9100mysql_export: 用来监控mysql数据库资源的采集器&…...

【24种设计模式】责任链模式

责任链模式是一种行为设计模式&#xff0c;它允许你将请求沿着处理链进行传递&#xff0c;直到有一个处理者能够处理该请求为止。这种模式将请求的发送者和接收者解耦&#xff0c;使多个对象都有机会处理该请求。 责任链模式的结构 责任链模式由以下几个角色组成&#xff1a;…...

C#异步委托的三种实现 BeginInvoke / EndInvoke / IsCompleted

本文将介绍C#异步委托的三种实现方式&#xff0c;并给出相关示例代码及解析。 注意事项 用委托开启线程的前提是&#xff1a;创建项目时必须选择“.NET Framework"&#xff0c;如果选择的是”.Net Core“&#xff0c;在调用BeginInvoke时&#xff0c;系统会报错”Operati…...

在HTTP请求中安全传输base64编码的字符串

前言 base64是一种常见的的编码格式&#xff0c;它可以把二进制数据编码成一个由大小写英文字母&#xff08;a-zA-Z&#xff09;、阿拉伯数字&#xff08;0-9&#xff09;&#xff0c;以及三个特殊字符、/、组成的字符串。 问题 但是在URL传输中&#xff0c;、/、这三个特殊…...

三河市最新消息/seo技术交流论坛

拿到Nuvi 350的时候&#xff0c;我惊讶不已&#xff0c;有这么小巧的GPS&#xff1f;竟然比PDA还要小一点点。把玩了一下&#xff0c;喜欢的不得了。下面我就同大家一起来分享我的Nuvi 350试用手记。 很早就去浏览台湾的Garmin网站&#xff0c;对在台湾新上市的Nuvi 350心仪不已…...

网页设计作业样例/seo基础教程

光敏电阻器&#xff08;photoresistor&#xff09;又叫光感电阻&#xff0c;它的电阻值会根据光的强度变化而变化。 现在我要把它接入树莓派Pico&#xff0c;观察电阻值随光强度的变化情况&#xff0c;本试验参考的文章&#xff1a;https://peppe8o.com/how-to-use-a-photoresi…...

长春公司网站建设/百度seo2022新算法更新

linux安装Navicat&#xff0c;界面出现乱码解决方法 &#xff08;转发&#xff09;参考文章&#xff1a; &#xff08;1&#xff09;linux安装Navicat&#xff0c;界面出现乱码解决方法 &#xff08;转发&#xff09; &#xff08;2&#xff09;https://www.cnblogs.com/miao…...

网推所和传统律所比较/搜索引擎优化方法有哪几种

高德地图 Android SDK 能够为 Android 应用开发人员提供互动的、功能丰富的 Android 手机地图。 将地图显示功能与搜索服务、定位服务分别封装为三个类库。每一个类库不相互依赖&#xff0c;用户能够分开使用。提供 2D&#xff08;栅格&#xff09;和3D&#xff08;矢量&#x…...

国内网页设计公司前十名/郑州seo优化服务

【Java基础-java反射】Java反射知识点(有这一篇就够了) 反射是框架设计的灵魂 &#xff08;使用的前提条件&#xff1a;必须先得到代表的字节码的Class&#xff0c;Class类用于表示.class文件&#xff08;字节码&#xff09;&#xff09; 文章目录【Java基础-java反射】Java反射…...

枣庄手机网站建设报价/爱站网关键词查询系统

百度地图api2.4.1 在发起步行路径检索的时候 onGetWalkingRouteResult回调方法中的结果总是空的&#xff0c;即使直接复制api的代码也不对。坐标我是用的百度地图的拾取坐标系统获取的坐标。开始的代码double cLat112.556305;double cLon32.975724;double cLat2112.560727;doub…...