regl 星环

原文链接: regl 星环

上一篇: webgpu 初探

下一篇: LeetCode 生命游戏,不用新数组的方式

调调参数啥的应该能更好看点, 但是没啥意义

up-803ea48ca3cb6e5fca209fcfd6196782f1e.gif

主要思想就是生成球形点和环形点, 然后用时间去改变位置, 所有计算都在gpu里, js只创建数组和初始数据, 每次用uniform变量来传递, 这样只需要每次传递一个变量就行了

import mat4 from "gl-mat4";
import Regl from "regl";
import { getPointList } from "../../utils/sphere";
import { random, randomColor, randomInt } from "../../utils/index";
const regl = Regl();
export default () => {
  const size = 20000;
  const pointList = Array(size)
    .fill(0)
    .map(() => [
      random(-Math.PI * 2, Math.PI * 2),
      random(-Math.PI * 2, Math.PI * 2),
    ]);
  const r = () => random(-1, 1);
  const offsetList = Array(pointList.length)
    .fill(0)
    .map(() => [r(), r()]);
  const colorList = Array(pointList.length)
    .fill(0)
    .map(() => randomColor(true));
  const drawCube = regl({
    frag: `
  precision mediump float;
  varying vec3 outColor;
  void main () {
    gl_FragColor = vec4(outColor,1);
  }`,
    vert: `
  precision mediump float;
  attribute vec2 degree;  // a,b
  attribute vec3 color;
  attribute vec2 offset;
  uniform float time;
  varying vec3 outColor;
  uniform mat4 projection, view;
  float r = 1.0;
  void main() {
    outColor=color;
    vec2 d = offset*sin(time/100.0)/2.0;
    // vec2 d = offset*mod(time,100.0)/100.0;
    float x = r * sin(degree.x+d.x)*sin(degree.y+d.y);
    float y = r * sin(degree.x+d.x)*cos(degree.y+d.y);
    float z = r * cos(degree.x+d.x);
    vec3 position  = vec3(x,y,z);
    vec4 p = projection * view * vec4(position, 1);
    // gl_Position = vec4(p.x+dp.x,p.y+dp.y,p.z+dp.z,p.w); 
    gl_Position = p; 
    gl_PointSize = 2.0;
  }`,
    attributes: {
      degree: pointList,
      color: colorList,
      offset: offsetList,
    },
    primitive: "points",
    count: pointList.length,
    // elements: cubeElements,
    uniforms: {
      time: regl.prop("time"),
      view: ({ tick }) => {
        // const t = 0.5;
        const t = 0.01 * tick;
        return mat4.lookAt(
          [],
          [5 * Math.cos(t), 2.5 * Math.sin(t), 5 * Math.sin(t)],
          [0, 0.0, 0],
          [0, 1, 0]
        );
      },
      projection: ({ viewportWidth, viewportHeight }) =>
        mat4.perspective(
          [],
          Math.PI / 4,
          viewportWidth / viewportHeight,
          0.01,
          10
        ),
    },
  });

  const sizeRing = 40000;
  const ringList = Array(sizeRing)
    .fill(0)
    .map(() => [
      random(-Math.PI * 2, Math.PI * 2), // 角度
      random(-0.2, 0.2), // 偏移
    ]);
  const ringRandom = () => random(-1, 1);
  const ringOffsetList = Array(ringList.length)
    .fill(0)
    .map(() => [ringRandom(), ringRandom()]);
  const ringColorList = Array(ringList.length)
    .fill(0)
    .map(() => randomColor(true));
  const drawRing = regl({
    frag: `
  precision mediump float;
  varying vec3 outColor;
  void main () {
    gl_FragColor = vec4(outColor,1);
  }`,
    vert: `
  precision mediump float;
  attribute vec2 degree;  // a,b
  attribute vec3 color;
  attribute vec2 offset;
  uniform float time;
  uniform float dr;
  varying vec3 outColor;
  uniform mat4 projection, view;
  float r = 2.0;
  void main() {
    // vec2 d = offset*sin(time/100.0)/2.0;
    vec2 dd = degree + sin(time/1000.0)*3.0;
    vec2 d = vec2(0,0);
    float x = (r+degree.y) * sin(dd.x+d.x+dr);
    float z = (r+degree.y) * cos(dd.x+d.y+dr);
    // float y = degree.y;
    float y = 0.0;
    vec3 position  = vec3(x,y,z);
    vec4 p = projection * view * vec4(position, 1);
    gl_Position = p; 
    gl_PointSize = 2.0;
    outColor=color;
  }`,
    attributes: {
      degree: ringList,
      color: ringColorList,
      offset: ringOffsetList,
    },
    primitive: "points",
    count: pointList.length,
    // elements: cubeElements,
    uniforms: {
      time: regl.prop("time"),
      dr: regl.prop("dr"),
      view: ({ tick }) => {
        // const t = 0.01 * tick;
        const t = 1;
        return mat4.lookAt(
          [],
          [5 * Math.cos(t), 2.5 * Math.sin(t), 5 * Math.sin(t)],
          [0, 0.0, 0],
          [0, 1, 0]
        );
      },
      projection: ({ viewportWidth, viewportHeight }) =>
        mat4.perspective(
          [],
          Math.PI / 4,
          viewportWidth / viewportHeight,
          0.01,
          10
        ),
    },
  });

  regl.frame(({ tick }) => {
    regl.clear({
      color: [0, 0, 0, 255],
      depth: 1,
    });
    drawCube({ time: tick });
    const dr = Math.sin(tick / 1000) * Math.PI * 2;
    drawRing({ time: tick, dr });
  });
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值