Performance refactor

This commit is contained in:
Paul Mathieu 2021-12-15 12:00:10 -08:00
parent 80284baf2e
commit 7bc7b64c8b

146
index.js
View File

@ -53,7 +53,9 @@ void main() {
* @param {WebGLRenderingContext} gl * @param {WebGLRenderingContext} gl
*/ */
function draw(gl, params, objects) { function draw(gl, params, objects) {
gl.clearColor(0.6, 0.8, 1.0, 1.0); const skyColor = [0.6, 0.8, 1.0];
gl.clearColor(...skyColor, 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.LEQUAL);
@ -65,55 +67,32 @@ function draw(gl, params, objects) {
const camrot = params.camera.orientation; const camrot = params.camera.orientation;
const campos = params.camera.position; const campos = params.camera.position;
const viewMat = se3.product( const viewMatrix = se3.product(
se3.rotxyz(-camrot[0], -camrot[1], -camrot[2]), se3.rotxyz(-camrot[0], -camrot[1], -camrot[2]),
se3.translation(-campos[0], -campos[1], -campos[2]) se3.translation(-campos[0], -campos[1], -campos[2])
); );
for (const {program, texture, position, orientation, geometry} of objects) { let lastGlContext;
// load those ahead of time
const viewLoc = gl.getUniformLocation(program, 'uView');
const modelLoc = gl.getUniformLocation(program, 'uModel');
const projLoc = gl.getUniformLocation(program, 'uProjection');
const samplerLoc = gl.getUniformLocation(program, 'uSampler');
const fogColorLoc = gl.getUniformLocation(program, 'uFogColor');
const lightDirectionLoc = gl.getUniformLocation(program, 'uLightDirection');
const ambiantLoc = gl.getUniformLocation(program, 'uAmbiantLight');
const positionLoc = gl.getAttribLocation(program, 'aPosition'); for (const {glContext, position, orientation, geometry} of objects) {
const normalLoc = gl.getAttribLocation(program, 'aNormal'); if (glContext !== lastGlContext) {
const textureLoc = gl.getAttribLocation(program, 'aTextureCoord'); glContext.setupScene({
projectionMatrix: params.projMatrix,
viewMatrix,
fogColor: skyColor,
lightDirection: params.lightDirection,
ambiantLightAmount: params.ambiantLight,
});
}
//const mvMatrix = se3.product(se3.translation(...position), se3.rotxyz(...orientation)); lastGlContext = glContext;
const mvMatrix = se3.identity();
gl.useProgram(program); glContext.drawObject({
position,
gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMat)); orientation,
gl.uniformMatrix4fv(modelLoc, false, new Float32Array(mvMatrix)); glBuffer: geometry.glBuffer,
gl.uniformMatrix4fv(projLoc, false, new Float32Array(params.projMatrix)); numVertices: geometry.numVertices,
gl.uniform3f(fogColorLoc, 0.6, 0.8, 1.0); });
gl.uniform3f(lightDirectionLoc, ...params.lightDirection);
gl.uniform1f(ambiantLoc, params.ambiantLight);
gl.bindBuffer(gl.ARRAY_BUFFER, geometry.glBuffer);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(normalLoc, 3, gl.BYTE, true, 20, 12);
gl.enableVertexAttribArray(normalLoc);
gl.vertexAttribPointer(textureLoc, 2, gl.UNSIGNED_SHORT, true, 20, 16);
gl.enableVertexAttribArray(textureLoc);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.uniform1i(samplerLoc, 0);
gl.drawArrays(gl.TRIANGLES, 0, geometry.numVertices);
// gl.bindTexture(gl.TEXTURE_2D, null);
// gl.drawArrays(gl.LINE_STRIP, 0, geometry.numVertices);
} }
} }
@ -180,7 +159,7 @@ function handleKeys(params) {
}); });
} }
function getObjects(world, z, x, program, texture) { function getObjects(world, z, x, glContext) {
return world.chunks return world.chunks
.filter(chunk => { .filter(chunk => {
if (chunk.position.z < z - 8 * 16) return false; if (chunk.position.z < z - 8 * 16) return false;
@ -197,9 +176,8 @@ function getObjects(world, z, x, program, texture) {
.map(chunk => ({ .map(chunk => ({
position: [0.0, 0.0, 0.0], position: [0.0, 0.0, 0.0],
orientation: [0.0, 0.0, 0.0], orientation: [0.0, 0.0, 0.0],
program,
geometry: chunk.buffer, geometry: chunk.buffer,
texture, glContext,
})); }));
} }
@ -239,7 +217,7 @@ function tick(time, gl, params) {
} }
} }
const objects = getObjects(params.world, campos[2], campos[0], params.program, params.texture); const objects = getObjects(params.world, campos[2], campos[0], params.worldGl);
draw(gl, params, objects); draw(gl, params, objects);
const dt = (time - stuff.lastFrameTime) * 0.001; const dt = (time - stuff.lastFrameTime) * 0.001;
@ -324,6 +302,74 @@ function checkCollision(curPos, newPos, world) {
// [x] better controls // [x] better controls
// [ ] save the world (yay) to local storage (bah) // [ ] save the world (yay) to local storage (bah)
async function initWorldGl(gl) {
const program = makeProgram(gl, TEST_VSHADER, TEST_FSHADER);
const texture = await loadTexture(gl, 'texture.png');
// load those ahead of time
const viewLoc = gl.getUniformLocation(program, 'uView');
const modelLoc = gl.getUniformLocation(program, 'uModel');
const projLoc = gl.getUniformLocation(program, 'uProjection');
const samplerLoc = gl.getUniformLocation(program, 'uSampler');
const fogColorLoc = gl.getUniformLocation(program, 'uFogColor');
const lightDirectionLoc = gl.getUniformLocation(program, 'uLightDirection');
const ambiantLoc = gl.getUniformLocation(program, 'uAmbiantLight');
const positionLoc = gl.getAttribLocation(program, 'aPosition');
const normalLoc = gl.getAttribLocation(program, 'aNormal');
const textureLoc = gl.getAttribLocation(program, 'aTextureCoord');
const setupScene = (sceneParams) => {
const {
projectionMatrix,
viewMatrix,
fogColor,
lightDirection,
ambiantLightAmount,
} = sceneParams;
gl.useProgram(program);
gl.uniformMatrix4fv(projLoc, false, new Float32Array(projectionMatrix));
gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMatrix));
gl.uniform3fv(fogColorLoc, fogColor);
gl.uniform3fv(lightDirectionLoc, lightDirection);
gl.uniform1f(ambiantLoc, ambiantLightAmount);
// doing this here because it's the same for all world stuff
gl.uniformMatrix4fv(modelLoc, false, new Float32Array(se3.identity()));
gl.uniform1i(samplerLoc, 0);
};
const drawObject = (objectParams) => {
const {
glBuffer,
numVertices,
} = objectParams;
gl.bindBuffer(gl.ARRAY_BUFFER, glBuffer);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 20, 0);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(normalLoc, 3, gl.BYTE, true, 20, 12);
gl.enableVertexAttribArray(normalLoc);
gl.vertexAttribPointer(textureLoc, 2, gl.UNSIGNED_SHORT, true, 20, 16);
gl.enableVertexAttribArray(textureLoc);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.drawArrays(gl.TRIANGLES, 0, numVertices);
};
return {
setupScene,
drawObject,
};
}
async function main() { async function main() {
const canvas = document.querySelector('#game'); const canvas = document.querySelector('#game');
const gl = canvas.getContext('webgl'); const gl = canvas.getContext('webgl');
@ -333,8 +379,7 @@ async function main() {
return; return;
} }
const program = makeProgram(gl, TEST_VSHADER, TEST_FSHADER); const worldGl = await initWorldGl(gl);
const texture = await loadTexture(gl, 'texture.png');
const params = { const params = {
projMatrix: se3.perspective(Math.PI / 3, canvas.clientWidth / canvas.clientHeight, 0.1, 100.0), projMatrix: se3.perspective(Math.PI / 3, canvas.clientWidth / canvas.clientHeight, 0.1, 100.0),
@ -345,12 +390,11 @@ async function main() {
}, },
keys: new Set(), keys: new Set(),
world: makeWorld(), world: makeWorld(),
texture,
program,
lightDirection: [-0.2, -0.5, 0.4], lightDirection: [-0.2, -0.5, 0.4],
ambiantLight: 0.7, ambiantLight: 0.7,
flying: false, flying: false,
isOnGround: false, isOnGround: false,
worldGl,
} }
document.querySelector('#lightx').oninput = e => { document.querySelector('#lightx').oninput = e => {