原文链接: webgl 彩色点大小颜色变化的随机飞舞
上一篇: webgl 贝塞尔多彩线
矩形的大小, 颜色都是随机变化的 ,轨迹是生成好的贝塞尔曲线
主要是每次修改后需要重新绘制
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>