UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

216 lines (161 loc) 5.75 kB
import { ClampToEdgeWrapping, DataTexture, FloatType, LinearFilter, RedFormat } from "three"; import { BvhClient } from "../../../../core/bvh2/bvh3/BvhClient.js"; import { Color } from "../../../../core/color/Color.js"; import Vector1 from "../../../../core/geom/Vector1.js"; import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js"; import { threeUpdateTransform } from "../../util/threeUpdateTransform.js"; import { WATER_SIZE } from "./WATER_SIZE.js"; class Water { level = new Vector1(0); /** * * @type {Color} */ color = new Color(0, 0.3, 0.5); /** * Defines what is considered as shore as well as how long is the transition between shore and deep water * @type {NumericInterval} */ shoreDepthTransition = new NumericInterval(0.7, 2); /** * Color of the water at the shore * @type {Color} */ shoreColor = new Color(0.584, 0.792, 0.850); /** * * @type {Vector1} */ waveSpeed = new Vector1(1.8); /** * * @type {Vector1} */ waveAmplitude = new Vector1(0.3); /** * * @type {Vector1} */ waveFrequency = new Vector1(1); /** * Scattering of light, the higher this value is - the more opaque water will become * @type {Vector1} */ scattering = new Vector1(1.2); bvh = new BvhClient(); constructor(options) { if (options !== undefined) { console.error('Constructor options are deprecated'); this.fromJSON(options); } /** * * @type {ShaderMaterial} */ this.__shader = null; /** * * @type {Object3D} * @private */ this.__threeObject = null; // monitor changes this.color.onChanged.add(this.writeShaderUniforms, this); this.shoreDepthTransition.onChanged.add(this.writeShaderUniforms, this); this.shoreColor.onChanged.add(this.writeShaderUniforms, this); this.waveSpeed.onChanged.add(this.writeShaderUniforms, this); this.waveAmplitude.onChanged.add(this.writeShaderUniforms, this); this.waveFrequency.onChanged.add(this.writeShaderUniforms, this); this.scattering.onChanged.add(this.writeShaderUniforms, this); } updateTransform() { const width = WATER_SIZE; const height = WATER_SIZE; const mesh = this.__threeObject; if (mesh !== null) { mesh.rotation.x = Math.PI * 0.5; mesh.position.x = width / 4; mesh.position.z = height / 4; mesh.position.y = this.level.getValue(); threeUpdateTransform(mesh); } this.updateBounds(); } updateBounds() { const width = WATER_SIZE; const height = WATER_SIZE; const level = this.level.getValue(); this.bvh.resize( -width / 4, level, -height / 4, width * (3 / 4), level, height * (3 / 4) ); } /** * * @param {Terrain} terrain * @param {number} waterSize */ updateShaderForTerrain(terrain, waterSize) { const shader = this.__shader; if (shader === null) { return; } const tW = terrain.size.x * terrain.gridScale; const tH = terrain.size.y * terrain.gridScale; const heightTexture = new DataTexture(terrain.samplerHeight.data, terrain.samplerHeight.width, terrain.samplerHeight.height, RedFormat, FloatType); heightTexture.wrapS = ClampToEdgeWrapping; heightTexture.wrapT = ClampToEdgeWrapping; heightTexture.generateMipmaps = false; heightTexture.minFilter = LinearFilter; heightTexture.magFilter = LinearFilter; heightTexture.flipY = false; heightTexture.internalFormat = 'R32F'; shader.uniforms.tHeightTexture.value = heightTexture; shader.uniforms.vHeightUv.value.set( -0.25, -0.25, (waterSize / tW), (waterSize / tH) ); shader.uniforms.vHeightTextureResolution.value.set(terrain.samplerHeight.width, terrain.samplerHeight.height); } writeShaderUniforms() { /** * * @type {ShaderMaterial} */ const shader = this.__shader; if (shader === null) { //no shader attached return; } const uniforms = shader.uniforms; uniforms.waterColor.value.setRGB(this.color.r, this.color.g, this.color.b); uniforms.shoreColor.value.setRGB(this.shoreColor.r, this.shoreColor.g, this.shoreColor.b); uniforms.fWaveSpeed.value = this.waveSpeed.getValue(); uniforms.fWaveAmplitude.value = this.waveAmplitude.getValue(); uniforms.fWaveFrequency.value = this.waveFrequency.getValue(); uniforms.fScattering.value = this.scattering.getValue(); uniforms.vShoreDepthTransition.value.set(this.shoreDepthTransition.min, this.shoreDepthTransition.max); } fromJSON(json) { if (typeof json.level === 'number') { this.level.fromJSON(json.level); } if (typeof json.color === 'object') { this.color.fromJSON(json.color); } } toJSON() { return { level: this.level.toJSON(), color: this.color.toJSON() }; } } Water.typeName = "Water"; export default Water;