3dexperiments/src/index.js

189 lines
5.5 KiB
JavaScript

import Engine from './engine'
import Camera from './engine/camera'
import loadMesh from './engine/mesh/loader'
import { randomInt } from './engine/utility'
import { Environment } from './engine/environment'
import { LODTerrain } from './engine/components/terrain/lod'
import { Skybox } from './engine/components/skybox'
import { WaterRenderer, WaterTile } from './engine/components/water'
import { Particle, ParticleTexture, ParticleSystem, ParticleRenderer } from './engine/components/particles'
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
import { Material, Texture } from './engine/mesh/material'
import { GUIRenderer, GUIImage, Dim4 } from './engine/gui'
import { FontRenderer, GUIText, Font } from './engine/gui/font'
import { VoxelWorld, VoxelGenerator } from './engine/voxel'
let game = Engine
let env = new Environment()
let gui = new GUIRenderer()
let fnt = new FontRenderer()
let prt = new ParticleRenderer()
async function pipeline () {
let entity = await loadMesh(game.gl, 'test')
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])
// Initialize water
let waterRenderer = new WaterRenderer()
let water = new WaterTile([100.0, 0.0, 100.0], 100.0)
await waterRenderer.initialize(game)
await waterRenderer.useDUDVMap(game.gl, 'dudv')
await waterRenderer.useNormalMap(game.gl, 'normalmap')
let arialFont = await Font.fromFile('arial')
await arialFont.loadTextures(game.gl)
// Initialize GUI
await gui.initialize(game)
await fnt.initialize(game)
// Initialize particles
await prt.initialize(game)
let particleSystem = new ParticleSystem(prt)
// Particle texture atlas
let particleTexture = new ParticleTexture(await Texture.fromFile(game.gl, 'particleAtlas.png'), 4)
let itms = [
new GUIImage(await Texture.fromFile(game.gl, '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))
]
// Nesting test
itms[0].addChild(new GUIText('', arialFont, 0.8, new Dim4(0.2, 0.0, 0.0, 0.0), new Dim4(1.0, 0.0, 0.3, 0.0), false))
itms[0].children[0].color = [0.0, 0.2, 1.0]
// Create a height map based on OpenSimplex noise
let hmap = new SimplexHeightMap(1, 1, 256, 50)
// Create a terrain instance
let terrain = new LODTerrain([0.0, 0.0, 0.0], 1024, 1024, 850, 4)
// Terrain material
let material = new Material(['grass-1024.jpg'])
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.setMaterial(material)
// Create and initialize the camera
let cam = new Camera([-16.0, 25.0, -16.0], [0.8, -0.6, 0.0])
cam.updateProjection(game.gl)
// Create skybox
let skybox = new Skybox('skybox', cam.farPlane / 2)
// Load textures and generate a mesh
await skybox.initialize(game.gl)
// Voxel test
// let voxgen = new VoxelGenerator(hmap, material)
// let block = new VoxelWorld(voxgen)
// Update function for camera and terrain
let fpsTimer = 0
game.addUpdateFunction(function (dt) {
if (game.input.isDown('w')) {
cam.processKeyboard(0, dt)
} else if (game.input.isDown('s')) {
cam.processKeyboard(1, dt)
}
if (game.input.isDown('a')) {
cam.processKeyboard(2, dt)
} else if (game.input.isDown('d')) {
cam.processKeyboard(3, dt)
}
// Panning
if (game.input.mouseMoved && game.input.mouse.btn0) {
cam.processMouseMove(game.input.mouseOffset)
}
// Particles
particleSystem.update(dt, -50)
if (game.input.isDown('y')) {
let velocity = 20
for (let i = 0; i < 360; i += 15) {
let rad1 = i * Math.PI / 180
let x1 = (Math.cos(rad1) * velocity) + randomInt(-5, 5)
let y1 = (Math.sin(rad1) * velocity) + randomInt(-5, 5)
particleSystem.add(new Particle(particleTexture, [0.0, 0.0, 0.0], [x1, randomInt(-velocity, velocity), y1], 0.2, 2, randomInt(0, 360), randomInt(0.1, 1)))
}
}
// Update detail levels
terrain.update(game.gl, cam)
terrain.updateLODMesh(game.gl)
// Ripple water
waterRenderer.update(dt)
// Update voxel chunk
// voxgen.update(dt)
// block.update(game.gl, cam, dt)
// Set text to FPS
fpsTimer++
if (fpsTimer === 10) {
itms[0].children[0].setText(game.fps + ' fps')
fpsTimer = 0
}
})
function drawEverything (gl) {
game.prepare()
// Draw the skybox
skyboxShader.use(gl)
skybox.draw(gl, skyboxShader, cam)
// Use terrain shader
terrainShader.use(gl)
// Set environment variables in shader
env.draw(gl, terrainShader)
// Set the viewport uniforms
cam.draw(gl, terrainShader)
// Draw terrain
terrain.draw(gl, terrainShader)
// entity.draw(gl, terrainShader)
// block.draw(gl, terrainShader)
}
// Render function for the triangle
game.addRenderFunction(function (gl) {
waterRenderer.reflect(gl, cam, drawEverything)
waterRenderer.refract(gl, cam, drawEverything)
drawEverything(gl)
waterRenderer.draw(gl, [water], cam, env.sun)
// Draw particles
particleSystem.draw(gl, cam)
// Draw GUIs
gui.draw(gl, cam, itms)
fnt.draw(gl, cam, itms)
})
game.startGameLoop()
}
// Start the game, catch any errors thrown
pipeline().catch(function (e) {
console.error(e)
})