Simple GUI, Simple Skybox, fixed sequential model rendering warnings
9
assets/shaders/skybox.fs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
varying vec3 uv;
|
||||||
|
|
||||||
|
uniform samplerCube cubeMap;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = textureCube(cubeMap, uv);
|
||||||
|
}
|
13
assets/shaders/skybox.vs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
attribute vec3 aVertexPosition;
|
||||||
|
|
||||||
|
uniform mat4 uViewMatrix;
|
||||||
|
uniform mat4 uProjectionMatrix;
|
||||||
|
|
||||||
|
varying vec3 uv;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = uProjectionMatrix * uViewMatrix * vec4(aVertexPosition, 1.0);
|
||||||
|
uv = aVertexPosition;
|
||||||
|
}
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 46 KiB |
BIN
assets/textures/skybox/back.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
assets/textures/skybox/bottom.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/textures/skybox/front.png
Normal file
After Width: | Height: | Size: 991 KiB |
BIN
assets/textures/skybox/left.png
Normal file
After Width: | Height: | Size: 938 KiB |
BIN
assets/textures/skybox/right.png
Normal file
After Width: | Height: | Size: 1003 KiB |
BIN
assets/textures/skybox/top.png
Normal file
After Width: | Height: | Size: 342 KiB |
@ -23,6 +23,9 @@ class Camera extends Node {
|
|||||||
this.right = vec3.create()
|
this.right = vec3.create()
|
||||||
this.worldUp = vec3.fromValues(0.0, 1.0, 0.0)
|
this.worldUp = vec3.fromValues(0.0, 1.0, 0.0)
|
||||||
|
|
||||||
|
this.nearPlane = ZNEAR
|
||||||
|
this.farPlane = ZFAR
|
||||||
|
|
||||||
this.updateTransform()
|
this.updateTransform()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +102,7 @@ class Camera extends Node {
|
|||||||
|
|
||||||
updateProjection (gl) {
|
updateProjection (gl) {
|
||||||
let aspect = gl.canvas.width / gl.canvas.height
|
let aspect = gl.canvas.width / gl.canvas.height
|
||||||
mat4.perspective(this.projection, this.fov, aspect, ZNEAR, ZFAR)
|
mat4.perspective(this.projection, this.fov, aspect, this.nearPlane, this.farPlane)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the view matrix on-the-go
|
// Calculate the view matrix on-the-go
|
||||||
|
@ -224,6 +224,7 @@ class MeshInstance extends Node {
|
|||||||
// Draw the mesh
|
// Draw the mesh
|
||||||
this.mesh.prepare(gl, shader)
|
this.mesh.prepare(gl, shader)
|
||||||
this.mesh.draw(gl, shader)
|
this.mesh.draw(gl, shader)
|
||||||
|
this.mesh.postdraw(gl, shader)
|
||||||
|
|
||||||
// Draw children
|
// Draw children
|
||||||
super.draw(gl, shader)
|
super.draw(gl, shader)
|
||||||
|
106
src/engine/components/skybox/index.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import { Mesh } from '../../mesh'
|
||||||
|
import { Texture } from '../../mesh/material'
|
||||||
|
|
||||||
|
import { mat4 } from 'gl-matrix'
|
||||||
|
|
||||||
|
import Resource from '../../resource'
|
||||||
|
|
||||||
|
const FNAMES = ['right', 'left', 'top', 'bottom', 'back', 'front']
|
||||||
|
const SIZE = 500
|
||||||
|
|
||||||
|
class Skybox {
|
||||||
|
constructor (name, size = SIZE) {
|
||||||
|
this.name = name
|
||||||
|
this.size = size
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize (gl) {
|
||||||
|
await this.createTexture(gl)
|
||||||
|
this.createMesh(gl)
|
||||||
|
}
|
||||||
|
|
||||||
|
async createTexture (gl) {
|
||||||
|
let ready = []
|
||||||
|
for (let i in FNAMES) {
|
||||||
|
let real = this.name + '/' + FNAMES[i] + '.png'
|
||||||
|
let loaded = await Resource.loadImage(real)
|
||||||
|
ready[i] = loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
let imgCube = Texture.createTextureCubeMap(gl, ready)
|
||||||
|
this.cubemap = imgCube
|
||||||
|
}
|
||||||
|
|
||||||
|
createMesh (gl) {
|
||||||
|
const vertices = [
|
||||||
|
-this.size, this.size, -this.size,
|
||||||
|
-this.size, -this.size, -this.size,
|
||||||
|
this.size, -this.size, -this.size,
|
||||||
|
this.size, -this.size, -this.size,
|
||||||
|
this.size, this.size, -this.size,
|
||||||
|
-this.size, this.size, -this.size,
|
||||||
|
|
||||||
|
-this.size, -this.size, this.size,
|
||||||
|
-this.size, -this.size, -this.size,
|
||||||
|
-this.size, this.size, -this.size,
|
||||||
|
-this.size, this.size, -this.size,
|
||||||
|
-this.size, this.size, this.size,
|
||||||
|
-this.size, -this.size, this.size,
|
||||||
|
|
||||||
|
this.size, -this.size, -this.size,
|
||||||
|
this.size, -this.size, this.size,
|
||||||
|
this.size, this.size, this.size,
|
||||||
|
this.size, this.size, this.size,
|
||||||
|
this.size, this.size, -this.size,
|
||||||
|
this.size, -this.size, -this.size,
|
||||||
|
|
||||||
|
-this.size, -this.size, this.size,
|
||||||
|
-this.size, this.size, this.size,
|
||||||
|
this.size, this.size, this.size,
|
||||||
|
this.size, this.size, this.size,
|
||||||
|
this.size, -this.size, this.size,
|
||||||
|
-this.size, -this.size, this.size,
|
||||||
|
|
||||||
|
-this.size, this.size, -this.size,
|
||||||
|
this.size, this.size, -this.size,
|
||||||
|
this.size, this.size, this.size,
|
||||||
|
this.size, this.size, this.size,
|
||||||
|
-this.size, this.size, this.size,
|
||||||
|
-this.size, this.size, -this.size,
|
||||||
|
|
||||||
|
-this.size, -this.size, -this.size,
|
||||||
|
-this.size, -this.size, this.size,
|
||||||
|
this.size, -this.size, -this.size,
|
||||||
|
this.size, -this.size, -this.size,
|
||||||
|
-this.size, -this.size, this.size,
|
||||||
|
this.size, -this.size, this.size
|
||||||
|
]
|
||||||
|
this.mesh = Mesh.constructFromVertices(gl, vertices)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCamera (gl, shader, camera) {
|
||||||
|
const projloc = shader.getUniformLocation(gl, 'uProjectionMatrix')
|
||||||
|
const viewloc = shader.getUniformLocation(gl, 'uViewMatrix')
|
||||||
|
|
||||||
|
// Set translation to zero to prevent the skybox from moving in relation to the camera
|
||||||
|
let view = mat4.clone(camera.view)
|
||||||
|
view[12] = 0
|
||||||
|
view[13] = 0
|
||||||
|
view[14] = 0
|
||||||
|
|
||||||
|
gl.uniformMatrix4fv(projloc, false, camera.projection)
|
||||||
|
gl.uniformMatrix4fv(viewloc, false, view)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw (gl, shader, camera) {
|
||||||
|
camera && this.updateCamera(gl, shader, camera)
|
||||||
|
|
||||||
|
gl.activeTexture(gl.TEXTURE0)
|
||||||
|
gl.bindTexture(this.cubemap.type, this.cubemap.id)
|
||||||
|
this.mesh.prepare(gl, shader)
|
||||||
|
this.mesh.draw(gl, shader)
|
||||||
|
this.mesh.postdraw(gl, shader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Skybox }
|
@ -59,6 +59,7 @@ class Terrain extends Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, shader) {
|
draw (gl, shader) {
|
||||||
|
super.draw(gl, shader)
|
||||||
if (!this.mesh) return
|
if (!this.mesh) return
|
||||||
// Set model transform matrix uniform
|
// Set model transform matrix uniform
|
||||||
const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix')
|
const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix')
|
||||||
@ -66,8 +67,7 @@ class Terrain extends Node {
|
|||||||
|
|
||||||
this.mesh.prepare(gl, shader)
|
this.mesh.prepare(gl, shader)
|
||||||
this.mesh.draw(gl, shader)
|
this.mesh.draw(gl, shader)
|
||||||
|
this.mesh.postdraw(gl, shader)
|
||||||
super.draw(gl, shader)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +105,7 @@ class TerrainNode extends Node {
|
|||||||
|
|
||||||
this.mesh.prepare(gl, shader)
|
this.mesh.prepare(gl, shader)
|
||||||
this.mesh.draw(gl, shader)
|
this.mesh.draw(gl, shader)
|
||||||
|
this.mesh.postdraw(gl, shader)
|
||||||
}
|
}
|
||||||
|
|
||||||
get generated () {
|
get generated () {
|
||||||
|
@ -1,4 +1,25 @@
|
|||||||
import { clamp } from '../utility'
|
import { Mesh } from '../mesh'
|
||||||
|
import { mat4 } from 'gl-matrix'
|
||||||
|
|
||||||
|
const VERTEX_SHADER = `
|
||||||
|
precision mediump float;
|
||||||
|
attribute vec2 aVertexPosition;
|
||||||
|
varying vec2 uv;
|
||||||
|
uniform mat4 uTransformationMatrix;
|
||||||
|
void main() {
|
||||||
|
gl_Position = uTransformationMatrix * vec4(aVertexPosition, 0.0, 1.0);
|
||||||
|
uv = vec2((aVertexPosition.x+1.0)/2.0, 1.0 - (aVertexPosition.y+1.0)/2.0);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const FRAGMENT_SHADER = `
|
||||||
|
precision mediump float;
|
||||||
|
varying vec2 uv;
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = texture2D(texture0, uv);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
class Dim4 {
|
class Dim4 {
|
||||||
constructor (scX, ofX, scY, ofY) {
|
constructor (scX, ofX, scY, ofY) {
|
||||||
@ -67,10 +88,34 @@ class Node2D {
|
|||||||
|
|
||||||
this.parent = null
|
this.parent = null
|
||||||
this.children = []
|
this.children = []
|
||||||
|
|
||||||
|
this.transform = mat4.create()
|
||||||
|
|
||||||
|
this.updateTransform()
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTransform () {
|
updateTransform () {
|
||||||
|
let matrix = mat4.create()
|
||||||
|
mat4.translate(matrix, matrix, [this.pos[0], this.pos[2], 0.0])
|
||||||
|
mat4.scale(matrix, matrix, [this.size[0], this.size[2], 1.0])
|
||||||
|
if (this.rotation !== 0.0) {
|
||||||
|
mat4.rotate(matrix, matrix, this.rotation * Math.PI / 180, [0.0, 0.0, 1.0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add parent's transform to this
|
||||||
|
if (this.parent) {
|
||||||
|
mat4.mul(matrix, this.parent.transform, matrix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the matrix
|
||||||
|
this.transform = matrix
|
||||||
|
|
||||||
|
// Update children's transforms
|
||||||
|
for (let i in this.children) {
|
||||||
|
let child = this.children[i]
|
||||||
|
if (!(child instanceof Node2D)) continue
|
||||||
|
child.updateTransform()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
@ -83,12 +128,12 @@ class Node2D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw base
|
// Draw base
|
||||||
draw (gl) {
|
draw (gl, shader, quad) {
|
||||||
// Nothing to draw here, so just draw children
|
// Nothing to draw here, so just draw children
|
||||||
for (let i in this.children) {
|
for (let i in this.children) {
|
||||||
let child = this.children[i]
|
let child = this.children[i]
|
||||||
if (!(child instanceof Node2D)) continue
|
if (!(child instanceof Node2D)) continue
|
||||||
child.draw(gl)
|
child.draw(gl, shader, quad)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,3 +163,55 @@ class Node2D {
|
|||||||
this.parent = p
|
this.parent = p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GUIImage extends Node2D {
|
||||||
|
constructor (texture, pos, size, rotation) {
|
||||||
|
super(pos, size, rotation)
|
||||||
|
this.texture = texture
|
||||||
|
this.active = true
|
||||||
|
}
|
||||||
|
|
||||||
|
draw (gl, shader, quad) {
|
||||||
|
super.draw(gl, shader, quad)
|
||||||
|
if (!this.active) return
|
||||||
|
gl.activeTexture(gl.TEXTURE0)
|
||||||
|
gl.bindTexture(this.texture.type, this.texture.id)
|
||||||
|
|
||||||
|
// Set transformation matrix
|
||||||
|
const transformLocation = shader.getUniformLocation(gl, 'uTransformationMatrix')
|
||||||
|
gl.uniformMatrix4fv(transformLocation, false, this.transform)
|
||||||
|
|
||||||
|
// Draw the quad
|
||||||
|
quad.draw(gl, shader, gl.TRIANGLE_STRIP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GUIRenderer {
|
||||||
|
async initialize (game) {
|
||||||
|
this.shader = await game.shaders.createShader(game.gl, 'gui', VERTEX_SHADER, FRAGMENT_SHADER)
|
||||||
|
this.createQuad(game.gl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reusable quad mesh for rendering GUIs
|
||||||
|
createQuad (gl) {
|
||||||
|
if (this.quad) return this.quad
|
||||||
|
this.quad = Mesh.constructFromVertices(gl, [-1, 1, -1, -1, 1, 1, 1, -1], 2)
|
||||||
|
return this.quad
|
||||||
|
}
|
||||||
|
|
||||||
|
draw (gl, nodes) {
|
||||||
|
if (typeof nodes !== 'object') nodes = [ nodes ]
|
||||||
|
this.shader.use(gl)
|
||||||
|
this.quad.prepare(gl, this.shader)
|
||||||
|
gl.enable(gl.BLEND)
|
||||||
|
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
||||||
|
gl.disable(gl.DEPTH_TEST)
|
||||||
|
for (let i in nodes) {
|
||||||
|
nodes[i].draw(gl, this.shader, this.quad)
|
||||||
|
}
|
||||||
|
gl.enable(gl.DEPTH_TEST)
|
||||||
|
gl.disable(gl.BLEND)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Dim4, GUIRenderer, GUIImage }
|
||||||
|
@ -37,7 +37,7 @@ class Engine {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
// Set clear color to black, fully opaque
|
// Set clear color to black, fully opaque
|
||||||
gl.clearColor(0.0, 0.7, 1.0, 1.0)
|
gl.clearColor(0.0, 0.0, 0.0, 1.0)
|
||||||
|
|
||||||
// Clear the color buffer with specified clear color
|
// Clear the color buffer with specified clear color
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||||
|
@ -38,21 +38,38 @@ class Mesh {
|
|||||||
return mesh
|
return mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constructFromVertices (gl, vertices, dimensions = 3) {
|
||||||
|
let pos = Mesh.loadToBuffer(gl, gl.ARRAY_BUFFER, new Float32Array(vertices))
|
||||||
|
let mesh = new Mesh()
|
||||||
|
mesh.posBuffer = pos
|
||||||
|
mesh.vertices = vertices
|
||||||
|
mesh.vertexCount = vertices.length / dimensions
|
||||||
|
mesh.vertexLayout = dimensions
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, null)
|
||||||
|
|
||||||
|
return mesh
|
||||||
|
}
|
||||||
|
|
||||||
bindBuffers (gl, shader) {
|
bindBuffers (gl, shader) {
|
||||||
|
this._bufferCount = 1
|
||||||
|
|
||||||
|
let d = this.vertexLayout || 3
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.posBuffer)
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.posBuffer)
|
||||||
shader.setAttribute(gl, 'aVertexPosition', 3, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0)
|
shader.setAttribute(gl, 'aVertexPosition', d, false, d * Float32Array.BYTES_PER_ELEMENT, 0)
|
||||||
|
|
||||||
if (this.nms && shader.hasAttribute(gl, 'aNormal')) {
|
if (this.nms && shader.hasAttribute(gl, 'aNormal')) {
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.nms)
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.nms)
|
||||||
shader.setAttribute(gl, 'aNormal', 3, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0)
|
shader.setAttribute(gl, 'aNormal', 3, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0)
|
||||||
|
this._bufferCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.uvs && shader.hasAttribute(gl, 'aTexCoords')) {
|
if (this.uvs && shader.hasAttribute(gl, 'aTexCoords')) {
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvs)
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvs)
|
||||||
shader.setAttribute(gl, 'aTexCoords', 2, false, 2 * Float32Array.BYTES_PER_ELEMENT, 0)
|
shader.setAttribute(gl, 'aTexCoords', 2, false, 2 * Float32Array.BYTES_PER_ELEMENT, 0)
|
||||||
|
this._bufferCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.ebo)
|
this.ebo && gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.ebo)
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare (gl, shader) {
|
prepare (gl, shader) {
|
||||||
@ -69,7 +86,14 @@ class Mesh {
|
|||||||
if (this.indices) {
|
if (this.indices) {
|
||||||
gl.drawElements(mode, this.indices.length, gl.UNSIGNED_SHORT, 0)
|
gl.drawElements(mode, this.indices.length, gl.UNSIGNED_SHORT, 0)
|
||||||
} else {
|
} else {
|
||||||
gl.drawArrays(mode, 0, this.vertices.length)
|
gl.drawArrays(mode, 0, this.vertexCount || this.vertices.length / (this.vertexLayout || 3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unbind all attrib arrays after drawing something
|
||||||
|
postdraw (gl, shader) {
|
||||||
|
for (let i = 0; i < this._bufferCount; i++) {
|
||||||
|
gl.disableVertexAttribArray(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,22 @@
|
|||||||
import Resource from '../resource'
|
import Resource from '../resource'
|
||||||
|
|
||||||
class Texture {
|
class Texture {
|
||||||
static createTexture2D (gl, img) {
|
static createTexture2D (gl, img, flip = true, filtering, repeat = gl.REPEAT) {
|
||||||
let tex = gl.createTexture()
|
let tex = gl.createTexture()
|
||||||
gl.bindTexture(gl.TEXTURE_2D, tex)
|
gl.bindTexture(gl.TEXTURE_2D, tex)
|
||||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip)
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img)
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img)
|
||||||
|
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, repeat)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, repeat)
|
||||||
|
|
||||||
|
if (filtering) {
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filtering)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filtering)
|
||||||
|
} else {
|
||||||
gl.generateMipmap(gl.TEXTURE_2D)
|
gl.generateMipmap(gl.TEXTURE_2D)
|
||||||
|
}
|
||||||
|
|
||||||
gl.bindTexture(gl.TEXTURE_2D, null)
|
gl.bindTexture(gl.TEXTURE_2D, null)
|
||||||
|
|
||||||
let oTex = new Texture()
|
let oTex = new Texture()
|
||||||
@ -16,9 +25,39 @@ class Texture {
|
|||||||
|
|
||||||
return oTex
|
return oTex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static createTextureCubeMap (gl, img) {
|
||||||
|
if (!img || img.length !== 6) throw new Error('createTextureCubeMap() requires six images!')
|
||||||
|
let tex = gl.createTexture()
|
||||||
|
gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex)
|
||||||
|
|
||||||
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false)
|
||||||
|
|
||||||
|
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[0])
|
||||||
|
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[1])
|
||||||
|
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[2])
|
||||||
|
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[3])
|
||||||
|
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[4])
|
||||||
|
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[5])
|
||||||
|
|
||||||
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||||
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||||
|
|
||||||
|
gl.bindTexture(gl.TEXTURE_CUBE_MAP, null)
|
||||||
|
|
||||||
|
let oTex = new Texture()
|
||||||
|
oTex.type = gl.TEXTURE_CUBE_MAP
|
||||||
|
oTex.id = tex
|
||||||
|
|
||||||
|
return oTex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Material {
|
class Material {
|
||||||
|
constructor (textures) {
|
||||||
|
this.textures = textures
|
||||||
|
}
|
||||||
|
|
||||||
async loadTextures (gl) {
|
async loadTextures (gl) {
|
||||||
if (this.textures) {
|
if (this.textures) {
|
||||||
for (let ti in this.textures) {
|
for (let ti in this.textures) {
|
||||||
|
@ -4,7 +4,7 @@ class Screen {
|
|||||||
constructor () {
|
constructor () {
|
||||||
this._el = document.createElement('canvas')
|
this._el = document.createElement('canvas')
|
||||||
this.resize()
|
this.resize()
|
||||||
this._gl = this._el.getContext('webgl')
|
this._gl = this._el.getContext('webgl', { alpha: false })
|
||||||
|
|
||||||
if (!this._gl) {
|
if (!this._gl) {
|
||||||
alert('Your machine or browser does not support WebGL!')
|
alert('Your machine or browser does not support WebGL!')
|
||||||
|
46
src/index.js
@ -1,34 +1,50 @@
|
|||||||
import Engine from './engine'
|
import Engine from './engine'
|
||||||
import Camera from './engine/camera'
|
import Camera from './engine/camera'
|
||||||
|
import Resource from './engine/resource'
|
||||||
import loadMesh from './engine/mesh/loader'
|
import loadMesh from './engine/mesh/loader'
|
||||||
|
|
||||||
import { Environment } from './engine/environment'
|
import { Environment } from './engine/environment'
|
||||||
import { LODTerrain } from './engine/components/terrain/lod'
|
import { LODTerrain } from './engine/components/terrain/lod'
|
||||||
|
import { Skybox } from './engine/components/skybox'
|
||||||
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
||||||
import { Material } from './engine/mesh/material'
|
import { Material, Texture } from './engine/mesh/material'
|
||||||
|
import { GUIRenderer, GUIImage, Dim4 } from './engine/gui'
|
||||||
|
|
||||||
let game = new Engine()
|
let game = new Engine()
|
||||||
let env = new Environment()
|
let env = new Environment()
|
||||||
|
let gui = new GUIRenderer()
|
||||||
|
|
||||||
// let t = 0
|
|
||||||
async function pipeline () {
|
async function pipeline () {
|
||||||
let entity = await loadMesh(game.gl, 'test')
|
let entity = await loadMesh(game.gl, 'test')
|
||||||
let shader = await game.shaders.createShaderFromFiles(game.gl, 'basic', false)
|
let shader = await game.shaders.createShaderFromFiles(game.gl, 'basic', false)
|
||||||
let terrainShader = await game.shaders.createShaderFromFiles(game.gl, 'terrain', false)
|
let terrainShader = await game.shaders.createShaderFromFiles(game.gl, 'terrain', false)
|
||||||
|
let skyboxShader = await game.shaders.createShaderFromFiles(game.gl, 'skybox', false)
|
||||||
|
|
||||||
entity.setRotation([0.0, 0.0, -90.0])
|
entity.setRotation([0.0, 0.0, -90.0])
|
||||||
|
|
||||||
|
// Initialize GUI
|
||||||
|
await gui.initialize(game)
|
||||||
|
let itms = [
|
||||||
|
new GUIImage(await Texture.createTexture2D(game.gl, await Resource.loadImage('noisy.png'), false, game.gl.LINEAR),
|
||||||
|
new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0))
|
||||||
|
]
|
||||||
|
|
||||||
// Create a height map based on OpenSimplex noise
|
// Create a height map based on OpenSimplex noise
|
||||||
let hmap = new SimplexHeightMap(1, 1, 256, 50)
|
let hmap = new SimplexHeightMap(1, 1, 256, 50)
|
||||||
|
|
||||||
// Create a terrain
|
// Create a terrain instance
|
||||||
let terrain = new LODTerrain([0.0, 0.0, 0.0], 1024, 1024, 850, 4)
|
let terrain = new LODTerrain([0.0, 0.0, 0.0], 1024, 1024, 850, 4)
|
||||||
|
|
||||||
// Terrain material
|
// Terrain material
|
||||||
let material = new Material()
|
let material = new Material(['grass-1024.jpg'])
|
||||||
material.textures = ['grass-1024.jpg']
|
|
||||||
await material.loadTextures(game.gl)
|
await material.loadTextures(game.gl)
|
||||||
|
|
||||||
|
// test code
|
||||||
|
for (let i in entity.children) {
|
||||||
|
entity.children[i].mesh.material = material
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set generator and material for terrain
|
||||||
terrain.setGenerator(hmap)
|
terrain.setGenerator(hmap)
|
||||||
terrain.setMaterial(material)
|
terrain.setMaterial(material)
|
||||||
|
|
||||||
@ -36,7 +52,13 @@ async function pipeline () {
|
|||||||
let cam = new Camera([-200.0, 1.0, 0.0])
|
let cam = new Camera([-200.0, 1.0, 0.0])
|
||||||
cam.updateProjection(game.gl)
|
cam.updateProjection(game.gl)
|
||||||
|
|
||||||
// Update function for camera
|
// Create skybox
|
||||||
|
let skybox = new Skybox('skybox', cam.farPlane / 2)
|
||||||
|
|
||||||
|
// Load textures and generate a mesh
|
||||||
|
await skybox.initialize(game.gl)
|
||||||
|
|
||||||
|
// Update function for camera and terrain
|
||||||
game.addUpdateFunction(function (dt) {
|
game.addUpdateFunction(function (dt) {
|
||||||
if (game.input.isDown('w')) {
|
if (game.input.isDown('w')) {
|
||||||
cam.processKeyboard(0, dt)
|
cam.processKeyboard(0, dt)
|
||||||
@ -50,6 +72,7 @@ async function pipeline () {
|
|||||||
cam.processKeyboard(3, dt)
|
cam.processKeyboard(3, dt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panning
|
||||||
if (game.input.mouseMoved && game.input.mouse.btn0) {
|
if (game.input.mouseMoved && game.input.mouse.btn0) {
|
||||||
cam.processMouseMove(game.input.mouseOffset)
|
cam.processMouseMove(game.input.mouseOffset)
|
||||||
}
|
}
|
||||||
@ -57,10 +80,6 @@ async function pipeline () {
|
|||||||
// Update detail levels
|
// Update detail levels
|
||||||
terrain.update(game.gl, cam)
|
terrain.update(game.gl, cam)
|
||||||
terrain.updateLODMesh(game.gl)
|
terrain.updateLODMesh(game.gl)
|
||||||
|
|
||||||
// TESTING: Move model forward
|
|
||||||
// t = t + 0.1
|
|
||||||
// entity.setPosition([t, 0.0, 0.0])
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Render function for the triangle
|
// Render function for the triangle
|
||||||
@ -80,6 +99,13 @@ async function pipeline () {
|
|||||||
|
|
||||||
// Draw terrain
|
// Draw terrain
|
||||||
terrain.draw(gl, terrainShader)
|
terrain.draw(gl, terrainShader)
|
||||||
|
// Draw the skybox
|
||||||
|
skyboxShader.use(gl)
|
||||||
|
skybox.draw(gl, skyboxShader, cam)
|
||||||
|
})
|
||||||
|
|
||||||
|
game.addRenderFunction(function (gl) {
|
||||||
|
gui.draw(gl, itms)
|
||||||
})
|
})
|
||||||
|
|
||||||
game.startGameLoop()
|
game.startGameLoop()
|
||||||
|