import { System } from '@serpentity/serpentity'; import Drawable from '../nodes/drawable'; import { initializeShaderProgram, initializeBuffers } from '../webgl_utils'; const internals = { kWidthRatio: 2.76, kHeightRatio: 1, kTargetVerticalResolution: 32 + Math.round(Math.random() * 1024), kVertexShader: ` attribute vec3 aVertexPosition; void main() { gl_Position = vec4(aVertexPosition.xy, 0.0, 1.0); gl_PointSize = 10.0; // Set the point size } `, kFragmentShader: ` precision mediump float; uniform vec4 uColor; void main() { gl_FragColor = uColor; } ` }; export default class WebGLRenderer extends System { constructor(canvasId) { super(); this.canvasId = canvasId; } added(engine){ // Set up canvas const canvas = document.getElementById(this.canvasId); window.addEventListener('resize', () => this._resizeCanvas(canvas)); // Set up WebGL const gl = canvas.getContext('webgl', { preserveDrawingBuffer: true }); this.gl = gl; const shaderProgram = initializeShaderProgram( gl, internals.kVertexShader, internals.kFragmentShader ); this.programInfo = { program: shaderProgram, attribLocations: { vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition') }, uniformLocations: { color: gl.getUniformLocation(shaderProgram, 'uColor') } }; this.buffers = initializeBuffers(gl); this._resizeCanvas(canvas); this.points = engine.getNodes(Drawable); } removed(engine){ this.points = undefined; } update(){ const {gl, programInfo, buffers} = this; gl.useProgram(programInfo.program); { const color = [1, 1, 1, 1]; gl.uniform4fv(programInfo.uniformLocations.color, color); } const positions = []; for (const point of this.points) { positions.push(point.position.x, point.position.y, point.position.z); positions.push( point.position.prevX || point.position.x, point.position.prevY || point.position.y, point.position.prevZ || point.position.z ); point.position.prevX = point.position.x; point.position.prevY = point.position.y; point.position.prevZ = point.position.z; } gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); { const numberOfComponents = 3; const type = gl.FLOAT; const normalize = false; const stride = 0; const offset = 0; gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position); gl.vertexAttribPointer( programInfo.attribLocations.vertexPosition, numberOfComponents, type, normalize, stride, offset ); gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition); } { gl.lineWidth(2); gl.drawArrays(gl.LINES, 0, this.points.nodes.length * 2); } } _resizeCanvas(canvas) { console.log('Resizing Canvas'); let width = window.innerWidth; let height = Math.round(width * internals.kHeightRatio / internals.kWidthRatio); if (window.innerHeight < height) { height = window.innerHeight; width = Math.round(height * internals.kWidthRatio / internals.kHeightRatio); console.log(width, height); } canvas.style.width = `${width}px`; canvas.style.height = `${height}px`; canvas.width = internals.kTargetVerticalResolution * internals.kWidthRatio; canvas.height = internals.kTargetVerticalResolution; this.gl.viewport(0, 0, canvas.width, canvas.height); } };