当前位置: 首页 > 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为例 机器人中的数值优化|【三】无约束优化…...

AI信息摘要工具:从数据采集到智能推送的完整实践指南

1. 项目概述&#xff1a;一个AI驱动的每日信息摘要工具最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“ai-daily-digest”。光看名字&#xff0c;你大概能猜到它的核心功能&#xff1a;利用人工智能技术&#xff0c;自动为你生成每日的信息摘要。作为一个经常被信息洪流…...

macOS虚拟机解锁终极指南:在普通PC上运行苹果系统的完整解决方案

macOS虚拟机解锁终极指南&#xff1a;在普通PC上运行苹果系统的完整解决方案 【免费下载链接】unlocker VMware Workstation macOS 项目地址: https://gitcode.com/gh_mirrors/unlo/unlocker 想要在Windows或Linux电脑上体验macOS系统&#xff0c;但又不想花费高昂的价…...

深耕区域数字生态,智森传媒赋能本地中小企业破局增长

在本地生活流量红利消退、行业内卷加剧的当下&#xff0c;中小企业数字化转型已不是选择题&#xff0c;而是生存题。十堰智森网络传媒立足本土市场&#xff0c;以技术研发为根基&#xff0c;以区域获客为核心&#xff0c;以数字人直播为抓手&#xff0c;为中小企业搭建全链路数…...

【紧急更新】Google官方刚推送的Veo 2 v2.3.1补丁深度解析:新增胶片扫描模拟、物理光晕建模与导演模式(Director Mode)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Google Veo 2 v2.3.1补丁核心特性概览 Google Veo 2 v2.3.1 补丁是面向视频生成模型推理优化与安全增强的关键更新&#xff0c;聚焦于低延迟部署、多模态对齐稳定性及合规性强化。该版本并非架构重构&a…...

Hermes Agent 可视化监控与文档生成工具 hermes-dashboard 详解

1. 项目概述与核心价值如果你正在使用 Hermes Agent 进行 AI 智能体开发&#xff0c;或者对 Agent 的内部运行状态感到好奇&#xff0c;那么你很可能需要一个“上帝视角”。hermes-dashboard正是这样一个工具&#xff0c;它为你提供了一个实时的监控仪表盘和一个自动生成的、可…...

龙为权,凰为心:凰标守住文化最柔软的底线@凤凰标志

龙为权凰为心 中国文艺生态的双轨平衡宣言秩序权力与创作初心&#xff0c;一刚一柔&#xff0c; 如日月轮值&#xff0c;缺一不可。 龙标掌「权」&#xff0c;凰标守「心」&#xff0c; 双轨并行&#xff0c;方可让文化既筋骨强健&#xff0c;又血肉温润。一、龙标&#xff1a;…...

OpenClaw CLI:在终端无缝集成AI智能体的MCP服务器部署指南

1. 项目概述&#xff1a;OpenClaw CLI&#xff0c;一个连接终端与智能体的桥梁 如果你和我一样&#xff0c;日常开发工作大部分时间都泡在终端里&#xff0c;同时又对AI智能体&#xff08;Agent&#xff09;的自动化能力垂涎三尺&#xff0c;那么你肯定也遇到过这样的痛点&…...

APK Installer终极指南:如何在Windows上快速安装安卓应用?

APK Installer终极指南&#xff1a;如何在Windows上快速安装安卓应用&#xff1f; 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 还在为Windows上安装安卓应用而烦恼吗…...

ML:SARSA 的基本原理与实现

在强化学习中&#xff0c;智能体&#xff08;Agent&#xff09;并不是一次性从已有标签中学习答案&#xff0c;而是在环境&#xff08;Environment&#xff09;中不断尝试动作、观察结果、获得奖励&#xff0c;并根据经验逐步调整行为策略。在 Q 学习中&#xff0c;智能体可以通…...

超越官方Demo:如何用COCO预训练权重快速微调Mask R-CNN处理你的自定义数据

超越官方Demo&#xff1a;如何用COCO预训练权重快速微调Mask R-CNN处理你的自定义数据 当你在工业质检、医疗影像分析或遥感图像处理中遇到需要精确目标分割的场景时&#xff0c;从头训练一个Mask R-CNN模型无疑是奢侈的。COCO数据集预训练权重就像一位经验丰富的"视觉专家…...