This commit is contained in:
Tristan Daniël Maat 2022-08-09 00:40:27 +01:00
parent ced10cc09f
commit 615217b237
Signed by: tlater
GPG key ID: 49670FD774E43268
4 changed files with 74 additions and 19 deletions

View file

@ -36,7 +36,7 @@ document.addEventListener("DOMContentLoaded", () => {
// Get the containing <span> element // Get the containing <span> element
const block = flash.parentNode; const block = flash.parentNode;
// flash.parentNode.parentNode.removeChild(block); flash.parentNode.parentNode.removeChild(block);
} }
}); });
}); });

View file

@ -5,19 +5,22 @@ import { Cube } from "./cube";
import vertexSource from "./vertices.glsl"; import vertexSource from "./vertices.glsl";
import fragmentSource from "./fragments.glsl"; import fragmentSource from "./fragments.glsl";
const ROTATION_SPEED = 0.0005;
class RendererError extends Error {} class RendererError extends Error {}
class Renderer { class Renderer {
private canvas: HTMLCanvasElement; private canvas: HTMLCanvasElement;
private analyser: AnalyserNode; private analyser: AnalyserNode;
private analyserData: Float32Array; private analyserData: Uint8Array;
private time: number; private time: number;
private buffers: { private buffers: {
indices?: WebGLBuffer; indices?: WebGLBuffer;
positions?: WebGLBuffer; positions?: WebGLBuffer;
normals?: WebGLBuffer; normals?: WebGLBuffer;
fft?: WebGLBuffer;
}; };
constructor( constructor(
@ -32,10 +35,10 @@ class Renderer {
this.canvas = canvas; this.canvas = canvas;
this.analyser = analyser; this.analyser = analyser;
this.analyserData = new Float32Array(analyser.frequencyBinCount); this.analyserData = new Uint8Array(analyser.frequencyBinCount);
this.time = 0; this.time = 0;
this.buffers = { indices: undefined, positions: undefined }; this.buffers = {};
} }
resize() { resize() {
@ -56,6 +59,7 @@ class Renderer {
.addShader(fragmentSource, gl.FRAGMENT_SHADER) .addShader(fragmentSource, gl.FRAGMENT_SHADER)
.addAttribute("aVertexPosition") .addAttribute("aVertexPosition")
.addAttribute("aVertexNormal") .addAttribute("aVertexNormal")
.addAttribute("aHeight")
.addUniforms("uProjectionMatrix") .addUniforms("uProjectionMatrix")
.addUniforms("uModelViewMatrix") .addUniforms("uModelViewMatrix")
.addUniforms("uNormalMatrix") .addUniforms("uNormalMatrix")
@ -67,6 +71,11 @@ class Renderer {
} }
initBuffers(gl: WebGLRenderingContext) { initBuffers(gl: WebGLRenderingContext) {
// Scale down the unit cube before we use it
Cube.vertices = Cube.vertices.map(
(num: number) => num / this.analyser.frequencyBinCount
);
// Position buffer // Position buffer
const positionBuffer = gl.createBuffer(); const positionBuffer = gl.createBuffer();
@ -99,6 +108,17 @@ class Renderer {
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, Cube.normals, gl.STATIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, Cube.normals, gl.STATIC_DRAW);
this.buffers.normals = normalBuffer; this.buffers.normals = normalBuffer;
// fft data buffer
const fftBuffer = gl.createBuffer();
if (fftBuffer === null) {
throw new Error("could not initialize fft buffer");
}
// No need to initialize this buffer here since we will be
// updating it as soon as we start rendering anyway.
this.buffers.fft = fftBuffer;
} }
initGL(gl: WebGLRenderingContext, shader: Shader) { initGL(gl: WebGLRenderingContext, shader: Shader) {
@ -106,7 +126,7 @@ class Renderer {
gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0); gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST); gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL); gl.depthFunc(gl.LESS);
} }
updateMatrices(gl: WebGLRenderingContext, shader: Shader) { updateMatrices(gl: WebGLRenderingContext, shader: Shader) {
@ -125,13 +145,14 @@ class Renderer {
); );
const modelViewMatrix = mat4.create(); const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [0.0, 1.0, -8.0]); mat4.translate(modelViewMatrix, modelViewMatrix, [0.0, 0.0, -1.5]);
mat4.rotateY(modelViewMatrix, modelViewMatrix, this.time / 1000); mat4.rotateX(modelViewMatrix, modelViewMatrix, Math.PI / 6);
mat4.rotateX( mat4.rotateY(
modelViewMatrix, modelViewMatrix,
modelViewMatrix, modelViewMatrix,
(this.time / 1000) * 0.7 this.time * ROTATION_SPEED
); );
mat4.translate(modelViewMatrix, modelViewMatrix, [-1.0, 0.0, 0.0]);
gl.uniformMatrix4fv( gl.uniformMatrix4fv(
shader.getUniform("uModelViewMatrix"), shader.getUniform("uModelViewMatrix"),
false, false,
@ -152,7 +173,8 @@ class Renderer {
if ( if (
this.buffers.indices === undefined || this.buffers.indices === undefined ||
this.buffers.positions === undefined || this.buffers.positions === undefined ||
this.buffers.normals === undefined this.buffers.normals === undefined ||
this.buffers.fft === undefined
) { ) {
throw new Error("failed to create buffers before rendering"); throw new Error("failed to create buffers before rendering");
} }
@ -184,8 +206,30 @@ class Renderer {
); );
gl.enableVertexAttribArray(shader.getAttribute("aVertexNormal")); gl.enableVertexAttribArray(shader.getAttribute("aVertexNormal"));
// Update fft
this.analyser.getByteFrequencyData(this.analyserData);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers.fft);
gl.bufferData(gl.ARRAY_BUFFER, this.analyserData, gl.STREAM_DRAW);
gl.vertexAttribPointer(
shader.getAttribute("aHeight"),
1,
gl.UNSIGNED_BYTE,
false,
0,
0
);
gl.vertexAttribDivisor(shader.getAttribute("aHeight"), 1);
gl.enableVertexAttribArray(shader.getAttribute("aHeight"));
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElementsInstanced(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0, 2); gl.drawElementsInstanced(
gl.TRIANGLES,
36,
gl.UNSIGNED_SHORT,
0,
this.analyser.frequencyBinCount
);
requestAnimationFrame((time) => { requestAnimationFrame((time) => {
this.time = time; this.time = time;

View file

@ -2,7 +2,7 @@
precision highp float; precision highp float;
flat in vec3 vColor; flat in vec4 vColor;
out vec4 color; out vec4 color;
void main() { color = vec4(vColor, 1.0); } void main() { color = vColor; }

View file

@ -9,21 +9,32 @@ precision highp float;
layout(location = 0) in vec4 aVertexPosition; layout(location = 0) in vec4 aVertexPosition;
layout(location = 1) in vec3 aVertexNormal; layout(location = 1) in vec3 aVertexNormal;
flat out vec3 vColor; layout(location = 2) in float aHeight;
flat out vec4 vColor;
uniform mat4 uModelViewMatrix; uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix; uniform mat4 uProjectionMatrix;
uniform mat4 uNormalMatrix; uniform mat4 uNormalMatrix;
void main() { void main() {
vec4 instancePosition = float instanceX =
vec4(float(gl_InstanceID) * aVertexPosition.x + aVertexPosition.x, aVertexPosition.x + float(gl_InstanceID) * 2.0 * abs(aVertexPosition.x);
aVertexPosition.yzw); float vertexY =
gl_Position = uProjectionMatrix * uModelViewMatrix * instancePosition; aVertexPosition.y > 0.0 ? aVertexPosition.y * aHeight : aVertexPosition.y;
gl_Position = uProjectionMatrix * uModelViewMatrix *
vec4(instanceX, vertexY, aVertexPosition.zw);
vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0); vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);
float directionalLight = float directionalLight =
max(dot(transformedNormal.xyz, LIGHT_DIRECTION), 0.0); max(dot(transformedNormal.xyz, LIGHT_DIRECTION), 0.0);
vColor = AMBIENT_LIGHT + (directionalLight * LIGHT_COLOR); if (aHeight == 0.0) {
vColor = vec4(0.0, 0.0, 0.0, 0.0);
} else {
vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);
float directionalLight =
max(dot(transformedNormal.xyz, LIGHT_DIRECTION), 0.0);
vColor = vec4(AMBIENT_LIGHT + (directionalLight * LIGHT_COLOR), 1.0);
}
} }