webgl 彩色点大小颜色变化的随机飞舞

本文介绍如何使用WebGL创建一个效果,其中彩色的点在画布上以随机大小和颜色变化的方式沿着预设的贝塞尔曲线轨迹飞舞。重点在于每次更新时重新绘制场景来实现动态效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接: webgl 彩色点大小颜色变化的随机飞舞

上一篇: webgl 贝塞尔多彩线

下一篇: 简单模拟 vectorize-text 效果

矩形的大小, 颜色都是随机变化的 ,轨迹是生成好的贝塞尔曲线

主要是每次修改后需要重新绘制

up-4bdb0ea9216a4a7b5db523be310053cb054.png

precision mediump float;  
varying vec4 outVsColor;
void main() {
    gl_FragColor = outVsColor;
}

attribute vec4 aVsPosition;
attribute vec4 aVsColor;
attribute float aVsSize;
varying vec4 outVsColor;
void main(){
    gl_PointSize = aVsSize;
    gl_Position = aVsPosition;
    outVsColor = aVsColor;
}
<template>
  <div class="flex-row">
    <div>gl001 绘制点 动画</div>
    <canvas id="gl"></canvas>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, render } from "vue";
import { initShaderProgram, clearGL } from "../common";
import { randomColor, randomInt } from "../../../utils";
import fsSouce from "./fs.glsl";
import vsSource from "./vs.glsl";
import { Bezier } from "bezier-js";
const width = 600;
const height = 600;
const length = 100;
const bezList = Array(length)
  .fill(0)
  .map(
    () =>
      new Bezier(
        randomInt(-width, width),
        randomInt(-height, height),
        randomInt(-width, width),
        randomInt(-height, height),
        randomInt(-width, width),
        randomInt(-height, height)
      )
  );
console.log("bezList", bezList);
onMounted(() => {
  const canvas = document.getElementById("gl")! as HTMLCanvasElement;
  canvas.width = width;
  canvas.height = height;
  const gl = canvas.getContext("webgl2", {
    alpha: true,
    depth: true,
    antialias: true,
  })!;
  clearGL(gl, width, height, [1, 0, 0, 1]);
  const shaderProgram = initShaderProgram(gl, vsSource, fsSouce);
  console.log("shaderProgram", shaderProgram);
  gl.useProgram(shaderProgram);
  const programInfo = {
    program: shaderProgram,
    attribLocations: {
      aVsPosition: gl.getAttribLocation(shaderProgram, "aVsPosition"),
      aVsColor: gl.getAttribLocation(shaderProgram, "aVsColor"),
      aVsSize: gl.getAttribLocation(shaderProgram, "aVsSize"),
      // vertexColor: gl.getAttribLocation(shaderProgram, "aVertexColor"),
    },
    uniformLocations: {
      uFsColor: gl.getUniformLocation(shaderProgram, "uFsColor"),
      uVsColor: gl.getUniformLocation(shaderProgram, "uVsColor"),
      modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"),
    },
  };
  let now = 0;
  const draw = (
    points: Float32Array,
    colors: Float32Array,
    sizes: Float32Array,
    length: number
  ) => {
    // console.log("colors", colors);
    // 创建缓冲区
    const vertexBuffer = gl.createBuffer();
    // 绑定缓冲区
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    // 向缓冲区写入数据
    gl.bufferData(gl.ARRAY_BUFFER, points, gl.DYNAMIC_DRAW);
    // 分配缓冲区至指定着色器变量地址
    gl.vertexAttribPointer(
      programInfo.attribLocations.aVsPosition,
      3,
      gl.FLOAT,
      false,
      0,
      0
    );
    // 连接地址
    gl.enableVertexAttribArray(programInfo.attribLocations.aVsPosition);

    // 创建缓冲区
    const colorBuffer = gl.createBuffer();
    // 绑定缓冲区
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    // 向缓冲区写入数据
    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.DYNAMIC_DRAW);
    // 分配缓冲区至指定着色器变量地址
    gl.vertexAttribPointer(
      programInfo.attribLocations.aVsColor,
      4,
      gl.FLOAT,
      false,
      0,
      0
    );
    // 连接地址
    gl.enableVertexAttribArray(programInfo.attribLocations.aVsColor);

    // 创建缓冲区
    const sizeBuffer = gl.createBuffer();
    // 绑定缓冲区
    gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
    // 向缓冲区写入数据
    gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.DYNAMIC_DRAW);
    // 分配缓冲区至指定着色器变量地址
    gl.vertexAttribPointer(
      programInfo.attribLocations.aVsSize,
      1,
      gl.FLOAT,
      false,
      0,
      0
    );
    // 连接地址
    gl.enableVertexAttribArray(programInfo.attribLocations.aVsSize);

    // gl.uniform4fv(programInfo.uniformLocations.uFsColor, [0.0, 1.0, 1.0, 1.0]);
    // 设置颜色缓冲区清空颜色
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    // 清空颜色缓冲区
    gl.clear(gl.COLOR_BUFFER_BIT);
    // 由于dx不支持线宽设置 https://stackoverflow.com/questions/28009734/webgl-line-strip-width
    // gl.lineWidth(2);
    // 需要使用矩形代替
    gl.drawArrays(gl.POINTS, 0, length);
  };
  const raf = (f: Function) => setTimeout(f, 10);
  const render = () => {
    const pointerList = bezList.map((i) => {
      const p = i.get(now);
      return [p.x / width, p.y / height, 0];
    });
    const points = new Float32Array(pointerList.flat());
    const colors = new Float32Array(
      // 使用三角形带的方式
      Array(length)
        .fill(0)
        .map(() => randomColor(true))
        .flat()
    );
    const sizes = new Float32Array(
      Array(length)
        .fill(0)
        .map(() => randomInt(2, 10))
        .flat()
    );
    draw(points, colors, sizes, length);
    now += 0.004;
    if (now >= 1) now = 0;
    raf(render);
  };
  raf(render);
});
</script>

<style></style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值