1 import { mat4
, vec3
} from 'gl-matrix';
2 import { System
} from '@serpentity/serpentity';
3 import Drawable
from '../nodes/drawable';
4 import Configurable
from '../nodes/configurable';
5 import Cameras
from '../nodes/cameras';
6 import { initializeShaderProgram
, initializeBuffers
} from '../webgl_utils';
9 kDefaultLineLength: 1000,
11 kCameraAngularVelocity: Math
.PI
/ 180,
12 kFieldOfView: 45, // degrees
17 kTargetVerticalResolution: 1024,
20 attribute vec4 aVertexPosition;
21 attribute vec4 aColor;
25 uniform mat4 uViewMatrix;
26 uniform mat4 uProjectionMatrix;
30 gl_Position = uProjectionMatrix * uViewMatrix * aVertexPosition;
32 gl_PointSize = 10.0; // Set the point size
38 precision mediump float;
43 gl_FragColor = vColor;
49 * Does all the WebGL rendering. I'm not super familiar with WebGL so I need
50 * to revisit this in a while and see how I would restructure this.
52 export default class WebGLRenderer
extends System
{
63 const { canvas
} = this;
64 window
.addEventListener('resize', () => this._resizeCanvas(canvas
));
67 const gl
= canvas
.getContext('webgl', {
68 preserveDrawingBuffer: true
72 gl
.clearColor(0.05882, 0.14902, 0.12157, 1);
73 gl
.enable(gl
.DEPTH_TEST
);
74 gl
.depthFunc(gl
.LEQUAL
);
76 this.colorBuffer
= gl
.createBuffer();
78 const shaderProgram
= initializeShaderProgram(
80 internals
.kVertexShader
,
81 internals
.kFragmentShader
85 program: shaderProgram
,
87 vertexPosition: gl
.getAttribLocation(shaderProgram
, 'aVertexPosition'),
88 vertexColor: gl
.getAttribLocation(shaderProgram
, 'aColor')
91 projectionMatrix: gl
.getUniformLocation(shaderProgram
, 'uProjectionMatrix'),
92 viewMatrix: gl
.getUniformLocation(shaderProgram
, 'uViewMatrix')
96 this.buffers
= initializeBuffers(gl
);
97 this._resizeCanvas(canvas
);
99 this.points
= engine
.getNodes(Drawable
);
103 this.configurations
= engine
.getNodes(Configurable
);
104 this.cameras
= engine
.getNodes(Cameras
);
111 delete this.colorBuffer
;
113 delete this.positions
;
115 delete this.configurations
;
121 const {gl
, programInfo
, buffers
} = this;
123 gl
.useProgram(programInfo
.program
);
125 gl
.clear(gl
.COLOR_BUFFER_BIT
| gl
.DEPTH_BUFFER_BIT
);
127 const fieldOfView
= internals
.kFieldOfView
* Math
.PI
/ 180;
128 const aspectRatio
= internals
.kWidthRatio
/ internals
.kHeightRatio
;
129 const projectionMatrix
= mat4
.create();
135 internals
.kNearLimit
,
140 programInfo
.uniformLocations
.projectionMatrix
,
145 // We only support one camera for now.
146 const camera
= this.cameras
.nodes
[0];
147 if (camera
!= undefined) {
148 const eye
= vec3
.fromValues(camera
.position
.x
, camera
.position
.y
, camera
.position
.z
);
149 const center
= vec3
.fromValues(0, 0, 0);
150 const up
= vec3
.fromValues(camera
.up
.x
, camera
.up
.y
, camera
.up
.z
);
151 const viewMatrix
= mat4
.create();
152 mat4
.lookAt(viewMatrix
, eye
, center
, up
);
154 programInfo
.uniformLocations
.viewMatrix
,
161 for (const point
of this.points
) {
162 this.positions
[i
] = this.positions
[i
] || [];
163 this.positions
[i
].push(point
.position
.x
, point
.position
.y
, point
.position
.z
, 1);
164 this.positions
[i
].push(
165 point
.position
.prevX
|| point
.position
.x
,
166 point
.position
.prevY
|| point
.position
.y
,
167 point
.position
.prevZ
|| point
.position
.z
,
170 point
.position
.prevX
= point
.position
.x
;
171 point
.position
.prevY
= point
.position
.y
;
172 point
.position
.prevZ
= point
.position
.z
;
174 this.colors
[i
] = this.colors
[i
] || [];
176 0.5 + point
.position
.z
/ 4 + point
.position
.x
/ 4,
177 0.5 + point
.position
.z
/ 4 + point
.position
.y
/ 4,
178 0.75 + point
.position
.z
/ 4, 1,
179 0.5 + point
.position
.prevZ
/ 4 + point
.position
.prevX
/ 4,
180 0.5 + point
.position
.prevZ
/ 4 + point
.position
.prevY
/ 4,
181 0.75 + point
.position
.prevZ
/ 4,1);
186 gl
.bindBuffer(gl
.ARRAY_BUFFER
, this.colorBuffer
);
187 const colors
= this.colors
.flat();
188 gl
.bufferData(gl
.ARRAY_BUFFER
,
189 new Float32Array(colors
),
193 const numberOfComponents
= 4;
194 const type
= gl
.FLOAT
;
195 const normalize
= false;
199 gl
.bindBuffer(gl
.ARRAY_BUFFER
, this.colorBuffer
);
200 gl
.vertexAttribPointer(
201 programInfo
.attribLocations
.vertexColor
,
208 gl
.enableVertexAttribArray(programInfo
.attribLocations
.vertexColor
);
211 gl
.bindBuffer(gl
.ARRAY_BUFFER
, buffers
.position
);
212 const positions
= this.positions
.flat();
213 gl
.bufferData(gl
.ARRAY_BUFFER
,
214 new Float32Array(positions
),
218 const numberOfComponents
= 4;
219 const type
= gl
.FLOAT
;
220 const normalize
= false;
224 gl
.bindBuffer(gl
.ARRAY_BUFFER
, buffers
.position
);
225 gl
.vertexAttribPointer(
226 programInfo
.attribLocations
.vertexPosition
,
233 gl
.enableVertexAttribArray(programInfo
.attribLocations
.vertexPosition
);
238 gl
.drawArrays(gl
.LINES
, 0, positions
.length
/ 4);
244 _resizeCanvas(canvas
) {
246 let width
= window
.innerWidth
;
247 let height
= Math
.round(width
* internals
.kHeightRatio
/ internals
.kWidthRatio
);
249 if (window
.innerHeight
< height
) {
250 height
= window
.innerHeight
;
251 width
= Math
.round(height
* internals
.kWidthRatio
/ internals
.kHeightRatio
);
254 canvas
.style
.width
= `${width}px`;
255 canvas
.style
.height
= `${height}px`;
257 canvas
.width
= internals
.kTargetVerticalResolution
* internals
.kWidthRatio
;
258 canvas
.height
= internals
.kTargetVerticalResolution
;
260 this.gl
.viewport(0, 0, canvas
.width
, canvas
.height
);
264 const lineLength
= this.configurations
.nodes
[0]?.configuration
.lineLength
|| internals
.kDefaultLineLength
;
266 for (const [i
, position
] of Object
.entries(this.positions
)) {
267 this.positions
[i
] = position
.slice(-lineLength
* 8);
270 for (const [i
, color
] of Object
.entries(this.colors
)) {
271 this.colors
[i
] = color
.slice(-lineLength
* 8);