绚丽的流光心

news2024/12/25 12:56:51

快到520了,送大家一颗心吧。
在这里插入图片描述
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <style>
    body {
      background-color: #000;
      margin: 0;
      overflow: hidden;
      background-repeat: no-repeat;
    }
  </style>
</head>
<body>
<canvas id="canvas" width="1400" height="600"></canvas>
</body>
<script>
  var canvas = document.getElementById("canvas");

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  // 初始化GL上下文
  var gl = canvas.getContext('webgl');
  if(!gl){
    console.error("Unable to initialize WebGL.");
  }

  //Time
  var time = 0.0;

  //************** 着色器源 **************

  var vertexSource = `
attribute vec2 position;
void main() {
	gl_Position = vec4(position, 0.0, 1.0);
}
`;

  var fragmentSource = `
precision highp float;

uniform float width;
uniform float height;
vec2 resolution = vec2(width, height);

uniform float time;

#define POINT_COUNT 8

vec2 points[POINT_COUNT];
const float speed = -0.5;
const float len = 0.25;
float intensity = 1.3;
float radius = 0.008;

//https://www.shadertoy.com/view/MlKcDD
//Signed distance to a quadratic bezier
float sdBezier(vec2 pos, vec2 A, vec2 B, vec2 C){
	vec2 a = B - A;
	vec2 b = A - 2.0*B + C;
	vec2 c = a * 2.0;
	vec2 d = A - pos;

	float kk = 1.0 / dot(b,b);
	float kx = kk * dot(a,b);
	float ky = kk * (2.0*dot(a,a)+dot(d,b)) / 3.0;
	float kz = kk * dot(d,a);

	float res = 0.0;

	float p = ky - kx*kx;
	float p3 = p*p*p;
	float q = kx*(2.0*kx*kx - 3.0*ky) + kz;
	float h = q*q + 4.0*p3;

	if(h >= 0.0){
		h = sqrt(h);
		vec2 x = (vec2(h, -h) - q) / 2.0;
		vec2 uv = sign(x)*pow(abs(x), vec2(1.0/3.0));
		float t = uv.x + uv.y - kx;
		t = clamp( t, 0.0, 1.0 );

		// 1 root
		vec2 qos = d + (c + b*t)*t;
		res = length(qos);
	}else{
		float z = sqrt(-p);
		float v = acos( q/(p*z*2.0) ) / 3.0;
		float m = cos(v);
		float n = sin(v)*1.732050808;
		vec3 t = vec3(m + m, -n - m, n - m) * z - kx;
		t = clamp( t, 0.0, 1.0 );

		// 3 roots
		vec2 qos = d + (c + b*t.x)*t.x;
		float dis = dot(qos,qos);

		res = dis;

		qos = d + (c + b*t.y)*t.y;
		dis = dot(qos,qos);
		res = min(res,dis);

		qos = d + (c + b*t.z)*t.z;
		dis = dot(qos,qos);
		res = min(res,dis);

		res = sqrt( res );
	}

	return res;
}


//http://mathworld.wolfram.com/HeartCurve.html
vec2 getHeartPosition(float t){
	return vec2(16.0 * sin(t) * sin(t) * sin(t),
							-(13.0 * cos(t) - 5.0 * cos(2.0*t)
							- 2.0 * cos(3.0*t) - cos(4.0*t)));
}

//https://www.shadertoy.com/view/3s3GDn
float getGlow(float dist, float radius, float intensity){
	return pow(radius/dist, intensity);
}

float getSegment(float t, vec2 pos, float offset, float scale){
	for(int i = 0; i < POINT_COUNT; i++){
		points[i] = getHeartPosition(offset + float(i)*len + fract(speed * t) * 6.28);
	}

	vec2 c = (points[0] + points[1]) / 2.0;
	vec2 c_prev;
	float dist = 10000.0;

	for(int i = 0; i < POINT_COUNT-1; i++){
		//https://tinyurl.com/y2htbwkm
		c_prev = c;
		c = (points[i] + points[i+1]) / 2.0;
		dist = min(dist, sdBezier(pos, scale * c_prev, scale * points[i], scale * c));
	}
	return max(0.0, dist);
}

void main(){
	vec2 uv = gl_FragCoord.xy/resolution.xy;
	float widthHeightRatio = resolution.x/resolution.y;
	vec2 centre = vec2(0.5, 0.5);
	vec2 pos = centre - uv;
	pos.y /= widthHeightRatio;
	//Shift upwards to centre heart
	pos.y += 0.02;
	float scale = 0.000015 * height;

	float t = time;

	//Get first segment
  float dist = getSegment(t, pos, 0.0, scale);
  float glow = getGlow(dist, radius, intensity);

  vec3 col = vec3(0.0);

	//White core
  col += 10.0*vec3(smoothstep(0.003, 0.001, dist));
  //Pink glow
  col += glow * vec3(1.0,0.05,0.3);

  //Get second segment
  dist = getSegment(t, pos, 3.4, scale);
  glow = getGlow(dist, radius, intensity);

  //White core
  col += 10.0*vec3(smoothstep(0.003, 0.001, dist));
  //Blue glow
  col += glow * vec3(0.1,0.4,1.0);

	//Tone mapping
	col = 1.0 - exp(-col);

	//Gamma
	col = pow(col, vec3(0.4545));

	//Output to screen
 	gl_FragColor = vec4(col,1.0);
}
`;

  //************** 程序功能 **************

  window.addEventListener('resize', onWindowResize, false);

  function onWindowResize(){
    canvas.width  = window.innerWidth;
    canvas.height = window.innerHeight;
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.uniform1f(widthHandle, window.innerWidth);
    gl.uniform1f(heightHandle, window.innerHeight);
  }


  //编译着色器并与源组合
  function compileShader(shaderSource, shaderType){
    var shader = gl.createShader(shaderType);
    gl.shaderSource(shader, shaderSource);
    gl.compileShader(shader);
    if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
      throw "Shader compile failed with: " + gl.getShaderInfoLog(shader);
    }
    return shader;
  }

  function getAttribLocation(program, name) {
    var attributeLocation = gl.getAttribLocation(program, name);
    if (attributeLocation === -1) {
      throw 'Cannot find attribute ' + name + '.';
    }
    return attributeLocation;
  }

  function getUniformLocation(program, name) {
    var attributeLocation = gl.getUniformLocation(program, name);
    if (attributeLocation === -1) {
      throw 'Cannot find uniform ' + name + '.';
    }
    return attributeLocation;
  }

  //************** 创建着色器 **************

  //创建顶点和片段着色器
  var vertexShader = compileShader(vertexSource, gl.VERTEX_SHADER);
  var fragmentShader = compileShader(fragmentSource, gl.FRAGMENT_SHADER);

  //创建着色器程序
  var program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);

  gl.useProgram(program);

  //设置覆盖整个画布的矩形
  var vertexData = new Float32Array([
    -1.0,  1.0, 	// 左上
    -1.0, -1.0, 	// 左下
    1.0,  1.0, 	// 右上
    1.0, -1.0, 	// 右下
  ]);

  //创建顶点缓冲区
  var vertexDataBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);

  // 顶点缓冲区中数据的布局
  var positionHandle = getAttribLocation(program, 'position');

  gl.enableVertexAttribArray(positionHandle);
  gl.vertexAttribPointer(positionHandle,
          2, 		// 位置
          gl.FLOAT, // 每个组件都是一个浮点
          false, 	// 不规范化值
          2 * 4, 	// 每个顶点有两个4字节的浮点(32位浮点为4字节)
          0 		// 从缓冲区中的多少字节开始
  );

  //设置 handle
  var timeHandle = getUniformLocation(program, 'time');
  var widthHandle = getUniformLocation(program, 'width');
  var heightHandle = getUniformLocation(program, 'height');

  gl.uniform1f(widthHandle, window.innerWidth);
  gl.uniform1f(heightHandle, window.innerHeight);

  var lastFrame = Date.now();
  var thisFrame;

  function draw(){

    //更新时间
    thisFrame = Date.now();
    time += (thisFrame - lastFrame)/1000;
    lastFrame = thisFrame;

    //发送uniforms
    gl.uniform1f(timeHandle, time);
    //绘制连接顶点0-4的三角形条带
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

    requestAnimationFrame(draw);
  }

  draw();
