Камера обычно смотрит вниз по оси -Z, поэтому для движения вперед вы просто добавляете ось Z камеры к своей позиции. Если вы не хотите перемещаться по вертикали, обнулите компонент Y и нормализуйте. Наконец, умножьте на желаемую скорость.
Ось x камеры содержит направление бокового движения, так что вы можете сделать то же самое для этого.
const cameraPosition = vec3.create();
const tempForwardDirection = vec3.create();
const tempSideDirection = vec3.create();
...
tempForwardDirection[0] = camera.matrix[8];
tempForwardDirection[1] = 0; // camera.matrix[9];
tempForwardDirection[2] = camera.matrix[10];
vec3.normalize(tempForwardDirection, tempForwardDirection)
tempSideDirection[0] = camera.matrix[0];
tempSideDirection[1] = camera.matrix[1];
tempSideDirection[2] = camera.matrix[2];
vec3.scaleAndAdd(
cameraPosition,
cameraPosition,
tempForwardDirection,
-fronBackMovement);
vec3.scaleAndAdd(
cameraPosition,
cameraPosition,
tempSideDirection,
sideMovement)
camera.matrix = mat4.fromTranslation(camera.matrix, cameraPosition);
camera.matrix = mat4.rotateY(camera.matrix,camera.matrix,rotateY);
let rotateY = 0; // For rotating along the Y axis
let fronBackMovement = 0; // Front and back movement
let sideMovement = 0; // Movement from side to side
const cameraPosition = vec3.create();
const tempForwardDirection = vec3.create();
const tempSideDirection = vec3.create();
const camera = {
matrix: mat4.create(),
};
const mouse = {
movementX: 0,
};
const gl = document.querySelector("canvas").getContext("webgl");
const vs = `
uniform mat4 u_worldViewProjection;
uniform mat4 u_worldInverseTranspose;
attribute vec4 position;
attribute vec3 normal;
varying vec3 v_normal;
void main() {
gl_Position = u_worldViewProjection * position;
v_normal = (u_worldInverseTranspose * vec4(normal, 0)).xyz;
}
`;
const fs = `
precision mediump float;
varying vec3 v_normal;
uniform vec3 u_lightDir;
uniform vec4 u_color;
void main() {
vec3 norm = normalize(v_normal);
float light = dot(u_lightDir, norm) * .5 + .5;
gl_FragColor = vec4(u_color.rgb * light, u_color.a);
}
`;
const progInfo = twgl.createProgramInfo(gl, [vs, fs]);
const bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 1);
const projection = mat4.create();
const view = mat4.create();
const viewProjection = mat4.create();
const world = mat4.create();
const worldViewProjection = mat4.create();
const worldInverse = mat4.create();
const worldInverseTranspose = mat4.create();
const fov = degToRad(90);
const zNear = 0.1;
const zFar = 100;
const lightDir = vec3.normalize(vec3.create(), [1, 2, 3]);
const key = {};
let px = 0;
let py = 0;
let pz = 0;
let elev = 0;
let ang = 0;
let roll = 0;
const speed = 1;
const turnSpeed = 90;
let then = 0;
function render(now) {
now *= 0.001; // seconds;
const deltaTime = now - then;
then = now;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.useProgram(progInfo.program);
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
mat4.perspective(projection, fov, aspect, zNear, zFar);
fronBackMovement = 0;
sideMovement = 0;
if( key.w == true ){
fronBackMovement = 5 * deltaTime;
}
if( key.a == true ){
sideMovement = -5 * deltaTime;
}
if( key.s == true ){
fronBackMovement = -5 * deltaTime;
}
if( key.d == true ){
sideMovement = 5 * deltaTime;
}
// Rotation
if( mouse.movementX != 0 ){
rotateY += mouse.movementX / 200; // mouse.movementX is screen movement of the cursor
mouse.movementX = 0;
}
tempForwardDirection[0] = camera.matrix[8];
tempForwardDirection[1] = 0; // camera.matrix[9];
tempForwardDirection[2] = camera.matrix[10];
vec3.normalize(tempForwardDirection, tempForwardDirection)
tempSideDirection[0] = camera.matrix[0];
tempSideDirection[1] = camera.matrix[1];
tempSideDirection[2] = camera.matrix[2];
vec3.scaleAndAdd(
cameraPosition,
cameraPosition,
tempForwardDirection,
-fronBackMovement);
vec3.scaleAndAdd(
cameraPosition,
cameraPosition,
tempSideDirection,
sideMovement)
camera.matrix = mat4.fromTranslation(camera.matrix, cameraPosition);
camera.matrix = mat4.rotateY(camera.matrix,camera.matrix,rotateY);
mat4.invert(view, camera.matrix);
mat4.multiply(viewProjection, projection, view);
for (let z = -1; z <= 1; ++z) {
for (let y = -1; y <= 1; ++y) {
for (let x = -1; x <= 1; ++x) {
if (x === 0 && y === 0 && z === 0) {
continue;
}
mat4.identity(world);
mat4.translate(world, world, [x * 3, y * 3, z * 3]);
mat4.multiply(worldViewProjection, viewProjection, world);
mat4.invert(worldInverse, world);
mat4.transpose(worldInverseTranspose, worldInverse);
twgl.setBuffersAndAttributes(gl, progInfo, bufferInfo);
twgl.setUniforms(progInfo, {
u_worldViewProjection: worldViewProjection,
u_worldInverseTranspose: worldInverseTranspose,
u_color: [(x + 2) / 3, (y + 2) / 3, (z + 2) / 3, 1],
u_lightDir: lightDir,
});
twgl.drawBufferInfo(gl, bufferInfo);
}
}
}
requestAnimationFrame(render);
}
requestAnimationFrame(render);
window.addEventListener('keydown', (e) => {
key[e.key] = true;
e.preventDefault();
});
window.addEventListener('keyup', (e) => {
key[e.key] = false;
e.preventDefault();
});
window.addEventListener('mousemove', (e) => {
mouse.movementX = e.movementX;
});
function degToRad(d) {
return d * Math.PI / 180;
}
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
pre { position: absolute; left: 1em; top: 0; }
A = left
D = right
W = forward
S = down