some broken water code that needs fixing at some point
This commit is contained in:
parent
e103fa6e3b
commit
bada6f86b4
28
assets/shaders/water.fs
Normal file
28
assets/shaders/water.fs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
varying vec4 clipSpace;
|
||||||
|
|
||||||
|
uniform sampler2D reflectionTexture;
|
||||||
|
uniform sampler2D refractionTexture;
|
||||||
|
uniform sampler2D dudvMap;
|
||||||
|
|
||||||
|
varying vec2 uv;
|
||||||
|
const float waveStrength = 0.002;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 ndc = (clipSpace.xy / clipSpace.w) / 2.0 + 0.5;
|
||||||
|
vec2 refractTexCoords = vec2(ndc.x, ndc.y);
|
||||||
|
vec2 reflectTexCoords = vec2(ndc.x, 1.0 - ndc.y);
|
||||||
|
|
||||||
|
vec2 distortion1 = texture2D(dudvMap, uv).xy * 2.0 - 1.0 * waveStrength;
|
||||||
|
refractTexCoords += distortion1;
|
||||||
|
refractTexCoords = clamp(refractTexCoords, 0.001, 0.999);
|
||||||
|
reflectTexCoords += distortion1;
|
||||||
|
reflectTexCoords.x = clamp(reflectTexCoords.x, 0.001, 0.999);
|
||||||
|
reflectTexCoords.y = clamp(reflectTexCoords.y, -0.999, -0.001);
|
||||||
|
|
||||||
|
vec4 reflectColor = texture2D(reflectionTexture, reflectTexCoords);
|
||||||
|
vec4 refractColor = texture2D(refractionTexture, refractTexCoords);
|
||||||
|
|
||||||
|
gl_FragColor = mix(reflectColor, refractColor, 0.5);
|
||||||
|
}
|
18
assets/shaders/water.vs
Normal file
18
assets/shaders/water.vs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
attribute vec2 aVertexPosition;
|
||||||
|
|
||||||
|
uniform mat4 uModelMatrix;
|
||||||
|
uniform mat4 uViewMatrix;
|
||||||
|
uniform mat4 uProjectionMatrix;
|
||||||
|
|
||||||
|
varying vec4 clipSpace;
|
||||||
|
varying vec2 uv;
|
||||||
|
|
||||||
|
const float tiling = 6.0;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
clipSpace = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4(aVertexPosition.x, 0.0, aVertexPosition.y, 1.0);
|
||||||
|
gl_Position = clipSpace;
|
||||||
|
uv = vec2(aVertexPosition.x/2.0+0.5,aVertexPosition.y/2.0+0.5) * tiling;
|
||||||
|
}
|
BIN
assets/textures/dudv.png
Normal file
BIN
assets/textures/dudv.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 565 KiB |
@ -1,3 +1,4 @@
|
|||||||
|
import Screen from './screen'
|
||||||
import { Node } from './components'
|
import { Node } from './components'
|
||||||
import { glMatrix, mat4, vec2, vec3 } from 'gl-matrix'
|
import { glMatrix, mat4, vec2, vec3 } from 'gl-matrix'
|
||||||
|
|
||||||
@ -101,8 +102,7 @@ class Camera extends Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateProjection (gl) {
|
updateProjection (gl) {
|
||||||
let aspect = gl.canvas.width / gl.canvas.height
|
mat4.perspective(this.projection, this.fov, Screen.aspectRatio, this.nearPlane, this.farPlane)
|
||||||
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
|
||||||
|
153
src/engine/components/water/index.js
Normal file
153
src/engine/components/water/index.js
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import { Node } from '../'
|
||||||
|
import { Mesh } from '../../mesh'
|
||||||
|
import { Texture } from '../../mesh/material'
|
||||||
|
import Screen from '../../screen'
|
||||||
|
import Resource from '../../resource'
|
||||||
|
|
||||||
|
class WaterFBOs {
|
||||||
|
constructor (reflectionWidth = 320, reflectionHeight = 180, refractionWidth = 1280, refractionHeight = 720) {
|
||||||
|
this.reflectionHeight = reflectionHeight
|
||||||
|
this.reflectionWidth = reflectionWidth
|
||||||
|
this.refractionHeight = refractionHeight
|
||||||
|
this.refractionWidth = refractionWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize (gl) {
|
||||||
|
this.initReflectionFrameBuffer(gl)
|
||||||
|
this.initRefractionFrameBuffer(gl)
|
||||||
|
}
|
||||||
|
|
||||||
|
initReflectionFrameBuffer (gl) {
|
||||||
|
this.reflectionFrameBuffer = this.createFrameBuffer(gl)
|
||||||
|
this.reflectionTexture = this.createTextureAttachment(gl, this.reflectionWidth, this.reflectionHeight)
|
||||||
|
this.reflectionDepthBuffer = this.createDepthBufferAttachment(gl, this.reflectionWidth, this.reflectionHeight)
|
||||||
|
this.unbindFrameBuffer(gl)
|
||||||
|
}
|
||||||
|
|
||||||
|
initRefractionFrameBuffer (gl) {
|
||||||
|
this.refractionFrameBuffer = this.createFrameBuffer(gl)
|
||||||
|
this.refractionTexture = this.createTextureAttachment(gl, this.refractionWidth, this.refractionHeight)
|
||||||
|
this.refractionDepthTexture = this.createDepthTextureAttachment(gl, this.refractionWidth, this.refractionHeight)
|
||||||
|
this.unbindFrameBuffer(gl)
|
||||||
|
}
|
||||||
|
|
||||||
|
createFrameBuffer (gl) {
|
||||||
|
// generate frame buffer
|
||||||
|
let frameBuffer = gl.createFramebuffer()
|
||||||
|
// create the framebuffer
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer)
|
||||||
|
// indicate that we will always render to color attachment 0
|
||||||
|
gl.drawBuffers.drawBuffersWEBGL([gl.COLOR_ATTACHMENT0])
|
||||||
|
return frameBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
unbindFrameBuffer (gl) {
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null)
|
||||||
|
gl.viewport(0, 0, Screen.width, Screen.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
bindFrameBuffer (gl, frameBuffer, width, height) {
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, null) // To make sure the texture isn't bound
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer)
|
||||||
|
gl.viewport(0, 0, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// call before rendering to this FBO
|
||||||
|
bindReflectionFrameBuffer (gl) {
|
||||||
|
this.bindFrameBuffer(gl, this.reflectionFrameBuffer, this.reflectionWidth, this.reflectionHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// call before rendering to this FBO
|
||||||
|
bindRefractionFrameBuffer (gl) {
|
||||||
|
this.bindFrameBuffer(gl, this.refractionFrameBuffer, this.refractionWidth, this.refractionHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
createTextureAttachment (gl, width, height) {
|
||||||
|
let texture = gl.createTexture()
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture)
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, null)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
||||||
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
|
||||||
|
createDepthTextureAttachment (gl, width, height) {
|
||||||
|
let texture = gl.createTexture()
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture)
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
||||||
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, texture, 0)
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
|
||||||
|
createDepthBufferAttachment (gl, width, height) {
|
||||||
|
let depthBuffer = gl.createRenderbuffer()
|
||||||
|
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer)
|
||||||
|
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height)
|
||||||
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer)
|
||||||
|
return depthBuffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WaterTile extends Node {
|
||||||
|
constructor (pos, scale, rot) {
|
||||||
|
super(pos, [scale, 0.0, scale], rot)
|
||||||
|
this.fbos = new WaterFBOs()
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize (gl) {
|
||||||
|
this.mesh = Mesh.constructFromVertices(gl, [-1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1], 2)
|
||||||
|
this.fbos.initialize(gl)
|
||||||
|
}
|
||||||
|
|
||||||
|
async useDUDV (gl, file) {
|
||||||
|
this.dudv = await Texture.createTexture2D(gl, await Resource.loadImage(file + '.png'), false, gl.LINEAR)
|
||||||
|
}
|
||||||
|
|
||||||
|
reflect (gl, cam, render) {
|
||||||
|
this.fbos.bindReflectionFrameBuffer(gl)
|
||||||
|
let dist = 2 * (cam.pos[1] - this.pos[1])
|
||||||
|
cam.pos[1] -= dist
|
||||||
|
cam.rotation[1] *= -1
|
||||||
|
cam.updateTransform()
|
||||||
|
render(gl)
|
||||||
|
this.fbos.unbindFrameBuffer(gl)
|
||||||
|
cam.pos[1] += dist
|
||||||
|
cam.rotation[1] *= -1
|
||||||
|
cam.updateTransform()
|
||||||
|
}
|
||||||
|
|
||||||
|
refract (gl, cam, render) {
|
||||||
|
this.fbos.bindRefractionFrameBuffer(gl)
|
||||||
|
render(gl)
|
||||||
|
this.fbos.unbindFrameBuffer(gl)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw (gl, shader) {
|
||||||
|
super.draw(gl, shader)
|
||||||
|
|
||||||
|
const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix')
|
||||||
|
gl.uniformMatrix4fv(transformLocation, false, this.transform)
|
||||||
|
|
||||||
|
gl.activeTexture(gl.TEXTURE0)
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.fbos.reflectionTexture)
|
||||||
|
gl.activeTexture(gl.TEXTURE1)
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.fbos.refractionTexture)
|
||||||
|
if (this.dudv) {
|
||||||
|
gl.activeTexture(gl.TEXTURE2)
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.dudv.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mesh.prepare(gl, shader)
|
||||||
|
this.mesh.draw(gl, shader)
|
||||||
|
this.mesh.postdraw(gl, shader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { WaterTile, WaterFBOs }
|
0
src/engine/framebuffer.js
Normal file
0
src/engine/framebuffer.js
Normal file
@ -6,7 +6,6 @@ import { Node2D } from './'
|
|||||||
|
|
||||||
import { mat4 } from 'gl-matrix'
|
import { mat4 } from 'gl-matrix'
|
||||||
|
|
||||||
const aspectRatio = Screen.width / Screen.height
|
|
||||||
const PAD_TOP = 0
|
const PAD_TOP = 0
|
||||||
const PAD_LEFT = 1
|
const PAD_LEFT = 1
|
||||||
const PAD_BOTTOM = 2
|
const PAD_BOTTOM = 2
|
||||||
@ -46,6 +45,7 @@ class Word {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addCharacter (char) {
|
addCharacter (char) {
|
||||||
|
if (!char) return
|
||||||
this.characters.push(char)
|
this.characters.push(char)
|
||||||
this.width += char.xAdvance * this.fontSize
|
this.width += char.xAdvance * this.fontSize
|
||||||
}
|
}
|
||||||
@ -74,7 +74,6 @@ class Line {
|
|||||||
class FontFile {
|
class FontFile {
|
||||||
constructor (name) {
|
constructor (name) {
|
||||||
this.name = name
|
this.name = name
|
||||||
this.values = {}
|
|
||||||
this.metadata = {}
|
this.metadata = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +90,7 @@ class FontFile {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse a .fnt file
|
||||||
readValues (data) {
|
readValues (data) {
|
||||||
let lines = data.split('\n')
|
let lines = data.split('\n')
|
||||||
for (let i in lines) {
|
for (let i in lines) {
|
||||||
@ -101,9 +101,7 @@ class FontFile {
|
|||||||
for (let j in lineSplit) {
|
for (let j in lineSplit) {
|
||||||
let valuePairs = lineSplit[j].split('=')
|
let valuePairs = lineSplit[j].split('=')
|
||||||
if (valuePairs.length === 2) {
|
if (valuePairs.length === 2) {
|
||||||
let key = valuePairs[0]
|
lineValues[valuePairs[0]] = valuePairs[1]
|
||||||
let val = valuePairs[1]
|
|
||||||
lineValues[key] = val
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,16 +112,11 @@ class FontFile {
|
|||||||
} else if (lineSplit[0] === 'common') {
|
} else if (lineSplit[0] === 'common') {
|
||||||
let lineHeightPixels = this.getValue(lineValues, 'lineHeight') - this.paddingHeight
|
let lineHeightPixels = this.getValue(lineValues, 'lineHeight') - this.paddingHeight
|
||||||
this.vertPerPixelSize = LINE_HEIGHT / lineHeightPixels
|
this.vertPerPixelSize = LINE_HEIGHT / lineHeightPixels
|
||||||
this.horizPixelSize = this.vertPerPixelSize / aspectRatio
|
this.horizPixelSize = this.vertPerPixelSize / Screen.aspectRatio
|
||||||
|
this.scaleWidth = this.getValue(lineValues, 'scaleW')
|
||||||
} else if (lineSplit[0] === 'char') {
|
} else if (lineSplit[0] === 'char') {
|
||||||
let c = this.loadCharacter(lineValues, this.getValue(this.values, 'scaleW'))
|
let c = this.loadCharacter(lineValues, this.scaleWidth)
|
||||||
if (c) this.metadata[c.id] = c
|
if (c) this.metadata[c.id] = c
|
||||||
continue
|
|
||||||
} else if (lineSplit[0] === 'kernings' || lineSplit[0] === 'kerning' || lineSplit[0] === 'chars') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for (let j in lineValues) {
|
|
||||||
this.values[j] = lineValues[j]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,7 +149,6 @@ class FontFile {
|
|||||||
let load = await Resource.GET('/assets/fonts/' + fontName + '.fnt')
|
let load = await Resource.GET('/assets/fonts/' + fontName + '.fnt')
|
||||||
let file = new FontFile(fontName)
|
let file = new FontFile(fontName)
|
||||||
file.readValues(load)
|
file.readValues(load)
|
||||||
console.log(file)
|
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,21 +160,25 @@ class Font {
|
|||||||
this.texture = null
|
this.texture = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load font data from a .fnt file and create a Font object with it
|
||||||
static async fromFile (name) {
|
static async fromFile (name) {
|
||||||
let meta = await FontFile.fromFile(name)
|
let meta = await FontFile.fromFile(name)
|
||||||
return new Font(name, meta)
|
return new Font(name, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load font texture
|
||||||
async loadTextures (gl) {
|
async loadTextures (gl) {
|
||||||
this.texture = await Texture.createTexture2D(gl, await Resource.loadImage('/assets/fonts/' + this.name + '.png'), false, gl.LINEAR)
|
this.texture = await Texture.createTexture2D(gl, await Resource.loadImage('/assets/fonts/' + this.name + '.png'), false, gl.LINEAR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a renderable mesh for a text
|
||||||
createTextMesh (gl, text) {
|
createTextMesh (gl, text) {
|
||||||
let lines = this.createStructure(text)
|
let lines = this.createStructure(text)
|
||||||
let data = this.createQuadVertices(text, lines)
|
let data = this.createQuadVertices(text, lines)
|
||||||
return Mesh.constructFromVerticesUVs(gl, data.vertices, data.textureCoords)
|
return Mesh.constructFromVerticesUVs(gl, data.vertices, data.textureCoords)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a structure of lines, words and characters in order to generate the vertices properly
|
||||||
createStructure (text) {
|
createStructure (text) {
|
||||||
let chars = text.asCharacters
|
let chars = text.asCharacters
|
||||||
let lines = []
|
let lines = []
|
||||||
@ -221,6 +217,7 @@ class Font {
|
|||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add final word
|
||||||
completeStructure (lines, currentLine, currentWord, text) {
|
completeStructure (lines, currentLine, currentWord, text) {
|
||||||
let added = currentLine.attemptToAddWord(currentWord)
|
let added = currentLine.attemptToAddWord(currentWord)
|
||||||
if (!added) {
|
if (!added) {
|
||||||
@ -232,6 +229,7 @@ class Font {
|
|||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create text vertices
|
||||||
createQuadVertices (text, lines) {
|
createQuadVertices (text, lines) {
|
||||||
text.lines = lines.length
|
text.lines = lines.length
|
||||||
let cursorX = 0
|
let cursorX = 0
|
||||||
@ -259,6 +257,7 @@ class Font {
|
|||||||
return { vertices, textureCoords }
|
return { vertices, textureCoords }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create text vertex coordinates for a specific character
|
||||||
addVerticesForCharacter (cursorX, cursorY, character, fontSize, vertices) {
|
addVerticesForCharacter (cursorX, cursorY, character, fontSize, vertices) {
|
||||||
let x = cursorX + (character.xOffset * fontSize)
|
let x = cursorX + (character.xOffset * fontSize)
|
||||||
let y = cursorY + (character.yOffset * fontSize)
|
let y = cursorY + (character.yOffset * fontSize)
|
||||||
@ -271,6 +270,7 @@ class Font {
|
|||||||
this.addVertices(vertices, properX, properY, properMaxX, properMaxY)
|
this.addVertices(vertices, properX, properY, properMaxX, properMaxY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create text vertex coordinates
|
||||||
addVertices (vertices, x, y, maxX, maxY) {
|
addVertices (vertices, x, y, maxX, maxY) {
|
||||||
vertices.push(x)
|
vertices.push(x)
|
||||||
vertices.push(y)
|
vertices.push(y)
|
||||||
@ -286,6 +286,7 @@ class Font {
|
|||||||
vertices.push(y)
|
vertices.push(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create text texture coordinates
|
||||||
addTexCoords (texCoords, x, y, maxX, maxY) {
|
addTexCoords (texCoords, x, y, maxX, maxY) {
|
||||||
texCoords.push(x)
|
texCoords.push(x)
|
||||||
texCoords.push(y)
|
texCoords.push(y)
|
||||||
@ -312,6 +313,7 @@ class GUIText extends Node2D {
|
|||||||
this.color = [0.0, 0.0, 0.0]
|
this.color = [0.0, 0.0, 0.0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not scale the transform like we do with regular GUIs
|
||||||
updateTransform () {
|
updateTransform () {
|
||||||
let matrix = mat4.create()
|
let matrix = mat4.create()
|
||||||
mat4.translate(matrix, matrix, [this.pos[0], this.pos[2], 0.0])
|
mat4.translate(matrix, matrix, [this.pos[0], this.pos[2], 0.0])
|
||||||
@ -343,6 +345,7 @@ class GUIText extends Node2D {
|
|||||||
return this.size[2]
|
return this.size[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return all characters as their ascii code
|
||||||
get asCharacters () {
|
get asCharacters () {
|
||||||
let chars = []
|
let chars = []
|
||||||
for (let i = 0; i < this.text.length; i++) {
|
for (let i = 0; i < this.text.length; i++) {
|
||||||
@ -352,6 +355,8 @@ class GUIText extends Node2D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, shader) {
|
draw (gl, shader) {
|
||||||
|
// Let only the font shader be used to render text
|
||||||
|
if (shader.name !== 'font') return super.draw(gl, shader)
|
||||||
const transformLocation = shader.getUniformLocation(gl, 'uTransformation')
|
const transformLocation = shader.getUniformLocation(gl, 'uTransformation')
|
||||||
const colorLocation = shader.getUniformLocation(gl, 'uColor')
|
const colorLocation = shader.getUniformLocation(gl, 'uColor')
|
||||||
gl.uniformMatrix4fv(transformLocation, false, this.transform)
|
gl.uniformMatrix4fv(transformLocation, false, this.transform)
|
||||||
@ -369,8 +374,8 @@ class FontRenderer {
|
|||||||
for (let i in nodes) {
|
for (let i in nodes) {
|
||||||
let node = nodes[i]
|
let node = nodes[i]
|
||||||
if (!(node instanceof GUIText)) {
|
if (!(node instanceof GUIText)) {
|
||||||
if (node.children) {
|
if (node.children.length) {
|
||||||
textNodes.concat(this.discoverTextNodes(node.children))
|
textNodes = textNodes.concat(this.discoverTextNodes(node.children))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -379,7 +384,8 @@ class FontRenderer {
|
|||||||
return textNodes
|
return textNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, nodes) {
|
draw (gl, cam, nodes) {
|
||||||
|
// Discover all nodes in the array that are texts
|
||||||
let fontPairs = {}
|
let fontPairs = {}
|
||||||
let textNodes = this.discoverTextNodes(nodes)
|
let textNodes = this.discoverTextNodes(nodes)
|
||||||
for (let i in textNodes) {
|
for (let i in textNodes) {
|
||||||
@ -399,6 +405,7 @@ class FontRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start rendering individual text arrays
|
||||||
this.shader.use(gl)
|
this.shader.use(gl)
|
||||||
gl.enable(gl.BLEND)
|
gl.enable(gl.BLEND)
|
||||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
||||||
@ -406,8 +413,10 @@ class FontRenderer {
|
|||||||
for (let i in fontPairs) {
|
for (let i in fontPairs) {
|
||||||
let texts = fontPairs[i]
|
let texts = fontPairs[i]
|
||||||
let font = this.fonts[i]
|
let font = this.fonts[i]
|
||||||
|
// Set font's map as the texture
|
||||||
gl.activeTexture(gl.TEXTURE0)
|
gl.activeTexture(gl.TEXTURE0)
|
||||||
gl.bindTexture(font.texture.type, font.texture.id)
|
gl.bindTexture(font.texture.type, font.texture.id)
|
||||||
|
// Draw all texts
|
||||||
for (let j in texts) {
|
for (let j in texts) {
|
||||||
let text = texts[j]
|
let text = texts[j]
|
||||||
text.draw(gl, this.shader)
|
text.draw(gl, this.shader)
|
||||||
|
@ -175,7 +175,11 @@ class GUIImage extends Node2D {
|
|||||||
super.draw(gl, shader, quad)
|
super.draw(gl, shader, quad)
|
||||||
if (!this.active) return
|
if (!this.active) return
|
||||||
gl.activeTexture(gl.TEXTURE0)
|
gl.activeTexture(gl.TEXTURE0)
|
||||||
gl.bindTexture(this.texture.type, this.texture.id)
|
if (!this.texture.type) {
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.texture)
|
||||||
|
} else {
|
||||||
|
gl.bindTexture(this.texture.type, this.texture.id)
|
||||||
|
}
|
||||||
|
|
||||||
// Set transformation matrix
|
// Set transformation matrix
|
||||||
const transformLocation = shader.getUniformLocation(gl, 'uTransformationMatrix')
|
const transformLocation = shader.getUniformLocation(gl, 'uTransformationMatrix')
|
||||||
@ -199,7 +203,7 @@ class GUIRenderer {
|
|||||||
return this.quad
|
return this.quad
|
||||||
}
|
}
|
||||||
|
|
||||||
draw (gl, nodes) {
|
draw (gl, cam, nodes) {
|
||||||
if (typeof nodes !== 'object') nodes = [ nodes ]
|
if (typeof nodes !== 'object') nodes = [ nodes ]
|
||||||
this.shader.use(gl)
|
this.shader.use(gl)
|
||||||
this.quad.prepare(gl, this.shader)
|
this.quad.prepare(gl, this.shader)
|
||||||
|
@ -35,7 +35,7 @@ class Engine {
|
|||||||
return this.screen.gl
|
return this.screen.gl
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
prepare () {
|
||||||
// Set clear color to black, fully opaque
|
// Set clear color to black, fully opaque
|
||||||
gl.clearColor(0.0, 0.0, 0.0, 1.0)
|
gl.clearColor(0.0, 0.0, 0.0, 1.0)
|
||||||
|
|
||||||
@ -48,7 +48,9 @@ class Engine {
|
|||||||
// Enable back-face culling
|
// Enable back-face culling
|
||||||
gl.enable(gl.CULL_FACE)
|
gl.enable(gl.CULL_FACE)
|
||||||
gl.cullFace(gl.BACK)
|
gl.cullFace(gl.BACK)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
// Render functions
|
// Render functions
|
||||||
for (let i in this.rst) {
|
for (let i in this.rst) {
|
||||||
this.rst[i](gl)
|
this.rst[i](gl)
|
||||||
@ -98,4 +100,4 @@ class Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Engine
|
export default new Engine()
|
||||||
|
@ -11,11 +11,8 @@ class Screen {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.loadExtensions()
|
||||||
document.body.appendChild(this._el)
|
document.body.appendChild(this._el)
|
||||||
|
|
||||||
window.addEventListener('resize', (e) => {
|
|
||||||
this.resize()
|
|
||||||
}, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get gl () {
|
get gl () {
|
||||||
@ -31,6 +28,12 @@ class Screen {
|
|||||||
this._el.height = window.innerHeight
|
this._el.height = window.innerHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadExtensions () {
|
||||||
|
this._gl.drawBuffers = this._gl.getExtension('WEBGL_draw_buffers')
|
||||||
|
this._gl.getExtension('WEBGL_depth_texture')
|
||||||
|
this._gl.getExtension('OES_texture_float')
|
||||||
|
}
|
||||||
|
|
||||||
get width () {
|
get width () {
|
||||||
return this._el.width
|
return this._el.width
|
||||||
}
|
}
|
||||||
@ -38,6 +41,10 @@ class Screen {
|
|||||||
get height () {
|
get height () {
|
||||||
return this._el.height
|
return this._el.height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get aspectRatio () {
|
||||||
|
return this.width / this.height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new Screen()
|
export default new Screen()
|
||||||
|
44
src/index.js
44
src/index.js
@ -6,12 +6,13 @@ 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 { Skybox } from './engine/components/skybox'
|
||||||
|
// import { WaterTile } from './engine/components/water'
|
||||||
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
||||||
import { Material, Texture } from './engine/mesh/material'
|
import { Material, Texture } from './engine/mesh/material'
|
||||||
import { GUIRenderer, GUIImage, Dim4 } from './engine/gui'
|
import { GUIRenderer, GUIImage, Dim4 } from './engine/gui'
|
||||||
import { FontRenderer, GUIText, Font } from './engine/gui/font'
|
import { FontRenderer, GUIText, Font } from './engine/gui/font'
|
||||||
|
|
||||||
let game = new Engine()
|
let game = Engine
|
||||||
let env = new Environment()
|
let env = new Environment()
|
||||||
let gui = new GUIRenderer()
|
let gui = new GUIRenderer()
|
||||||
let fnt = new FontRenderer()
|
let fnt = new FontRenderer()
|
||||||
@ -21,9 +22,14 @@ async function pipeline () {
|
|||||||
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)
|
let skyboxShader = await game.shaders.createShaderFromFiles(game.gl, 'skybox', false)
|
||||||
|
// let waterShader = await game.shaders.createShaderFromFiles(game.gl, 'water', false)
|
||||||
|
|
||||||
entity.setRotation([0.0, 0.0, -90.0])
|
entity.setRotation([0.0, 0.0, -90.0])
|
||||||
|
|
||||||
|
// let water = new WaterTile([100.0, 0.0, 100.0], 100.0)
|
||||||
|
// water.initialize(game.gl)
|
||||||
|
// await water.useDUDV(game.gl, 'dudv')
|
||||||
|
|
||||||
let arialFont = await Font.fromFile('arial')
|
let arialFont = await Font.fromFile('arial')
|
||||||
await arialFont.loadTextures(game.gl)
|
await arialFont.loadTextures(game.gl)
|
||||||
|
|
||||||
@ -33,10 +39,12 @@ async function pipeline () {
|
|||||||
|
|
||||||
let itms = [
|
let itms = [
|
||||||
new GUIImage(await Texture.createTexture2D(game.gl, await Resource.loadImage('noisy.png'), false, game.gl.LINEAR),
|
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)),
|
new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0))
|
||||||
new GUIText('this is example text!\nmulti line!', arialFont, 2, new Dim4(0.1, 0.0, -0.2, 0.0), new Dim4(1.0, 0.0, 0.3, 0.0), true)
|
|
||||||
]
|
]
|
||||||
itms[1].color = [1.0, 0.0, 0.2]
|
// Nesting test
|
||||||
|
itms[0].addChild(new GUIText('this is example text!\nmulti line!', arialFont, 1.5, new Dim4(0.1, 0.0, -0.1, 0.0), new Dim4(1.0, 0.0, 0.3, 0.0), false))
|
||||||
|
itms[0].children[0].color = [1.0, 0.0, 0.2]
|
||||||
|
itms[0].updateTransform()
|
||||||
|
|
||||||
// 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)
|
||||||
@ -58,7 +66,7 @@ async function pipeline () {
|
|||||||
terrain.setMaterial(material)
|
terrain.setMaterial(material)
|
||||||
|
|
||||||
// Create and initialize the camera
|
// Create and initialize the camera
|
||||||
let cam = new Camera([-200.0, 1.0, 0.0])
|
let cam = new Camera([-32.0, 100.0, -32.0], [0.8, -0.6, 0.0])
|
||||||
cam.updateProjection(game.gl)
|
cam.updateProjection(game.gl)
|
||||||
|
|
||||||
// Create skybox
|
// Create skybox
|
||||||
@ -67,6 +75,9 @@ async function pipeline () {
|
|||||||
// Load textures and generate a mesh
|
// Load textures and generate a mesh
|
||||||
await skybox.initialize(game.gl)
|
await skybox.initialize(game.gl)
|
||||||
|
|
||||||
|
// itms.push(new GUIImage(water.fbos.reflectionTexture, new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)))
|
||||||
|
// itms.push(new GUIImage(water.fbos.refractionTexture, new Dim4(-0.3, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)))
|
||||||
|
|
||||||
// Update function for camera and terrain
|
// Update function for camera and terrain
|
||||||
game.addUpdateFunction(function (dt) {
|
game.addUpdateFunction(function (dt) {
|
||||||
if (game.input.isDown('w')) {
|
if (game.input.isDown('w')) {
|
||||||
@ -91,8 +102,9 @@ async function pipeline () {
|
|||||||
terrain.updateLODMesh(game.gl)
|
terrain.updateLODMesh(game.gl)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Render function for the triangle
|
function drawEverything (gl) {
|
||||||
game.addRenderFunction(function (gl) {
|
game.prepare()
|
||||||
|
|
||||||
shader.use(gl)
|
shader.use(gl)
|
||||||
cam.draw(gl, shader)
|
cam.draw(gl, shader)
|
||||||
entity.draw(gl, shader)
|
entity.draw(gl, shader)
|
||||||
@ -108,14 +120,26 @@ async function pipeline () {
|
|||||||
|
|
||||||
// Draw terrain
|
// Draw terrain
|
||||||
terrain.draw(gl, terrainShader)
|
terrain.draw(gl, terrainShader)
|
||||||
|
|
||||||
// Draw the skybox
|
// Draw the skybox
|
||||||
skyboxShader.use(gl)
|
skyboxShader.use(gl)
|
||||||
skybox.draw(gl, skyboxShader, cam)
|
skybox.draw(gl, skyboxShader, cam)
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// Render function for the triangle
|
||||||
game.addRenderFunction(function (gl) {
|
game.addRenderFunction(function (gl) {
|
||||||
gui.draw(gl, itms)
|
// water.reflect(gl, cam, drawEverything)
|
||||||
fnt.draw(gl, itms)
|
// water.refract(gl, cam, drawEverything)
|
||||||
|
|
||||||
|
drawEverything(gl)
|
||||||
|
|
||||||
|
// waterShader.use(gl)
|
||||||
|
// cam.draw(gl, waterShader)
|
||||||
|
// water.draw(gl, waterShader)
|
||||||
|
|
||||||
|
// Draw GUIs
|
||||||
|
gui.draw(gl, cam, itms)
|
||||||
|
fnt.draw(gl, cam, itms)
|
||||||
})
|
})
|
||||||
|
|
||||||
game.startGameLoop()
|
game.startGameLoop()
|
||||||
|
Loading…
Reference in New Issue
Block a user