</script>
</html>

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

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

相关文章

国内免费版ChatGPT

目录 前言&#xff1a;网站大全 1. ChatGPT是什么 2. ChatGPT的发展历程 3. ChatGPT对程序员的影响 4. ChatGPT对普通人的影响 5. ChatGPT的不足之处 前言&#xff1a;网站大全 AI文本工具站 (laicj.cn) ——gpt-3.5 功能强大(推荐&#xff09; Chatgpt在线网页版-…

2024王道数据结构考研丨第四章:串

2024王道数据结构考研笔记专栏将持续更新&#xff0c;欢迎 点此 收藏&#xff0c;共同交流学习… 文章目录 第四章&#xff1a;串4.1串的定义和实现4.1.1串的定义4.1.2串的基本操作4.1.3串的存储结构 4.2串的模式匹配4.2.1朴素模式匹配算法4.2.2改进的模式匹配算法——KMP算法 …

【SQLServer】sqlserver数据库导入oracle

将sqlserver数据库导入到oracle 实用工具&#xff1a; SQL Server Management Studio 15.0.18424.0 SQL Server 管理对象 (SMO) 16.100.47021.07eef34a564af48c5b0cf0d617a65fd77f06c3eb1 Microsoft Analysis Services 客户端工具 15.0.19750.0 Microsoft 数据访问组件 (MDAC) …

