@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
133 lines (132 loc) • 5.8 kB
JavaScript
"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;
// }
}