UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

133 lines (132 loc) 5.8 kB
"use strict"; import { Color, FrontSide, Matrix4, ShaderMaterial, UniformsLib, UniformsUtils, Vector3 } from "three"; import { BaseReflector } from "./_BaseReflector"; import VERTEX from "./water/vert.glsl"; import FRAGMENT from "./water/frag.glsl"; export class Water extends BaseReflector { constructor(geometry, _options) { super(geometry, _options); this._options = _options; this.isWater = true; // private _renderReflection = true; this._mirrorCameraMultipliedByMatrixWorld = false; } _createMaterial() { const options = this._options; const alpha = options.alpha !== void 0 ? options.alpha : 1; const timeScale = options.timeScale !== void 0 ? options.timeScale : 1; const size = options.size !== void 0 ? options.size : 0; const direction = options.direction !== void 0 ? options.direction : new Vector3(0, 1, 0); const sunDirection = options.sunDirection !== void 0 ? options.sunDirection : new Vector3(0.70707, 0.70707, 0); const sunColor = new Color(options.sunColor !== void 0 ? options.sunColor : 16777215); const wavesHeight = options.wavesHeight !== void 0 ? options.wavesHeight : 1; const waterColor = new Color(options.waterColor !== void 0 ? options.waterColor : 8355711); const reflectionColor = new Color(options.reflectionColor !== void 0 ? options.reflectionColor : 16777215); const reflectionFresnel = options.reflectionFresnel !== void 0 ? options.reflectionFresnel : 1; const distortionScale = options.distortionScale !== void 0 ? options.distortionScale : 20; const side = options.side !== void 0 ? options.side : FrontSide; const useFog = options.useFog !== void 0 ? options.useFog : false; const normalBias = options.normalBias !== void 0 ? options.normalBias : 1e-3; const mirrorShader = { uniforms: UniformsUtils.merge([ UniformsLib["fog"], UniformsLib["lights"], { mirrorSampler: { value: null }, alpha: { value: 1 }, time: { value: 0 }, // do not assign time uniform here, as the uniforms as cloned shortly after timeScale: { value: 1 }, size: { value: 1 }, distortionScale: { value: 20 }, textureMatrix: { value: new Matrix4() }, sunColor: { value: new Color(8355711) }, sunDirection: { value: new Vector3(0.70707, 0.70707, 0) }, direction: { value: new Vector3().copy(BaseReflector.REFLECTOR_DEFAULT_UP) }, eye: { value: new Vector3() }, wavesHeight: { value: wavesHeight }, waterColor: { value: new Color(5592405) }, reflectionColor: { value: new Color(16777215) }, reflectionFresnel: { value: 1 }, normalBias: { value: normalBias } } ]), vertexShader: VERTEX, fragmentShader: FRAGMENT }; const material = new ShaderMaterial({ fragmentShader: mirrorShader.fragmentShader, vertexShader: mirrorShader.vertexShader, uniforms: UniformsUtils.clone(mirrorShader.uniforms), lights: true, side // fog: useFog, // transparent: true, // TODO: allow transparency when I have a good alpha model }); material.fog = useFog; material.uniforms["time"] = this._options.polyScene.timeController.timeUniform(); material.uniforms["timeScale"].value = timeScale; material.uniforms["size"].value = size; material.uniforms["textureMatrix"].value = this.textureMatrix; material.uniforms["alpha"].value = alpha; material.uniforms["sunColor"].value = sunColor; material.uniforms["wavesHeight"].value = wavesHeight; material.uniforms["waterColor"].value = waterColor; material.uniforms["reflectionColor"].value = reflectionColor; material.uniforms["reflectionFresnel"].value = reflectionFresnel; material.uniforms["direction"].value = direction; material.uniforms["sunDirection"].value = sunDirection; material.uniforms["distortionScale"].value = distortionScale; material.uniforms["normalBias"].value = normalBias; material.uniforms["eye"].value = new Vector3(); return material; } _assignMaterialRenderTarget() { if (this.renderTarget) { this.material.uniforms["mirrorSampler"].value = this.renderTarget.texture; } } _onBeforeRender(renderer, scene, anyCamera) { super._onBeforeRender(renderer, scene, anyCamera); if (this.material) { this.material.uniforms["eye"].value.setFromMatrixPosition(anyCamera.matrixWorld); } } setReflectionActive(state) { this._options.active = state; if (state) { if (this.renderTarget) { this.material.uniforms["mirrorSampler"].value = this.renderTarget.texture; } } else { this.material.uniforms["mirrorSampler"].value = null; } } // override clone(recursive: boolean): this { // // we clone so that a cloned reflector does not share the same color // const clonedOptions = {...this._options}; // clonedOptions.sunDirection = this._options.sunDirection?.clone(); // clonedOptions.sunColor = this._options.sunColor?.clone(); // clonedOptions.waterColor = this._options.waterColor?.clone(); // const clonedGeometry = this.geometry.clone(); // const clonedWater = new Water(clonedGeometry, clonedOptions); // const material: WaterMaterial = clonedWater.material; // clonedWater.copy(this, recursive); // // the material and geometry needs to be added back after the copy, as Mesh.copy would override that // clonedWater.material = material; // clonedWater.geometry = clonedGeometry; // // TODO: // // - size is not passed correctly // // - make time dependent to update the time uniform attribute // clonedWater.updateMatrix(); // return clonedWater as this; // } }