Вот решение, чтобы получить полуслучайный цвет для каждой частицы для каждого кадра - измените свой fragmentShaderSource
на ниже:
const fragmentShaderSource = `
precision lowp float;
uniform float uWobble;
void main() {
float r = fract(sin(uWobble*10000.0*gl_FragCoord.z));
float g = fract(cos(uWobble*10000.0*gl_FragCoord.z)*43758.5453);
float b = fract(cos(uWobble*10000.0*gl_FragCoord.z)*12.9898);
gl_FragColor = vec4(r, g, b, 1.7);
}
`;
Рабочий пример здесь на скрипке (для простотыизменить) или ниже:
'use strict';
const triangleCount = 2e5;
const antialias = true;
const generateTriangles = (count, width, height) => {
const coords = new Float32Array(9 * count);
for (var i = 0; i < coords.length;) {
const x = Math.random() * 2 - 1;
const y = Math.random() * 2 - 1;
const z = Math.random() * 2 - 1;
const theta = Math.random() * Math.PI;
const ax = 10 * Math.cos(theta) / width;
const ay = 10 * Math.sin(theta) / height;
const bx = 10 * Math.cos(theta + 0.1) / width;
const by = 10 * Math.sin(theta + 0.1) / height;
coords[i++] = x + ax;
coords[i++] = y + ay;
coords[i++] = z;
coords[i++] = x + bx;
coords[i++] = y + by;
coords[i++] = z;
coords[i++] = x - ax;
coords[i++] = y - ay;
coords[i++] = z;
coords[i++] = x - ax;
coords[i++] = y - ay;
coords[i++] = z;
coords[i++] = x - bx;
coords[i++] = y - by;
coords[i++] = z;
coords[i++] = x + ax;
coords[i++] = y + ay;
coords[i++] = z;
}
return coords;
};
const vertexShaderSource = `
precision lowp float;
attribute vec3 aPosition;
uniform float uWobble;
void main() {
float p = 0.1 / (0.3 * aPosition.z - 0.14 + 0.1 * uWobble);
gl_Position = vec4(p * aPosition.x, p * aPosition.y, aPosition.z, 1);
}
`;
const fragmentShaderSource = `
precision lowp float;
uniform float uWobble;
void main() {
float r = fract(sin(uWobble*10000.0*gl_FragCoord.z));
float g = fract(cos(uWobble*10000.0*gl_FragCoord.z)*43758.5453);
float b = fract(cos(uWobble*10000.0*gl_FragCoord.z)*12.9898);
gl_FragColor = vec4(r, g, b, 1.7);
}
`;
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const gl = canvas.getContext('webgl', {
alpha: false,
antialias
});
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
const aVertexPosition = gl.getAttribLocation(program, 'aPosition');
gl.enableVertexAttribArray(aVertexPosition);
const uWobble = gl.getUniformLocation(program, 'uWobble');
gl.uniform1f(uWobble, 1);
const vertices = generateTriangles(triangleCount, canvas.width, canvas.height);
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
const render = (timestamp) => {
requestAnimationFrame(render);
gl.uniform1f(uWobble, Math.sin(0.00002 * timestamp));
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
};
window.requestAnimationFrame(render);
html,
body {
background: #000;
height: 100%;
margin: 0;
}
canvas {
width: 1280px;
height: 720px;
position: absolute;
margin: auto;
top: 0;
right: 0;
left: 0;
bottom: 0;
}