From 30cf48cd70f1c52f89362245891be355af110afe Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Wed, 18 Jan 2023 22:43:02 -0500 Subject: [PATCH] cube --- public/cube.js | 57 ++++++++ public/gl/core/Camera.js | 18 +++ public/gl/core/Entity.js | 25 ++++ public/gl/core/Material.js | 46 +++++++ public/{js/buffer.js => gl/core/Mesh.js} | 28 ++-- public/gl/core/Renderer.js | 79 ++++++++++++ public/gl/core/Scene.js | 38 ++++++ public/gl/core/Shader.js | 98 ++++++++++++++ public/gl/gl.js | 20 +++ public/{js => gl/io}/file.js | 5 +- public/gl/math/Mat4.js | 157 +++++++++++++++++++++++ public/gl/math/Vec2.js | 78 +++++++++++ public/gl/math/Vec3.js | 88 +++++++++++++ public/index.html | 21 ++- public/js/gl.js | 38 ------ public/js/shader.js | 50 -------- public/shader/simple.vert | 8 +- public/test.js | 36 ++++++ 18 files changed, 772 insertions(+), 118 deletions(-) create mode 100644 public/cube.js create mode 100644 public/gl/core/Camera.js create mode 100644 public/gl/core/Entity.js create mode 100644 public/gl/core/Material.js rename public/{js/buffer.js => gl/core/Mesh.js} (58%) create mode 100644 public/gl/core/Renderer.js create mode 100644 public/gl/core/Scene.js create mode 100644 public/gl/core/Shader.js create mode 100644 public/gl/gl.js rename public/{js => gl/io}/file.js (70%) create mode 100644 public/gl/math/Mat4.js create mode 100644 public/gl/math/Vec2.js create mode 100644 public/gl/math/Vec3.js delete mode 100644 public/js/gl.js delete mode 100644 public/js/shader.js create mode 100644 public/test.js diff --git a/public/cube.js b/public/cube.js new file mode 100644 index 0000000..5e4b258 --- /dev/null +++ b/public/cube.js @@ -0,0 +1,57 @@ +export const gen_cube = () => { + var cube_data = [ + -1.0, 1.0, -1.0, 0.5, 0.5, 0.5, + -1.0, 1.0, 1.0, 0.5, 0.5, 0.5, + 1.0, 1.0, 1.0, 0.5, 0.5, 0.5, + 1.0, 1.0, -1.0, 0.5, 0.5, 0.5, + -1.0, 1.0, 1.0, 0.75, 0.25, 0.5, + -1.0, -1.0, 1.0, 0.75, 0.25, 0.5, + -1.0, -1.0, -1.0, 0.75, 0.25, 0.5, + -1.0, 1.0, -1.0, 0.75, 0.25, 0.5, + 1.0, 1.0, 1.0, 0.25, 0.25, 0.75, + 1.0, -1.0, 1.0, 0.25, 0.25, 0.75, + 1.0, -1.0, -1.0, 0.25, 0.25, 0.75, + 1.0, 1.0, -1.0, 0.25, 0.25, 0.75, + 1.0, 1.0, 1.0, 1.0, 0.0, 0.15, + 1.0, -1.0, 1.0, 1.0, 0.0, 0.15, + -1.0, -1.0, 1.0, 1.0, 0.0, 0.15, + -1.0, 1.0, 1.0, 1.0, 0.0, 0.15, + 1.0, 1.0, -1.0, 0.0, 1.0, 0.15, + 1.0, -1.0, -1.0, 0.0, 1.0, 0.15, + -1.0, -1.0, -1.0, 0.0, 1.0, 0.15, + -1.0, 1.0, -1.0, 0.0, 1.0, 0.15, + -1.0, -1.0, -1.0, 0.5, 0.5, 1.0, + -1.0, -1.0, 1.0, 0.5, 0.5, 1.0, + 1.0, -1.0, 1.0, 0.5, 0.5, 1.0, + 1.0, -1.0, -1.0, 0.5, 0.5, 1.0, + ]; + + var cube_indicies = [ + 0, 1, 2, + 0, 2, 3, + 5, 4, 6, + 6, 4, 7, + 8, 9, 10, + 8, 10, 11, + 13, 12, 14, + 15, 14, 12, + 16, 17, 18, + 16, 18, 19, + 21, 20, 22, + 22, 20, 23 + ]; + + var cube_verticies = [] + var cube_colors = [] + for (let x = 0; x < cube_indicies.length; x++) { + var i = cube_indicies[x] + cube_verticies.push(cube_data[i * 6 + 0]) + cube_verticies.push(cube_data[i * 6 + 1]) + cube_verticies.push(cube_data[i * 6 + 2]) + cube_colors.push(cube_data[i * 6 + 3]) + cube_colors.push(cube_data[i * 6 + 4]) + cube_colors.push(cube_data[i * 6 + 5]) + } + + return [cube_verticies, cube_colors, cube_indicies.length] +} \ No newline at end of file diff --git a/public/gl/core/Camera.js b/public/gl/core/Camera.js new file mode 100644 index 0000000..870c13f --- /dev/null +++ b/public/gl/core/Camera.js @@ -0,0 +1,18 @@ +import { Vec3 } from '../math/Vec3.js' +import { Mat4 } from '../math/Mat4.js' + +export class Camera { + + constructor() { + this.position = new Vec3() + this.rotation = new Vec3() + } + + view() { + return new Mat4() + .identity() + .rot(this.rotation.clone().multS(Math.PI/180)) + .pos(this.position.clone().multS(-1)) + } + +} \ No newline at end of file diff --git a/public/gl/core/Entity.js b/public/gl/core/Entity.js new file mode 100644 index 0000000..d0d6e4a --- /dev/null +++ b/public/gl/core/Entity.js @@ -0,0 +1,25 @@ +import { Vec3 } from '../math/Vec3.js' +import { Mat4 } from '../math/Mat4.js' + +export class Entity { + + static #id = 0 + + constructor(mesh) { + this.mesh = mesh + this.position = new Vec3() + this.rotation = new Vec3() + this.scale = new Vec3(1, 1, 1) + this.id = Entity.#id + Entity.#id++ + } + + tran() { + return new Mat4() + .identity() + .pos(this.position) + .rot(this.rotation.clone().multS(Math.PI/180)) + .scale(this.scale) + } + +} \ No newline at end of file diff --git a/public/gl/core/Material.js b/public/gl/core/Material.js new file mode 100644 index 0000000..c99b9e8 --- /dev/null +++ b/public/gl/core/Material.js @@ -0,0 +1,46 @@ +export class Material { + + static #id = 0 + + constructor(shader, data = {}) { + this.shader = shader + this.data = data + this.id = Material.#id + Material.#id++ + } + + set(data) { + this.data = data + return this + } + + bind() { + this.shader.start() + for (const key in this.data) { + const value = this.data[key] + if (typeof value == 'number' && !isNaN(x)) { + if (Number.isInteger(value)) { + this.shader.loadInt(key, value) + } else { + this.shader.loadFloat(key, value) + } + } else if (typeof value == 'boolean') { + this.shader.loadBool(key, value) + } else if (typeof value == 'object') { + const name = value.constructor.name + if (name == 'Vec2') { + this.shader.loadVec2(key, value) + } else if (name == 'Vec3') { + this.shader.loadVec3(key,value) + } else if (name == 'Mat4') { + this.shader.loadMat4(key, value) + } + } + } + } + + unbind() { + this.shader.stop() + } + +} \ No newline at end of file diff --git a/public/js/buffer.js b/public/gl/core/Mesh.js similarity index 58% rename from public/js/buffer.js rename to public/gl/core/Mesh.js index 15da457..b35c13c 100644 --- a/public/js/buffer.js +++ b/public/gl/core/Mesh.js @@ -1,20 +1,20 @@ -const Buffer = {} +import { gl, ext } from './Renderer.js' -let vaos = [] -let vbos = [] - -class Mesh { +export class Mesh { static #vaos = [] static #vbos = [] - #count = 0 + #vertexCount + #count + #id constructor(vertexCount) { - this.id = gl.createVertexArray() - gl.bindVertexArray(this.id) - Mesh.#vaos.push(this.id) - this.vertexCount = vertexCount + this.#id = ext.createVertexArrayOES() + ext.bindVertexArrayOES(this.#id) + Mesh.#vaos.push(this.#id) + this.#vertexCount = vertexCount + this.#count = 0 } store(data, dim) { @@ -34,11 +34,15 @@ class Mesh { } bind() { - gl.bindVertexArray(this.id) + ext.bindVertexArrayOES(this.#id) } unbind() { - gl.bindVertexArray(null) + ext.bindVertexArrayOES(null) + } + + draw() { + gl.drawArrays(gl.TRIANGLES, 0, this.#vertexCount) } } \ No newline at end of file diff --git a/public/gl/core/Renderer.js b/public/gl/core/Renderer.js new file mode 100644 index 0000000..32f5e9c --- /dev/null +++ b/public/gl/core/Renderer.js @@ -0,0 +1,79 @@ +import { Mat4 } from '../math/Mat4.js' + +export var gl +export var ext +export var canvas + +export class Renderer { + constructor() { + canvas = document.createElement("canvas") + canvas.id = "canvas" + canvas.width = window.innerWidth + canvas.height = window.innerHeight + canvas.style = "display: block;" + document.body.appendChild(canvas) + document.body.style.margin = 0 + + gl = canvas.getContext('webgl') + + if(!gl) { + console.log("Your browser does not support webgl") + return + } + + ext = gl.getExtension('OES_vertex_array_object'); + if(!ext) { + console.log("Your browser does not support webgl 2") + return + } + + window.onresize = (event) => { + canvas.width = window.innerWidth + canvas.height = window.innerHeight + gl.viewport(0, 0, canvas.width, canvas.height) + } + } + + draw(scene, camera) { + for (const material_id in scene.map) { + const material = scene.materials[material_id] + gl.enable(gl.DEPTH_TEST); + gl.enable(gl.CULL_FACE); + gl.cullFace(gl.BACK); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.clearColor(0, 0, 0, 1); + material.bind() + material.shader.loadMat4("proj", this.proj()) + material.shader.loadMat4("view", camera.view()) + scene.map[material_id].forEach((entity_id) => { + const entity = scene.entities[entity_id] + material.shader.loadMat4("tran", entity.tran()) + entity.mesh.bind() + entity.mesh.draw() + entity.mesh.unbind() + }) + material.unbind() + } + } + + proj() { + const fov = 90 + const far = 100 + const near = 0.1 + + const aspect = canvas.width / canvas.height + const f = 1.0 / Math.tan((fov * (Math.PI/180)) / 2) + const fa = f / aspect + const nf = 1.0 / (near - far) + + const c1 = (near + far) * nf + const c2 = near * far * nf * 2 + + return new Mat4().set( + fa, 0, 0, 0, + 0, f, 0, 0, + 0, 0, c1, c2, + 0, 0, -1, 0 + ) + } +} \ No newline at end of file diff --git a/public/gl/core/Scene.js b/public/gl/core/Scene.js new file mode 100644 index 0000000..568fe37 --- /dev/null +++ b/public/gl/core/Scene.js @@ -0,0 +1,38 @@ +export class Scene { + + constructor() { + this.map = {} + this.entities = {} + this.materials = {} + } + + add(material, entity) { + var arr = this.map[material.id] + if (arr == undefined) { + arr = [] + this.materials[material.id] = material + } + if (!arr.includes(entity.id)) { + arr.push(entity.id) + this.entities[entity.id] = entity + } + this.map[material.id] = arr + } + + remove(material, entity) { + var arr = this.objects[material.id] + if (arr == undefined) { + return + } + const i = arr.indexOf(entity.id) + if(i > -1) { + arr = arr.splice(i, 1) + delete this.entities[entity.id] + if(arr.length < 1) { + delete this.map[material.id] + delete this.materials[material.id] + } + } + } + +} \ No newline at end of file diff --git a/public/gl/core/Shader.js b/public/gl/core/Shader.js new file mode 100644 index 0000000..f5e0a88 --- /dev/null +++ b/public/gl/core/Shader.js @@ -0,0 +1,98 @@ +import { gl } from './Renderer.js' + +export class Shader { + + #vertexShader; + #fragmentShader; + #program; + #attributes; + #uniforms; + + constructor(vertexCode, fragmentCode) { + + this.#vertexShader = gl.createShader(gl.VERTEX_SHADER) + this.#fragmentShader = gl.createShader(gl.FRAGMENT_SHADER) + + gl.shaderSource(this.#vertexShader, vertexCode) + gl.shaderSource(this.#fragmentShader, fragmentCode) + + gl.compileShader(this.#vertexShader) + if (!gl.getShaderParameter(this.#vertexShader, gl.COMPILE_STATUS)) { + console.error('Failed to compile vertex shader!', gl.getShaderInfoLog(this.#vertexShader)) + return + } + + gl.compileShader(this.#fragmentShader) + if (!gl.getShaderParameter(this.#fragmentShader, gl.COMPILE_STATUS)) { + console.error('Failed to compile fragment shader!', gl.getShaderInfoLog(this.#fragmentShader)) + return + } + + this.#program = gl.createProgram() + gl.attachShader(this.#program, this.#vertexShader) + gl.attachShader(this.#program, this.#fragmentShader) + gl.linkProgram(this.#program) + if (!gl.getProgramParameter(this.#program, gl.LINK_STATUS)) { + console.error("Failed to link shader program!", gl.getProgramInfoLog(this.#program)); + return + } + + gl.validateProgram(this.#program); + if (!gl.getProgramParameter(this.#program, gl.VALIDATE_STATUS)) { + console.error("Failed to validate shader program!", gl.getProgramInfoLog(this.#program)); + return + } + + this.#attributes = [] + this.#uniforms = {} + + vertexCode.split('\n').forEach((line) => { + const tokens = line.split(" ") + if (tokens.length != 3) return + if (tokens[0] === "attribute") { + this.#attributes.push(tokens[2].replace(/\s+/g, '').split(';')[0]) + } + if (tokens[0] == "uniform") { + const loc = gl.getUniformLocation(this.#program, tokens[2].replace(/\s+/g, '').split(';')[0]) + this.#uniforms[tokens[2].replace(/\s+/g, '').split(';')[0]] = loc + } + }) + + } + + start() { + gl.useProgram(this.#program) + for (let i = 0; i < this.#attributes.length; i++) { + gl.bindAttribLocation(this.#program, i, this.#attributes[i]) + } + } + + stop() { + gl.useProgram(null) + } + + loadFloat(name, float) { + gl.uniform1f(this.#uniforms[name], float) + } + + loadInt(name, int) { + gl.uniform1i(this.#uniforms[name], int) + } + + loadVec2(name, v) { + gl.uniform2f(this.#uniforms[name], v.x, v.y) + } + + loadVec3(name, v) { + gl.uniform3f(this.#uniforms[name], v.x, v.y, v.z) + } + + loadMat4(name, m) { + gl.uniformMatrix4fv(this.#uniforms[name], gl.FALSE, new Float32Array(m.get())) + } + + loadBool(name, bool) { + gl.uniform1f(this.#uniforms[name], bool ? 1 : 0) + } + +} \ No newline at end of file diff --git a/public/gl/gl.js b/public/gl/gl.js new file mode 100644 index 0000000..20b6225 --- /dev/null +++ b/public/gl/gl.js @@ -0,0 +1,20 @@ +export { Camera } from './core/Camera.js' +export { Entity } from './core/Entity.js' +export { Material } from './core/Material.js' +export { Mesh } from './core/Mesh.js' +export { Renderer } from './core/Renderer.js' +export { Scene } from './core/Scene.js' +export { Shader } from './core/Shader.js' +export { readFileAsync } from './io/file.js' +export { Mat4 } from './math/Mat4.js' +export { Vec2 } from './math/Vec2.js' +export { Vec3 } from './math/Vec3.js' +export { Loop } + +const Loop = (fn) => { + const callback = () => { + fn() + window.requestAnimationFrame(callback) + } + callback() +} \ No newline at end of file diff --git a/public/js/file.js b/public/gl/io/file.js similarity index 70% rename from public/js/file.js rename to public/gl/io/file.js index 7675abb..f89565c 100644 --- a/public/js/file.js +++ b/public/gl/io/file.js @@ -1,6 +1,6 @@ -const File = {} +export { readFileAsync } -File.read = async (path) => { +const readFileAsync = async (path) => { try { let data = await fetch(path) let text = await data.text() @@ -8,5 +8,4 @@ File.read = async (path) => { } catch (err) { return undefined } - } \ No newline at end of file diff --git a/public/gl/math/Mat4.js b/public/gl/math/Mat4.js new file mode 100644 index 0000000..a342c0a --- /dev/null +++ b/public/gl/math/Mat4.js @@ -0,0 +1,157 @@ +export class Mat4 { + + constructor() { + this.data = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ] + } + + set(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { + const d = this.data + d[0] = m00; d[1] = m01; d[2] = m02; d[3] = m03; + d[4] = m10; d[5] = m11; d[6] = m12; d[7] = m13; + d[8] = m20; d[9] = m21; d[10] = m22; d[11] = m23; + d[12] = m30; d[13] = m31; d[14] = m32; d[15] = m33; + return this + } + + clone() { + return new Mat4().arr(this.da) + } + + arr(arr, offset = 0) { + for(let i = 0; i < 16; i++) { + this.data[i] = arr[i + offset] + } + return this + } + + identity() { + this.set( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ) + return this + } + + copy(m) { + const d = this.data + const o = m.data + d[0] = o[0]; d[1] = o[1]; d[2] = o[2]; d[3] = o[3]; + d[4] = o[4]; d[5] = o[5]; d[6] = o[6]; d[7] = o[7]; + d[8] = o[8]; d[9] = o[9]; d[10] = o[10]; d[11] = o[11]; + d[12] = o[12]; d[13] = o[13]; d[14] = o[14]; d[15] = o[15]; + return this + } + + mult(v) { + return this.multmat(this.clone(), v) + } + + premult(v) { + return this.multmat(v, this.clone()) + } + + multmat(ma, mb) { + const a = ma.data; + const b = mb.data + const d = this.data; + + const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; + const a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; + const a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; + const a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; + + const b00 = b[0], b01 = b[1], b02 = b[2], b03 = a[3]; + const b10 = b[4], b11 = b[5], b12 = b[6], b13 = a[7]; + const b20 = b[8], b21 = b[9], b22 = b[10], b23 = a[11]; + const b30 = b[12], b31 = b[13], b32 = b[14], b33 = a[15]; + + d[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30; + d[1] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31; + d[2] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32; + d[3] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33; + + d[4] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30; + d[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31; + d[6] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32; + d[7] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33; + + d[8] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30; + d[9] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31; + d[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32; + d[11] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33; + + d[12] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30; + d[13] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31; + d[14] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32; + d[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33; + + return this; + } + + pos(v) { + const d = this.data + + const m30 = d[0] * v.x + d[4] * v.y + d[8] * v.z; + const m31 = d[1] * v.x + d[5] * v.y + d[9] * v.z; + const m32 = d[2] * v.x + d[6] * v.y + d[10] * v.z; + const m33 = d[3] * v.x + d[7] * v.y + d[11] * v.z; + + d[3] += m30; + d[7] += m31; + d[11] += m32; + d[15] += m33; + return this; + } + + rot(v) { + const da = this.data; + const c3 = Math.cos(v.z) + const s3 = Math.sin(v.z) + const c2 = Math.cos(v.x) + const s2 = Math.sin(v.x) + const c1 = Math.cos(v.y) + const s1 = Math.sin(v.y) + + da[0] = c1 * c3 + s1 * s2 * s3 + da[4] = c2 * s3 + da[8] = c1 * s2 * s3 - c3 * s1 + + da[1] = c3 * s1 * s2 - c1 * s3 + da[5] = c2 * c3 + da[9] = c1 * c3 * s2 + s1 * s3 + + da[2] = c2 * s1 + da[6] = -s2 + da[10] = c1 * c2 + + return this + } + + scale( v ) { + const d = this.data; + + d[0] *= v.x; d[1] *= v.y; d[2] *= v.z; + d[4] *= v.x; d[5] *= v.y; d[6] *= v.z; + d[8] *= v.x; d[9] *= v.y; d[10] *= v.z; + d[12] *= v.x; d[13] *= v.y; d[14] *= v.z; + + return this; + } + + get() { + const d = this.data + return [ + d[0], d[4], d[8], d[12], + d[1], d[5], d[9], d[13], + d[2], d[6], d[10], d[14], + d[3], d[7], d[11], d[15] + ] + } +} \ No newline at end of file diff --git a/public/gl/math/Vec2.js b/public/gl/math/Vec2.js new file mode 100644 index 0000000..6156e40 --- /dev/null +++ b/public/gl/math/Vec2.js @@ -0,0 +1,78 @@ +export class Vec2 { + + constructor(x = 0, y = 0) { + this.x = x + this.y = y + } + + set(x,y) { + this.x = x + this.y = y + return this + } + + clone() { + return new Vec2(this.x, this.y) + } + + add(v) { + this.x += v.x + this.y += v.y + return this + } + + sub(v) { + this.x -= v.x + this.y -= v.y + return this + } + + copy(v) { + this.x = v.x + this.y = v.y + return this + } + + multV(v) { + this.x *= v.x + this.y *= v.y + return this + } + + multS(s) { + this.x *= s + this.y *= s + return this + } + + divV(v) { + this.x *= (1 / v.x) + this.y *= (1 / v.y) + return this + } + + divS(s) { + this.x *= (1 / s) + this.y *= (1 / s) + return this + } + + invert() { + this.x = this.x == 0 ? 0 : (1 / this.x) + this.y = this.y == 0 ? 0 : (1 / this.y) + return this + } + + normalize() { + return this.divS(this.length() || 1) + } + + dot(v) { + return this.x * v.x + this.y * v.y; + } + + length() { + return Math.sqrt(this.x * this.x + this.y * this.y); + } + +} \ No newline at end of file diff --git a/public/gl/math/Vec3.js b/public/gl/math/Vec3.js new file mode 100644 index 0000000..d77d49d --- /dev/null +++ b/public/gl/math/Vec3.js @@ -0,0 +1,88 @@ +export class Vec3 { + + constructor(x = 0, y = 0, z = 0) { + this.x = x + this.y = y + this.z = z + } + + set(x,y,z) { + this.x = x + this.y = y + this.z = z + return this + } + + clone() { + return new Vec3(this.x, this.y, this.z) + } + + add(v) { + this.x += v.x + this.y += v.y + this.x += v.x + return this + } + + sub(v) { + this.x -= v.x + this.y -= v.y + this.x -= v.z + return this + } + + copy(v) { + this.x = v.x + this.y = v.y + this.z = v.z + return this + } + + multV(v) { + this.x *= v.x + this.y *= v.y + this.z *= v.z + return this + } + + multS(s) { + this.x *= s + this.y *= s + this.z *= s + return this + } + + divV(v) { + this.x *= (1 / v.x) + this.y *= (1 / v.y) + this.z *= (1 / v.z) + return this + } + + divS(s) { + this.x *= (1 / s) + this.y *= (1 / s) + this.z *= (1 / s) + return this + } + + invert() { + this.x = this.x == 0 ? 0 : (1 / this.x) + this.y = this.y == 0 ? 0 : (1 / this.y) + this.z = this.z == 0 ? 0 : (1 / this.z) + return this + } + + normalize() { + return this.divS(this.length() || 1) + } + + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + } + + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + +} \ No newline at end of file diff --git a/public/index.html b/public/index.html index a5719fe..b5cc309 100644 --- a/public/index.html +++ b/public/index.html @@ -1,16 +1,11 @@ - - - welgl - - - - Your browser does not support NTML5 - - - - - - + + + welgl + + + + + \ No newline at end of file diff --git a/public/js/gl.js b/public/js/gl.js deleted file mode 100644 index 0863bf8..0000000 --- a/public/js/gl.js +++ /dev/null @@ -1,38 +0,0 @@ -var gl; - -async function main() { - const canvas = document.getElementById("canvas") - gl = canvas.getContext('webgl') - - if(!gl) { - console.log("Your browser does not support webgl") - return - } - - var ext = gl.getExtension('OES_vertex_array_object'); - if(!ext) { - console.log("Your browser does not support webgl 2") - return - } - - - - gl['createVertexArray'] = function() { return ext['createVertexArrayOES'](); }; - gl['deleteVertexArray'] = function(vao) { ext['deleteVertexArrayOES'](vao); }; - gl['bindVertexArray'] = function(vao) { ext['bindVertexArrayOES'](vao); }; - gl['isVertexArray'] = function(vao) { return ext['isVertexArrayOES'](vao); }; - - var shader = await Shader.load("shader/simple.vert","shader/simple.frag") - - var triangle = new Mesh(3) - .store([0.0, 0.5, -0.5, -0.5, 0.5, -0.5], 2) - .store([1.0, 1.0, 0.0, 0.7, 0.0, 1.0, 0.1, 1.0, 0.6], 3) - .finish() - - gl.useProgram(shader) - triangle.bind() - gl.drawArrays(gl.TRIANGLES, 0, triangle.vertexCount) - -} - -main() \ No newline at end of file diff --git a/public/js/shader.js b/public/js/shader.js deleted file mode 100644 index 28a8843..0000000 --- a/public/js/shader.js +++ /dev/null @@ -1,50 +0,0 @@ -const Shader = {} - -Shader.load = async (vertexPath, fragmentPath) => { - let vertexCode = await File.read(vertexPath) - if(!vertexCode) { - console.log("Invalid shader path:", vertexPath) - return - } - - let fragmentCode = await File.read(fragmentPath) - if(!fragmentCode) { - console.log("Invalid shader path:", fragmentPath) - return - } - - var vertexShader = gl.createShader(gl.VERTEX_SHADER) - var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER) - - gl.shaderSource(vertexShader, vertexCode) - gl.shaderSource(fragmentShader, fragmentCode) - - gl.compileShader(vertexShader) - if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { - console.error('Failed to compile ' + vertexPath + '!', gl.getShaderInfoLog(vertexShader)) - return - } - - gl.compileShader(fragmentShader) - if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { - console.error('Failed to compile ' + fragmentPath + '!', gl.getShaderInfoLog(fragmentShader)) - return - } - - var program = gl.createProgram() - gl.attachShader(program, vertexShader) - gl.attachShader(program, fragmentShader) - gl.linkProgram(program) - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - console.error("Failed to link shader program!", gl.getProgramInfoLog(program)); - return - } - - gl.validateProgram(program); - if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) { - console.error("Failed to validate shader program!", gl.getProgramInfoLog(program)); - return - } - - return program -} \ No newline at end of file diff --git a/public/shader/simple.vert b/public/shader/simple.vert index 801b91d..09db32e 100644 --- a/public/shader/simple.vert +++ b/public/shader/simple.vert @@ -1,11 +1,15 @@ precision mediump float; -attribute vec2 position; +attribute vec3 position; attribute vec3 color; +uniform mat4 proj; +uniform mat4 view; +uniform mat4 tran; + varying vec3 color_pass; void main() { color_pass = color; - gl_Position = vec4(position, 0.0, 1.0); + gl_Position = proj * view * tran * vec4(position, 1.0); } \ No newline at end of file diff --git a/public/test.js b/public/test.js new file mode 100644 index 0000000..65e059a --- /dev/null +++ b/public/test.js @@ -0,0 +1,36 @@ +import * as GL from '/gl/gl.js' +import { gen_cube } from './cube.js' + +async function main() { + + var Renderer = new GL.Renderer() + var Scene = new GL.Scene() + var Camera = new GL.Camera() + + var Shader = new GL.Shader( + await GL.readFileAsync("shader/simple.vert"), + await GL.readFileAsync("shader/simple.frag") + ) + + var Material = new GL.Material(Shader) + + var cube_data = gen_cube() + var Mesh = new GL.Mesh(cube_data[2]) + .store(cube_data[0], 3) + .store(cube_data[1], 3) + .finish() + + var Cube = new GL.Entity(Mesh) + Cube.position.z = -4; + + Scene.add(Material, Cube) + + const a = new GL.Vec3(1,1,1) + + GL.Loop(() => { + Renderer.draw(Scene, Camera) + Cube.rotation.add(a) + }); +} + +main() \ No newline at end of file