漏洞扫描的原理

漏洞扫描是指通过自动或者手动的方式&#xff0c;对系统进行全面扫描&#xff0c;发现系统中存在的漏洞。随着互联网的发展&#xff0c;漏洞扫描的重要性越来越凸显&#xff0c;因为漏洞一旦被黑客利用&#xff0c;就可能会导致系统被攻击、数据被窃取等问题。那么什么是漏洞扫…

【实践篇】教你玩转JWT认证---从一个优惠券聊起 | 京东云技术团队

引言 最近面试过程中&#xff0c;无意中跟候选人聊到了JWT相关的东西&#xff0c;也就联想到我自己关于JWT落地过的那些项目。 关于JWT&#xff0c;可以说是分布式系统下的一个利器&#xff0c;我在我的很多项目实践中&#xff0c;认证系统的第一选择都是JWT。它的优势会让你…

shallowRef和shallowReactive的使用?

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、 shallowRef&#xff1f;二、 shallowReactive&#xff1f;在什么时候使用&#xff1f; 三、案例1、shallowRef2、shallowReactive 提示&#xff1a;以下是本篇…

为世界第一大癌症高效研发首创新药,AI大模型助力药物研发叩开未来之门

近日&#xff0c;三位高中生引爆了医药圈&#xff0c;他们使用人工智能&#xff08;AI&#xff09;引擎进行靶点发现&#xff0c;确定了多形性胶质母细胞瘤&#xff08;GBM&#xff09;的新治疗靶点&#xff0c;多形性胶质母细胞瘤&#xff08;GBM&#xff09;是最具侵袭性和最…

在外出差,如何远程登录公司内网金蝶云ERP管理系统【cpolar内网穿透】

文章目录 前言1.金蝶安装简介2. 安装cpolar内网穿透3. 创建安全隧道映射4. 在外远程访问金蝶云星空管理中心5. 固定访问地址6. 配置固定公网访问地址7.创建数据中心简介8.远程访问数据中心9. 固定远程访问数据中心地址10. 配置固定公网访问地址 转发自CSDN风浪越大%鱼越贵的文章…

微信小程序最新获取头像昵称方式

前言 版本历史变迁 一、获取头像的正确姿势 二、获取昵称的正确姿势 总结 前言 产品需要获取微信用户的昵称和头像。 这这还不简单&#xff0c;so easy&#xff01; 通过wx.getUserProfile或者 wx.getUserInfo 就可以获取到。 但是获取的昵称是”微信用户“获取的头像是…

LeetCode 515. 在每个树行中找最大值

515. 在每个树行中找最大值 描述 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09; 示例 示例1 输入&#xff1a;root [1,3,2,5,3,null,9] 输出&#xff1a;[1,3,9] 示例2 输入&#…

