I am trying to render a lot of objects. It worked fine on 1 object, just not on multiple. It is causing some of the vertices not to be rendered when looking around to the right of the camera:
But when I look to the left of the camera, it works:
But in reality, it's in quadrants:
("[]" = working, "||" = not working)
[][][][]||||||||
[][][][]||||||||
[][][][]||||||||
[][][][]||||||||
||||||||||||||||
||||||||||||||||
||||||||||||||||
||||||||||||||||
and if I try to move my camera (Let's say down 3 left 1)
("[]" = working, "||" = not working)
[][][]||||||||||
[][][]||||||||||
[][][]||||||||||
[][][]||||||||||
[][][]||||||||||
[][][]||||||||||
[][][]||||||||||
||||||||||||||||
I have tried changing the "gl.cullFace(gl.BACK);
" function to gl.cullFace(gl.FRONT);
, but that doesn't help, neither does gl.cullFace(gl.FRONT_AND_BACK);
, but that causes the objects to disappear.
I use gl.drawElements();
to draw the elements, and, for the position buffer, I just add every vertex (X, Y, Z) by its position.
var x = 3;
var y = 4;
var z = 5;
var i = 0;
var verticies = Array.from([
// verticies
], e => {
var g = i % 3;
if (g == 0) {
e += x * (e * 2); // So you can just have x = 1, and x = 2 without clipping
} else if (g == 1) {
e += y * (e * 2);
} else if (g == 2) {
e += z * (e * 2);
}
i += 1;
return e;
})
Frame:
function frame() {
// gl.viewport(0, 0, width, height); // NOT NEEDED (I believe)
gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST);
// gl.cullFace(gl.BACK); // NOT NEEDED
gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(program);
return;
}
Here's my Mat4
and Camera
classes:
Mat4:
class Mat4 {
#mat = [
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
];
get Matrix() {
return this.#mat;
}
set(p, n) {
n = parseFloat(n);
p = parseInt(p);
if (isNaN(n)) {
console.error(`N must be a number.`);
return;
}
if (isNaN(p)) {
console.error(`P must be a number.`);
return;
}
if (p > 15 || p < 0) {
console.error(`P must be inbetween 0 and 15.`);
return;
}
this.#mat[p] = n;
}
translate(pos = new Vec3(0, 0, 0)) {
if (!(pos instanceof Vec3)) {
console.error(`Pos is not a Vec3.`);
return;
}
this.#mat[12] = this.#mat[0] * pos.x + this.#mat[4] * pos.y + this.#mat[8] * pos.z + this.#mat[12];
this.#mat[13] = this.#mat[1] * pos.x + this.#mat[5] * pos.y + this.#mat[9] * pos.z + this.#mat[13];
this.#mat[14] = this.#mat[2] * pos.x + this.#mat[6] * pos.y + this.#mat[10] * pos.z + this.#mat[14];
this.#mat[15] = this.#mat[3] * pos.x + this.#mat[7] * pos.y + this.#mat[11] * pos.z + this.#mat[15];
return;
}
rotateX(degree = 0) {
degree = parseInt(degree);
if (isNaN(degree)) {
console.error(`Degree is not a number.`);
return;
}
degree = degree * (Math.PI / 180);
var s = Math.sin(degree),
c = Math.cos(degree),
a10 = this.#mat[4],
a11 = this.#mat[5],
a12 = this.#mat[6],
a13 = this.#mat[7],
a20 = this.#mat[8],
a21 = this.#mat[9],
a22 = this.#mat[10],
a23 = this.#mat[11];
this.#mat[4] = a10 * c + a20 * s;
this.#mat[5] = a11 * c + a21 * s;
this.#mat[6] = a12 * c + a22 * s;
this.#mat[7] = a13 * c + a23 * s;
this.#mat[8] = a20 * c - a10 * s;
this.#mat[9] = a21 * c - a11 * s;
this.#mat[10] = a22 * c - a12 * s;
this.#mat[11] = a23 * c - a13 * s;
return;
}
rotateY(degree = 0) {
degree = parseInt(degree);
if (isNaN(degree)) {
console.error(`Degree is not a number.`);
return;
}
degree = degree * (Math.PI / 180);
var s = Math.sin(degree),
c = Math.cos(degree),
a00 = this.#mat[0],
a01 = this.#mat[1],
a02 = this.#mat[2],
a03 = this.#mat[3],
a20 = this.#mat[8],
a21 = this.#mat[9],
a22 = this.#mat[10],
a23 = this.#mat[11];
this.#mat[0] = a00 * c - a20 * s;
this.#mat[1] = a01 * c - a21 * s;
this.#mat[2] = a02 * c - a22 * s;
this.#mat[3] = a03 * c - a23 * s;
this.#mat[8] = a00 * s + a20 * c;
this.#mat[9] = a01 * s + a21 * c;
this.#mat[10] = a02 * s + a22 * c;
this.#mat[11] = a03 * s + a23 * c;
return;
}
rotateZ(degree = 0) {
degree = parseInt(degree);
if (isNaN(degree)) {
console.error(`Degree is not a number.`);
return;
}
degree = degree * (Math.PI / 180);
var s = Math.sin(degree),
c = Math.cos(degree),
a00 = this.#mat[0],
a01 = this.#mat[1],
a02 = this.#mat[2],
a03 = this.#mat[3],
a10 = this.#mat[4],
a11 = this.#mat[5],
a12 = this.#mat[6],
a13 = this.#mat[7];
this.#mat[0] = a00 * c + a10 * s;
this.#mat[1] = a01 * c + a11 * s;
this.#mat[2] = a02 * c + a12 * s;
this.#mat[3] = a03 * c + a13 * s;
this.#mat[4] = a10 * c - a00 * s;
this.#mat[5] = a11 * c - a01 * s;
this.#mat[6] = a12 * c - a02 * s;
this.#mat[7] = a13 * c - a03 * s;
return;
}
scale(scale = new Vec3(1, 1, 1)) {
if (!(scale instanceof Vec3)) {
console.error(`Scale is not a Vec3.`);
return;
}
this.#mat[0] *= scale.x;
this.#mat[1] *= scale.x;
this.#mat[2] *= scale.x;
this.#mat[3] *= scale.x;
this.#mat[4] *= scale.y;
this.#mat[5] *= scale.y;
this.#mat[6] *= scale.y;
this.#mat[7] *= scale.y;
this.#mat[8] *= scale.z;
this.#mat[9] *= scale.z;
this.#mat[10] *= scale.z;
this.#mat[11] *= scale.z;
return;
}
mul(matrix = new Mat4()) {
if (!(matrix instanceof Mat4)) {
console.error(`Matrix is not a Mat4.`);
return;
}
this.#mat[0] *= matrix.Matrix[0];
this.#mat[1] *= matrix.Matrix[1];
this.#mat[2] *= matrix.Matrix[2];
this.#mat[3] *= matrix.Matrix[3];
this.#mat[4] *= matrix.Matrix[4];
this.#mat[5] *= matrix.Matrix[5];
this.#mat[6] *= matrix.Matrix[6];
this.#mat[7] *= matrix.Matrix[7];
this.#mat[8] *= matrix.Matrix[8];
this.#mat[9] *= matrix.Matrix[9];
this.#mat[10] *= matrix.Matrix[10];
this.#mat[11] *= matrix.Matrix[11];
this.#mat[12] *= matrix.Matrix[12];
this.#mat[13] *= matrix.Matrix[13];
this.#mat[14] *= matrix.Matrix[14];
this.#mat[15] *= matrix.Matrix[15];
return;
}
div(matrix = new Mat4()) {
if (!(matrix instanceof Mat4)) {
console.error(`Matrix is not a Mat4.`);
return;
}
this.#mat[0] /= matrix.Matrix[0];
this.#mat[1] /= matrix.Matrix[1];
this.#mat[2] /= matrix.Matrix[2];
this.#mat[3] /= matrix.Matrix[3];
this.#mat[4] /= matrix.Matrix[4];
this.#mat[5] /= matrix.Matrix[5];
this.#mat[6] /= matrix.Matrix[6];
this.#mat[7] /= matrix.Matrix[7];
this.#mat[8] /= matrix.Matrix[8];
this.#mat[9] /= matrix.Matrix[9];
this.#mat[10] /= matrix.Matrix[10];
this.#mat[11] /= matrix.Matrix[11];
this.#mat[12] /= matrix.Matrix[12];
this.#mat[13] /= matrix.Matrix[13];
this.#mat[14] /= matrix.Matrix[14];
this.#mat[15] /= matrix.Matrix[15];
return;
}
sub(matrix = new Mat4()) {
if (!(matrix instanceof Mat4)) {
console.error(`Matrix is not a Mat4.`);
return;
}
this.#mat[0] -= matrix.Matrix[0];
this.#mat[1] -= matrix.Matrix[1];
this.#mat[2] -= matrix.Matrix[2];
this.#mat[3] -= matrix.Matrix[3];
this.#mat[4] -= matrix.Matrix[4];
this.#mat[5] -= matrix.Matrix[5];
this.#mat[6] -= matrix.Matrix[6];
this.#mat[7] -= matrix.Matrix[7];
this.#mat[8] -= matrix.Matrix[8];
this.#mat[9] -= matrix.Matrix[9];
this.#mat[10] -= matrix.Matrix[10];
this.#mat[11] -= matrix.Matrix[11];
this.#mat[12] -= matrix.Matrix[12];
this.#mat[13] -= matrix.Matrix[13];
this.#mat[14] -= matrix.Matrix[14];
this.#mat[15] -= matrix.Matrix[15];
return;
}
add(matrix = new Mat4()) {
if (!(matrix instanceof Mat4)) {
console.error(`Matrix is not a Mat4.`);
return;
}
this.#mat[0] += matrix.Matrix[0];
this.#mat[1] += matrix.Matrix[1];
this.#mat[2] += matrix.Matrix[2];
this.#mat[3] += matrix.Matrix[3];
this.#mat[4] += matrix.Matrix[4];
this.#mat[5] += matrix.Matrix[5];
this.#mat[6] += matrix.Matrix[6];
this.#mat[7] += matrix.Matrix[7];
this.#mat[8] += matrix.Matrix[8];
this.#mat[9] += matrix.Matrix[9];
this.#mat[10] += matrix.Matrix[10];
this.#mat[11] += matrix.Matrix[11];
this.#mat[12] += matrix.Matrix[12];
this.#mat[13] += matrix.Matrix[13];
this.#mat[14] += matrix.Matrix[14];
this.#mat[15] += matrix.Matrix[15];
return;
}
replace(matrix = new Mat4()) {
if (!(matrix instanceof Mat4)) {
console.error(`Matrix is not a Mat4.`);
return;
}
this.#mat = matrix.Matrix;
return;
}
invert() {
var a00 = this.#mat[0], a01 = this.#mat[1], a02 = this.#mat[2], a03 = this.#mat[3],
a10 = this.#mat[4], a11 = this.#mat[5], a12 = this.#mat[6], a13 = this.#mat[7],
a20 = this.#mat[8], a21 = this.#mat[9], a22 = this.#mat[10], a23 = this.#mat[11],
a30 = this.#mat[12], a31 = this.#mat[13], a32 = this.#mat[14], a33 = this.#mat[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32,
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
console.error(`Unable to invert matrix.`);
return;
}
det = 1.0 / det;
this.#mat[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
this.#mat[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
this.#mat[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
this.#mat[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
this.#mat[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
this.#mat[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
this.#mat[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
this.#mat[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
this.#mat[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
this.#mat[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
this.#mat[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
this.#mat[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
this.#mat[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
this.#mat[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
this.#mat[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
this.#mat[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
return;
}
reset() {
this.#mat = [
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
];
return;
}
constructor(pos = undefined) {
if (pos instanceof Vec3) {
this.translate(pos);
}
return;
}
}
Camera:
class Camera extends Mat4 {
#x = 0.0;
#y = 0.0;
#z = 0.0;
#cx = 0.0;
#cy = 0.0;
#cz = 0.0;
#pcx = 0.0;
#pcy = 0.0;
#pcz = 0.0;
#fov = 70.0;
#near = 0.0;
#far = 100.0;
get cx() {
return this.#cx;
}
get cy() {
return this.#cy;
}
get x() {
return this.#x;
}
get y() {
return this.#y;
}
get z() {
return this.#z;
}
camRotateX(deg) {
this.#cx += deg;
if (this.#cx < -90) {
this.#cx = -90;
} else if (this.#cx > 90) {
this.#cx = 90;
}
}
camRotateY(deg) {
this.#cy += deg;
}
camRotateZ(deg) {
this.#cz += deg;
}
camResetX(deg) {
this.#pcx = this.#cx;
this.#cx = deg;
}
camResetY(deg) {
this.#pcy = this.#cy;
this.#cy = deg;
}
camResetZ(deg) {
this.#pcz = this.#cz;
this.#cz = deg;
}
camSaveX() {
this.#pcx = this.#cx;
}
camSaveY() {
this.#pcy = this.#cy;
}
camSaveZ() {
this.#pcz = this.#cz;
}
camRestoreX() {
this.#cx = this.#pcx;
}
camRestoreY() {
this.#cy = this.#pcy;
}
camRestoreZ() {
this.#cz = this.#pcz;
}
camTranslate(pos = new Vec3(0, 0, 0)) {
this.#x += pos.x;
this.#y += pos.y;
this.#z += pos.z;
}
get camMatrix() {
this.calculate();
return this.Matrix;
}
camReset() {
var f = 1.0 / Math.tan(this.#fov / 2.0),
nf = 1.0 / (this.#near - this.#far);
this.set(0, f / (Minecraft.width / Minecraft.height));
this.set(1, 0.0);
this.set(2, 0.0);
this.set(3, 0.0);
this.set(4, 0.0);
this.set(5, f);
this.set(6, 0.0);
this.set(7, 0.0);
this.set(8, 0.0);
this.set(9, 0.0);
this.set(10, -(this.#far + this.#near) * nf);
this.set(11, -1.0);
this.set(12, 0.0);
this.set(13, 0.0);
this.set(14, -(2.0 * this.#far * this.#near) * nf);
this.set(15, 0.0);
return;
}
calculate() {
this.camReset();
this.rotateX(this.#cx);
this.rotateY(this.#cy);
this.rotateZ(this.#cz);
this.translate(new Vec3(this.#x, this.#y - 1.72, this.#z));
return;
}
constructor(pos = undefined, fov = 70.0, near = 0.0, far = 100.0) {
super();
fov = parseFloat(fov);
near = parseFloat(near);
far = parseFloat(far);
if (isNaN(fov)) {
console.warn(`Fov is NOT valid, setting to default.`);
fov = 70.0;
}
if (isNaN(near)) {
console.warn(`Near is NOT valid, setting to default.`);
near = 0.0;
}
if (isNaN(far)) {
console.warn(`Far is NOT valid, setting to default.`);
far = 100.0;
}
fov = fov * (Math.PI / 180);
var f = 1.0 / Math.tan(fov / 2.0),
nf = 1.0 / (near - far);
this.set(0, f / (Minecraft.width / Minecraft.height));
this.set(1, 0.0);
this.set(2, 0.0);
this.set(3, 0.0);
this.set(4, 0.0);
this.set(5, f);
this.set(6, 0.0);
this.set(7, 0.0);
this.set(8, 0.0);
this.set(9, 0.0);
this.set(10, -(far + near) * nf);
this.set(11, -1.0);
this.set(12, 0.0);
this.set(13, 0.0);
this.set(14, -(2.0 * far * near) * nf);
this.set(15, 0.0);
if (pos instanceof Vec3) {
this.#x = pos.x;
this.#y = pos.y;
this.#z = pos.z;
}
this.#far = far;
this.#near = near;
this.#fov = fov;
return;
}
}
Here's my Vertex Shader:
attribute vec3 position;
attribute vec3 normal;
attribute vec2 texcoord;
uniform mat4 model;
varying highp vec2 vtexcoord;
varying vec3 vnormal;
void main() {
gl_Position = model * vec4(position, 1.0);
vnormal = normal;
vtexcoord = texcoord;
}
Here's my Fragment Shader:
precision highp float;
varying vec3 vnormal;
varying highp vec2 vtexcoord;
uniform vec3 lightDir;
uniform sampler2D sampler;
void main(void) {
vec3 norm = normalize(vnormal);
float light = dot(lightDir, norm) * .5 + .5;
vec4 tex = texture2D(sampler, vtexcoord);
if (tex.a == 0.0) {
discard;
}
gl_FragColor = vec4(tex.rgb * light, tex.a);
}
My texture buffer vertices:
[
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
]
Here's my normal vertices:
[
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0
]
Here's my indices:
[
0, 1, 2, 0, 2, 3,
4, 5, 6, 4, 6, 7,
8, 9, 10, 8, 10, 11,
12, 13, 14, 12, 14, 15,
16, 17, 18, 16, 18, 19,
20, 21, 22, 20, 22, 23
]
Here's my position vertices:
[
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
]
Mat4 does not calculate their Perspective camera properly for my code to work with it, however, it does work correctly with the Orthographic camera, I worked it out, and converted it back to a Perspective camera.
class Camera extends Mat4 {
// ... Other code (See question)
camReset() {
var f = 1.0 / Math.tan(this.#fov / 2.0);
var nf = 1.0 / (this.#near - this.#far);
this.setMatrix([
f / (width / height), 0.0, 0.0, 0.0,
0.0, f, 0.0, 0.0,
0.0, 0.0, (this.#far - this.#near) * nf, -1.0,
0.0, 0.0, (this.#far + this.#near) * nf, 0.0
]); // -(this.#far + this.#near) * nf -> (this.#far - this.#near) * nf
}
// ... Other code (See question)
}