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
*/
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.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
@ -65,55 +67,32 @@ function draw(gl, params, objects) {
const camrot = params.camera.orientation;
const campos = params.camera.position;
const viewMat = se3.product(
const viewMatrix = se3.product(
se3.rotxyz(-camrot[0], -camrot[1], -camrot[2]),
se3.translation(-campos[0], -campos[1], -campos[2])
);
for (const {program, texture, position, orientation, geometry} of objects) {
// 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');
let lastGlContext;
const positionLoc = gl.getAttribLocation(program, 'aPosition');
const normalLoc = gl.getAttribLocation(program, 'aNormal');
const textureLoc = gl.getAttribLocation(program, 'aTextureCoord');
for (const {glContext, position, orientation, geometry} of objects) {
if (glContext !== lastGlContext) {
glContext.setupScene({
projectionMatrix: params.projMatrix,
viewMatrix,
fogColor: skyColor,
lightDirection: params.lightDirection,
ambiantLightAmount: params.ambiantLight,
});
}
//const mvMatrix = se3.product(se3.translation(...position), se3.rotxyz(...orientation));
const mvMatrix = se3.identity();
lastGlContext = glContext;
gl.useProgram(program);
gl.uniformMatrix4fv(viewLoc, false, new Float32Array(viewMat));
gl.uniformMatrix4fv(modelLoc, false, new Float32Array(mvMatrix));
gl.uniformMatrix4fv(projLoc, false, new Float32Array(params.projMatrix));
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);
glContext.drawObject({
position,
orientation,
glBuffer: geometry.glBuffer,
numVertices: 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
.filter(chunk => {
if (chunk.position.z < z - 8 * 16) return false;
@ -197,9 +176,8 @@ function getObjects(world, z, x, program, texture) {
.map(chunk => ({
position: [0.0, 0.0, 0.0],
orientation: [0.0, 0.0, 0.0],
program,
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);
const dt = (time - stuff.lastFrameTime) * 0.001;
@ -324,6 +302,74 @@ function checkCollision(curPos, newPos, world) {
// [x] better controls
// [ ] 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() {
const canvas = document.querySelector('#game');
const gl = canvas.getContext('webgl');
@ -333,8 +379,7 @@ async function main() {
return;
}
const program = makeProgram(gl, TEST_VSHADER, TEST_FSHADER);
const texture = await loadTexture(gl, 'texture.png');
const worldGl = await initWorldGl(gl);
const params = {
projMatrix: se3.perspective(Math.PI / 3, canvas.clientWidth / canvas.clientHeight, 0.1, 100.0),
@ -345,12 +390,11 @@ async function main() {
},
keys: new Set(),
world: makeWorld(),
texture,
program,
lightDirection: [-0.2, -0.5, 0.4],
ambiantLight: 0.7,
flying: false,
isOnGround: false,
worldGl,
}
document.querySelector('#lightx').oninput = e => {