OpenHarmony dump渲染和合成图层SurfaceBuffer指南

OpenHarmony dump渲染和合成图层SurfaceBuffer指南 引言 博客停更很久了&#xff0c;提起笔来渐感生疏啊&#xff01;看来&#xff0c;还是得抽出时间来更新更新啊&#xff01;好了&#xff0c;感慨也发完了&#xff0c;是时候切入正题了。本篇博客主要以本人在实际项目的开发中…

Excel技巧之 【提取文件夹内的全部文件名】

在工作中&#xff0c;有时候需要将所有文档的名字提取出来做成表格。 这种情况&#xff0c;你是一个一个复制粘贴么&#xff1f;nonono&#xff01; 如果你是复制粘贴的&#xff0c;一定要试试下面的方法&#xff0c;可以快速提取文件名。 具体步骤&#xff1a; 1. 将所有的…

chatgpt赋能Python-python3_5怎么算

Python3|5是如何计算的&#xff1f; 介绍 Python是一种高级编程语言&#xff0c;许多开发人员喜欢使用它来构建各种应用程序&#xff0c;从网站到机器学习应用程序。然而&#xff0c;在使用Python编写代码时&#xff0c;很多人都会遇到一个问题&#xff1a;Python3|5计算是如…

粪菌移植——一种治疗人体疾病的新型疗法

谷禾健康 粪菌移植是一项近年来备受关注的医疗技术&#xff0c;它涉及将健康捐赠者的粪便物质转移至患有疾病或障碍患者的胃肠道。 简单来说就是选择健康合适的人粪便&#xff0c;通过科学方法提取出有用的微生物&#xff0c;去除有害与无用的部分&#xff0c;然后制成制剂&…

Redis缓存实战

一 Redis缓存简介 二 Redis缓存入门 在我们查询数据一般都是直接查询数据库&#xff0c;返回给前端。为了提高效率实际项目中会将基础数据等热点数据放入redis缓存中。 发起请求&#xff0c;先访问redis缓存&#xff0c;缓存中有直接将数据返回&#xff1b;缓存没有命中&…

玩转Netty,从“Hello World”开始

大家好&#xff0c;我是老三&#xff0c;之前里&#xff0c;我们讨论了Java的三种IO模型&#xff0c;提到了网络通信框架Netty&#xff0c;它简化和优化了NIO的使用&#xff0c;这期&#xff0c;我们正式开始走近Netty。 为什么要用Netty? 首先当然是NIO的使用&#xff0c;本…

知行之桥EDI系统2023版功能介绍——日志页面

在知行之桥EDI系统2023版中&#xff0c;除了在此前的文章中曾经介绍过的概览页面之外&#xff0c;还新增了日志页面。日志页面基于旧版本的状态页面进行了功能优化&#xff0c;为用户展示了消息、交易日志、应用程序日志、访问日志以及审计日志五种类型&#xff0c;每种日志类型…

MySQL 复合查询 内外连接

目录 基本查询回顾 多表查询 自连接 group by可以带多个 子查询 在from子句中使用子查询 合并查询 表的内连和外连 内连接 外连接 左外连接 右外连接 关于自连接和内连接&#xff08;chatgpt&#xff09; 基本查询回顾 查询工资高于 500 或岗位为 MANAGER 的雇员…

虚拟键盘:十六进制值和鼠标或键盘等效项。 代码按数字顺序列出

Virtual-Key Codes (Winuser.h) - Win32 apps | Microsoft Learn 虚拟键码 (Winuser.h) - Win32 apps | Microsoft Learn Value说明0x01鼠标左键0x02鼠标右键0x03控制中断处理0x04中间鼠标按钮 (三键鼠标)0x05X1 鼠标按钮0x06X2 鼠标按钮0x07Undefined0x08BACKSPACE 密钥0x09T…

注册阿里云OSS步骤

注册阿里云OSS步骤 阿里云是阿里巴巴集团旗下全球领先的云计算公司&#xff0c;也是国内最大的云服务提供商 。 云服务指的就是通过互联网对外提供的各种各样的服务&#xff0c;比如像&#xff1a;语音服务、短信服务、邮件服务、视频直播服务、文字识别服务、对象存储服务等等…