cube
This commit is contained in:
parent
a28e995202
commit
30cf48cd70
18 changed files with 772 additions and 118 deletions
57
public/cube.js
Normal file
57
public/cube.js
Normal file
|
@ -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]
|
||||||
|
}
|
18
public/gl/core/Camera.js
Normal file
18
public/gl/core/Camera.js
Normal file
|
@ -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))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
public/gl/core/Entity.js
Normal file
25
public/gl/core/Entity.js
Normal file
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
46
public/gl/core/Material.js
Normal file
46
public/gl/core/Material.js
Normal file
|
@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,20 +1,20 @@
|
||||||
const Buffer = {}
|
import { gl, ext } from './Renderer.js'
|
||||||
|
|
||||||
let vaos = []
|
export class Mesh {
|
||||||
let vbos = []
|
|
||||||
|
|
||||||
class Mesh {
|
|
||||||
|
|
||||||
static #vaos = []
|
static #vaos = []
|
||||||
static #vbos = []
|
static #vbos = []
|
||||||
|
|
||||||
#count = 0
|
#vertexCount
|
||||||
|
#count
|
||||||
|
#id
|
||||||
|
|
||||||
constructor(vertexCount) {
|
constructor(vertexCount) {
|
||||||
this.id = gl.createVertexArray()
|
this.#id = ext.createVertexArrayOES()
|
||||||
gl.bindVertexArray(this.id)
|
ext.bindVertexArrayOES(this.#id)
|
||||||
Mesh.#vaos.push(this.id)
|
Mesh.#vaos.push(this.#id)
|
||||||
this.vertexCount = vertexCount
|
this.#vertexCount = vertexCount
|
||||||
|
this.#count = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
store(data, dim) {
|
store(data, dim) {
|
||||||
|
@ -34,11 +34,15 @@ class Mesh {
|
||||||
}
|
}
|
||||||
|
|
||||||
bind() {
|
bind() {
|
||||||
gl.bindVertexArray(this.id)
|
ext.bindVertexArrayOES(this.#id)
|
||||||
}
|
}
|
||||||
|
|
||||||
unbind() {
|
unbind() {
|
||||||
gl.bindVertexArray(null)
|
ext.bindVertexArrayOES(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
gl.drawArrays(gl.TRIANGLES, 0, this.#vertexCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
79
public/gl/core/Renderer.js
Normal file
79
public/gl/core/Renderer.js
Normal file
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
38
public/gl/core/Scene.js
Normal file
38
public/gl/core/Scene.js
Normal file
|
@ -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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
98
public/gl/core/Shader.js
Normal file
98
public/gl/core/Shader.js
Normal file
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
public/gl/gl.js
Normal file
20
public/gl/gl.js
Normal file
|
@ -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()
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
const File = {}
|
export { readFileAsync }
|
||||||
|
|
||||||
File.read = async (path) => {
|
const readFileAsync = async (path) => {
|
||||||
try {
|
try {
|
||||||
let data = await fetch(path)
|
let data = await fetch(path)
|
||||||
let text = await data.text()
|
let text = await data.text()
|
||||||
|
@ -8,5 +8,4 @@ File.read = async (path) => {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
157
public/gl/math/Mat4.js
Normal file
157
public/gl/math/Mat4.js
Normal file
|
@ -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]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
78
public/gl/math/Vec2.js
Normal file
78
public/gl/math/Vec2.js
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
88
public/gl/math/Vec3.js
Normal file
88
public/gl/math/Vec3.js
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,14 +3,9 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>welgl</title>
|
<title>welgl</title>
|
||||||
|
<script type="module" src="gl/gl.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas id="canvas">
|
<script type="module" src="test.js"></script>
|
||||||
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>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -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()
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -1,11 +1,15 @@
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
attribute vec2 position;
|
attribute vec3 position;
|
||||||
attribute vec3 color;
|
attribute vec3 color;
|
||||||
|
|
||||||
|
uniform mat4 proj;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 tran;
|
||||||
|
|
||||||
varying vec3 color_pass;
|
varying vec3 color_pass;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
color_pass = color;
|
color_pass = color;
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = proj * view * tran * vec4(position, 1.0);
|
||||||
}
|
}
|
36
public/test.js
Normal file
36
public/test.js
Normal file
|
@ -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()
|
Loading…
Reference in a new issue