summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/cube.js57
-rw-r--r--public/gl/core/Camera.js18
-rw-r--r--public/gl/core/Entity.js25
-rw-r--r--public/gl/core/Material.js46
-rw-r--r--public/gl/core/Mesh.js (renamed from public/js/buffer.js)28
-rw-r--r--public/gl/core/Renderer.js79
-rw-r--r--public/gl/core/Scene.js38
-rw-r--r--public/gl/core/Shader.js98
-rw-r--r--public/gl/gl.js20
-rw-r--r--public/gl/io/file.js (renamed from public/js/file.js)5
-rw-r--r--public/gl/math/Mat4.js157
-rw-r--r--public/gl/math/Vec2.js78
-rw-r--r--public/gl/math/Vec3.js88
-rw-r--r--public/index.html21
-rw-r--r--public/js/gl.js38
-rw-r--r--public/js/shader.js50
-rw-r--r--public/shader/simple.vert8
-rw-r--r--public/test.js36
18 files changed, 772 insertions, 118 deletions
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
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
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 @@
<!DOCTYPE html>
<html lang="en">
-<head>
- <meta charset="UTF-8">
- <title>welgl</title>
-</head>
-<body>
- <canvas id="canvas">
- Your browser does not support NTML5
- </canvas>
- <script src="js/file.js"></script>
- <script src="js/shader.js"></script>
- <script src="js/buffer.js"></script>
- <script src="js/gl.js"></script>
-</body>
+ <head>
+ <meta charset="UTF-8">
+ <title>welgl</title>
+ <script type="module" src="gl/gl.js"></script>
+ </head>
+ <body>
+ <script type="module" src="test.js"></script>
+ </body>
</html> \ 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