mirror of https://gitee.com/cf-fz/WebCAD.git
pull/821/MERGE
parent
69d19ca74b
commit
10c3f32a3d
@ -1,265 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Slayvin / http://slayvin.net
|
|
||||||
*/
|
|
||||||
|
|
||||||
THREE.Reflector = function (width, height, options)
|
|
||||||
{
|
|
||||||
|
|
||||||
THREE.Mesh.call(this, new THREE.PlaneBufferGeometry(width, height));
|
|
||||||
|
|
||||||
this.type = 'Reflector';
|
|
||||||
|
|
||||||
var scope = this;
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var color = (options.color !== undefined) ? new THREE.Color(options.color) : new THREE.Color(0x7F7F7F);
|
|
||||||
var textureWidth = options.textureWidth || 512;
|
|
||||||
var textureHeight = options.textureHeight || 512;
|
|
||||||
var clipBias = options.clipBias || 0;
|
|
||||||
var shader = options.shader || THREE.Reflector.ReflectorShader;
|
|
||||||
var recursion = options.recursion !== undefined ? options.recursion : 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
var reflectorPlane = new THREE.Plane();
|
|
||||||
var normal = new THREE.Vector3();
|
|
||||||
var reflectorWorldPosition = new THREE.Vector3();
|
|
||||||
var cameraWorldPosition = new THREE.Vector3();
|
|
||||||
var rotationMatrix = new THREE.Matrix4();
|
|
||||||
var lookAtPosition = new THREE.Vector3(0, 0, - 1);
|
|
||||||
var clipPlane = new THREE.Vector4();
|
|
||||||
var viewport = new THREE.Vector4();
|
|
||||||
|
|
||||||
var view = new THREE.Vector3();
|
|
||||||
var target = new THREE.Vector3();
|
|
||||||
var q = new THREE.Vector4();
|
|
||||||
|
|
||||||
var textureMatrix = new THREE.Matrix4();
|
|
||||||
var virtualCamera = new THREE.PerspectiveCamera();
|
|
||||||
|
|
||||||
var parameters = {
|
|
||||||
minFilter: THREE.LinearFilter,
|
|
||||||
magFilter: THREE.LinearFilter,
|
|
||||||
format: THREE.RGBFormat,
|
|
||||||
stencilBuffer: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var renderTarget = new THREE.WebGLRenderTarget(textureWidth, textureHeight, parameters);
|
|
||||||
|
|
||||||
if (!THREE.Math.isPowerOfTwo(textureWidth) || !THREE.Math.isPowerOfTwo(textureHeight)) {
|
|
||||||
|
|
||||||
renderTarget.texture.generateMipmaps = false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var material = new THREE.ShaderMaterial({
|
|
||||||
uniforms: THREE.UniformsUtils.clone(shader.uniforms),
|
|
||||||
fragmentShader: shader.fragmentShader,
|
|
||||||
vertexShader: shader.vertexShader,
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
material.uniforms.tDiffuse.value = renderTarget.texture;
|
|
||||||
material.uniforms.color.value = color;
|
|
||||||
material.uniforms.textureMatrix.value = textureMatrix;
|
|
||||||
|
|
||||||
this.material = material;
|
|
||||||
|
|
||||||
this.onBeforeRender = function (renderer, scene, camera)
|
|
||||||
{
|
|
||||||
|
|
||||||
if ('recursion' in camera.userData) {
|
|
||||||
|
|
||||||
if (camera.userData.recursion === recursion) return;
|
|
||||||
|
|
||||||
camera.userData.recursion++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
reflectorWorldPosition.setFromMatrixPosition(scope.matrixWorld);
|
|
||||||
cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
|
|
||||||
|
|
||||||
rotationMatrix.extractRotation(scope.matrixWorld);
|
|
||||||
|
|
||||||
normal.set(0, 0, 1);
|
|
||||||
normal.applyMatrix4(rotationMatrix);
|
|
||||||
|
|
||||||
view.subVectors(reflectorWorldPosition, cameraWorldPosition);
|
|
||||||
|
|
||||||
// Avoid rendering when reflector is facing away
|
|
||||||
|
|
||||||
if (view.dot(normal) > 0) return;
|
|
||||||
|
|
||||||
view.reflect(normal).negate();
|
|
||||||
view.add(reflectorWorldPosition);
|
|
||||||
|
|
||||||
rotationMatrix.extractRotation(camera.matrixWorld);
|
|
||||||
|
|
||||||
lookAtPosition.set(0, 0, - 1);
|
|
||||||
lookAtPosition.applyMatrix4(rotationMatrix);
|
|
||||||
lookAtPosition.add(cameraWorldPosition);
|
|
||||||
|
|
||||||
target.subVectors(reflectorWorldPosition, lookAtPosition);
|
|
||||||
target.reflect(normal).negate();
|
|
||||||
target.add(reflectorWorldPosition);
|
|
||||||
|
|
||||||
virtualCamera.position.copy(view);
|
|
||||||
virtualCamera.up.set(0, 1, 0);
|
|
||||||
virtualCamera.up.applyMatrix4(rotationMatrix);
|
|
||||||
virtualCamera.up.reflect(normal);
|
|
||||||
virtualCamera.lookAt(target);
|
|
||||||
|
|
||||||
virtualCamera.far = camera.far; // Used in WebGLBackground
|
|
||||||
|
|
||||||
virtualCamera.updateMatrixWorld();
|
|
||||||
virtualCamera.projectionMatrix.copy(camera.projectionMatrix);
|
|
||||||
|
|
||||||
virtualCamera.userData.recursion = 0;
|
|
||||||
|
|
||||||
// Update the texture matrix
|
|
||||||
textureMatrix.set(
|
|
||||||
0.5, 0.0, 0.0, 0.5,
|
|
||||||
0.0, 0.5, 0.0, 0.5,
|
|
||||||
0.0, 0.0, 0.5, 0.5,
|
|
||||||
0.0, 0.0, 0.0, 1.0
|
|
||||||
);
|
|
||||||
textureMatrix.multiply(virtualCamera.projectionMatrix);
|
|
||||||
textureMatrix.multiply(virtualCamera.matrixWorldInverse);
|
|
||||||
textureMatrix.multiply(scope.matrixWorld);
|
|
||||||
|
|
||||||
// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
|
|
||||||
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
|
|
||||||
reflectorPlane.setFromNormalAndCoplanarPoint(normal, reflectorWorldPosition);
|
|
||||||
reflectorPlane.applyMatrix4(virtualCamera.matrixWorldInverse);
|
|
||||||
|
|
||||||
clipPlane.set(reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant);
|
|
||||||
|
|
||||||
var projectionMatrix = virtualCamera.projectionMatrix;
|
|
||||||
|
|
||||||
q.x = (Math.sign(clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
|
|
||||||
q.y = (Math.sign(clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
|
|
||||||
q.z = - 1.0;
|
|
||||||
q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
|
|
||||||
|
|
||||||
// Calculate the scaled plane vector
|
|
||||||
clipPlane.multiplyScalar(2.0 / clipPlane.dot(q));
|
|
||||||
|
|
||||||
// Replacing the third row of the projection matrix
|
|
||||||
projectionMatrix.elements[2] = clipPlane.x;
|
|
||||||
projectionMatrix.elements[6] = clipPlane.y;
|
|
||||||
projectionMatrix.elements[10] = clipPlane.z + 1.0 - clipBias;
|
|
||||||
projectionMatrix.elements[14] = clipPlane.w;
|
|
||||||
|
|
||||||
// Render
|
|
||||||
|
|
||||||
scope.visible = false;
|
|
||||||
|
|
||||||
var currentRenderTarget = renderer.getRenderTarget();
|
|
||||||
|
|
||||||
var currentVrEnabled = renderer.vr.enabled;
|
|
||||||
var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
|
||||||
|
|
||||||
renderer.vr.enabled = false; // Avoid camera modification and recursion
|
|
||||||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
|
|
||||||
|
|
||||||
renderer.render(scene, virtualCamera, renderTarget, true);
|
|
||||||
|
|
||||||
renderer.vr.enabled = currentVrEnabled;
|
|
||||||
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
|
||||||
|
|
||||||
renderer.setRenderTarget(currentRenderTarget);
|
|
||||||
|
|
||||||
// Restore viewport
|
|
||||||
|
|
||||||
var bounds = camera.bounds;
|
|
||||||
|
|
||||||
if (bounds !== undefined) {
|
|
||||||
|
|
||||||
var size = renderer.getSize();
|
|
||||||
var pixelRatio = renderer.getPixelRatio();
|
|
||||||
|
|
||||||
viewport.x = bounds.x * size.width * pixelRatio;
|
|
||||||
viewport.y = bounds.y * size.height * pixelRatio;
|
|
||||||
viewport.z = bounds.z * size.width * pixelRatio;
|
|
||||||
viewport.w = bounds.w * size.height * pixelRatio;
|
|
||||||
|
|
||||||
renderer.state.viewport(viewport);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.visible = true;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
this.getRenderTarget = function ()
|
|
||||||
{
|
|
||||||
|
|
||||||
return renderTarget;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
THREE.Reflector.prototype = Object.create(THREE.Mesh.prototype);
|
|
||||||
THREE.Reflector.prototype.constructor = THREE.Reflector;
|
|
||||||
|
|
||||||
THREE.Reflector.ReflectorShader = {
|
|
||||||
|
|
||||||
uniforms: {
|
|
||||||
|
|
||||||
'color': {
|
|
||||||
type: 'c',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'tDiffuse': {
|
|
||||||
type: 't',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'textureMatrix': {
|
|
||||||
type: 'm4',
|
|
||||||
value: null
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
vertexShader: [
|
|
||||||
'uniform mat4 textureMatrix;',
|
|
||||||
'varying vec4 vUv;',
|
|
||||||
|
|
||||||
'void main() {',
|
|
||||||
|
|
||||||
' vUv = textureMatrix * vec4( position, 1.0 );',
|
|
||||||
|
|
||||||
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
|
|
||||||
|
|
||||||
'}'
|
|
||||||
].join('\n'),
|
|
||||||
|
|
||||||
fragmentShader: [
|
|
||||||
'uniform vec3 color;',
|
|
||||||
'uniform sampler2D tDiffuse;',
|
|
||||||
'varying vec4 vUv;',
|
|
||||||
|
|
||||||
'float blendOverlay( float base, float blend ) {',
|
|
||||||
|
|
||||||
' return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );',
|
|
||||||
|
|
||||||
'}',
|
|
||||||
|
|
||||||
'vec3 blendOverlay( vec3 base, vec3 blend ) {',
|
|
||||||
|
|
||||||
' return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );',
|
|
||||||
|
|
||||||
'}',
|
|
||||||
|
|
||||||
'void main() {',
|
|
||||||
|
|
||||||
' vec4 base = texture2DProj( tDiffuse, vUv );',
|
|
||||||
' gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );',
|
|
||||||
|
|
||||||
'}'
|
|
||||||
].join('\n')
|
|
||||||
};
|
|
@ -1,10 +0,0 @@
|
|||||||
THREE.ReflectorRTT = function (width, height, options)
|
|
||||||
{
|
|
||||||
|
|
||||||
THREE.Reflector.call(this, width, height, options);
|
|
||||||
|
|
||||||
this.geometry.setDrawRange(0, 0); // avoid rendering geometry
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
THREE.ReflectorRTT.prototype = Object.create(THREE.Reflector.prototype);
|
|
@ -1,72 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author erichlof / http://github.com/erichlof
|
|
||||||
*
|
|
||||||
* A shadow Mesh that follows a shadow-casting Mesh in the scene, but is confined to a single plane.
|
|
||||||
*/
|
|
||||||
|
|
||||||
THREE.ShadowMesh = function (mesh)
|
|
||||||
{
|
|
||||||
|
|
||||||
var shadowMaterial = new THREE.MeshBasicMaterial({
|
|
||||||
|
|
||||||
color: 0x000000,
|
|
||||||
transparent: true,
|
|
||||||
opacity: 0.6,
|
|
||||||
depthWrite: false
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
THREE.Mesh.call(this, mesh.geometry, shadowMaterial);
|
|
||||||
|
|
||||||
this.meshMatrix = mesh.matrixWorld;
|
|
||||||
|
|
||||||
this.frustumCulled = false;
|
|
||||||
this.matrixAutoUpdate = false;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
THREE.ShadowMesh.prototype = Object.create(THREE.Mesh.prototype);
|
|
||||||
THREE.ShadowMesh.prototype.constructor = THREE.ShadowMesh;
|
|
||||||
|
|
||||||
THREE.ShadowMesh.prototype.update = function ()
|
|
||||||
{
|
|
||||||
|
|
||||||
var shadowMatrix = new THREE.Matrix4();
|
|
||||||
|
|
||||||
return function (plane, lightPosition4D)
|
|
||||||
{
|
|
||||||
|
|
||||||
// based on https://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm
|
|
||||||
|
|
||||||
var dot = plane.normal.x * lightPosition4D.x +
|
|
||||||
plane.normal.y * lightPosition4D.y +
|
|
||||||
plane.normal.z * lightPosition4D.z +
|
|
||||||
- plane.constant * lightPosition4D.w;
|
|
||||||
|
|
||||||
var sme = shadowMatrix.elements;
|
|
||||||
|
|
||||||
sme[0] = dot - lightPosition4D.x * plane.normal.x;
|
|
||||||
sme[4] = - lightPosition4D.x * plane.normal.y;
|
|
||||||
sme[8] = - lightPosition4D.x * plane.normal.z;
|
|
||||||
sme[12] = - lightPosition4D.x * - plane.constant;
|
|
||||||
|
|
||||||
sme[1] = - lightPosition4D.y * plane.normal.x;
|
|
||||||
sme[5] = dot - lightPosition4D.y * plane.normal.y;
|
|
||||||
sme[9] = - lightPosition4D.y * plane.normal.z;
|
|
||||||
sme[13] = - lightPosition4D.y * - plane.constant;
|
|
||||||
|
|
||||||
sme[2] = - lightPosition4D.z * plane.normal.x;
|
|
||||||
sme[6] = - lightPosition4D.z * plane.normal.y;
|
|
||||||
sme[10] = dot - lightPosition4D.z * plane.normal.z;
|
|
||||||
sme[14] = - lightPosition4D.z * - plane.constant;
|
|
||||||
|
|
||||||
sme[3] = - lightPosition4D.w * plane.normal.x;
|
|
||||||
sme[7] = - lightPosition4D.w * plane.normal.y;
|
|
||||||
sme[11] = - lightPosition4D.w * plane.normal.z;
|
|
||||||
sme[15] = dot - lightPosition4D.w * - plane.constant;
|
|
||||||
|
|
||||||
this.matrix.multiplyMatrices(shadowMatrix, this.meshMatrix);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}();
|
|
@ -1,311 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author jbouny / https://github.com/jbouny
|
|
||||||
*
|
|
||||||
* Work based on :
|
|
||||||
* @author Slayvin / http://slayvin.net : Flat mirror for three.js
|
|
||||||
* @author Stemkoski / http://www.adelphi.edu/~stemkoski : An implementation of water shader based on the flat mirror
|
|
||||||
* @author Jonas Wagner / http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
|
|
||||||
*/
|
|
||||||
|
|
||||||
THREE.Water = function (width, height, options)
|
|
||||||
{
|
|
||||||
|
|
||||||
THREE.Mesh.call(this, new THREE.PlaneBufferGeometry(width, height));
|
|
||||||
|
|
||||||
var scope = this;
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
|
|
||||||
var textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512;
|
|
||||||
|
|
||||||
var clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
|
|
||||||
var alpha = options.alpha !== undefined ? options.alpha : 1.0;
|
|
||||||
var time = options.time !== undefined ? options.time : 0.0;
|
|
||||||
var normalSampler = options.waterNormals !== undefined ? options.waterNormals : null;
|
|
||||||
var sunDirection = options.sunDirection !== undefined ? options.sunDirection : new THREE.Vector3(0.70707, 0.70707, 0.0);
|
|
||||||
var sunColor = new THREE.Color(options.sunColor !== undefined ? options.sunColor : 0xffffff);
|
|
||||||
var waterColor = new THREE.Color(options.waterColor !== undefined ? options.waterColor : 0x7F7F7F);
|
|
||||||
var eye = options.eye !== undefined ? options.eye : new THREE.Vector3(0, 0, 0);
|
|
||||||
var distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0;
|
|
||||||
var side = options.side !== undefined ? options.side : THREE.FrontSide;
|
|
||||||
var fog = options.fog !== undefined ? options.fog : false;
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
var mirrorPlane = new THREE.Plane();
|
|
||||||
var normal = new THREE.Vector3();
|
|
||||||
var mirrorWorldPosition = new THREE.Vector3();
|
|
||||||
var cameraWorldPosition = new THREE.Vector3();
|
|
||||||
var rotationMatrix = new THREE.Matrix4();
|
|
||||||
var lookAtPosition = new THREE.Vector3(0, 0, - 1);
|
|
||||||
var clipPlane = new THREE.Vector4();
|
|
||||||
|
|
||||||
var view = new THREE.Vector3();
|
|
||||||
var target = new THREE.Vector3();
|
|
||||||
var q = new THREE.Vector4();
|
|
||||||
|
|
||||||
var textureMatrix = new THREE.Matrix4();
|
|
||||||
|
|
||||||
var mirrorCamera = new THREE.PerspectiveCamera();
|
|
||||||
|
|
||||||
var parameters = {
|
|
||||||
minFilter: THREE.LinearFilter,
|
|
||||||
magFilter: THREE.LinearFilter,
|
|
||||||
format: THREE.RGBFormat,
|
|
||||||
stencilBuffer: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var renderTarget = new THREE.WebGLRenderTarget(textureWidth, textureHeight, parameters);
|
|
||||||
|
|
||||||
if (!THREE.Math.isPowerOfTwo(textureWidth) || !THREE.Math.isPowerOfTwo(textureHeight)) {
|
|
||||||
|
|
||||||
renderTarget.texture.generateMipmaps = false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var mirrorShader = {
|
|
||||||
|
|
||||||
uniforms: THREE.UniformsUtils.merge([
|
|
||||||
THREE.UniformsLib['fog'],
|
|
||||||
THREE.UniformsLib['lights'],
|
|
||||||
{
|
|
||||||
normalSampler: { value: null },
|
|
||||||
mirrorSampler: { value: null },
|
|
||||||
alpha: { value: 1.0 },
|
|
||||||
time: { value: 0.0 },
|
|
||||||
size: { value: 1.0 },
|
|
||||||
distortionScale: { value: 20.0 },
|
|
||||||
noiseScale: { value: 1.0 },
|
|
||||||
textureMatrix: { value: new THREE.Matrix4() },
|
|
||||||
sunColor: { value: new THREE.Color(0x7F7F7F) },
|
|
||||||
sunDirection: { value: new THREE.Vector3(0.70707, 0.70707, 0) },
|
|
||||||
eye: { value: new THREE.Vector3() },
|
|
||||||
waterColor: { value: new THREE.Color(0x555555) }
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
|
|
||||||
vertexShader: [
|
|
||||||
'uniform mat4 textureMatrix;',
|
|
||||||
'uniform float time;',
|
|
||||||
|
|
||||||
'varying vec4 mirrorCoord;',
|
|
||||||
'varying vec4 worldPosition;',
|
|
||||||
|
|
||||||
THREE.ShaderChunk['fog_pars_vertex'],
|
|
||||||
THREE.ShaderChunk['shadowmap_pars_vertex'],
|
|
||||||
|
|
||||||
'void main() {',
|
|
||||||
' mirrorCoord = modelMatrix * vec4( position, 1.0 );',
|
|
||||||
' worldPosition = mirrorCoord.xyzw;',
|
|
||||||
' mirrorCoord = textureMatrix * mirrorCoord;',
|
|
||||||
' vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );',
|
|
||||||
' gl_Position = projectionMatrix * mvPosition;',
|
|
||||||
|
|
||||||
THREE.ShaderChunk['fog_vertex'],
|
|
||||||
THREE.ShaderChunk['shadowmap_vertex'],
|
|
||||||
|
|
||||||
'}'
|
|
||||||
].join('\n'),
|
|
||||||
|
|
||||||
fragmentShader: [
|
|
||||||
'uniform sampler2D mirrorSampler;',
|
|
||||||
'uniform float alpha;',
|
|
||||||
'uniform float time;',
|
|
||||||
'uniform float size;',
|
|
||||||
'uniform float distortionScale;',
|
|
||||||
'uniform sampler2D normalSampler;',
|
|
||||||
'uniform vec3 sunColor;',
|
|
||||||
'uniform vec3 sunDirection;',
|
|
||||||
'uniform vec3 eye;',
|
|
||||||
'uniform vec3 waterColor;',
|
|
||||||
|
|
||||||
'varying vec4 mirrorCoord;',
|
|
||||||
'varying vec4 worldPosition;',
|
|
||||||
|
|
||||||
'vec4 getNoise( vec2 uv ) {',
|
|
||||||
' vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);',
|
|
||||||
' vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );',
|
|
||||||
' vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );',
|
|
||||||
' vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );',
|
|
||||||
' vec4 noise = texture2D( normalSampler, uv0 ) +',
|
|
||||||
' texture2D( normalSampler, uv1 ) +',
|
|
||||||
' texture2D( normalSampler, uv2 ) +',
|
|
||||||
' texture2D( normalSampler, uv3 );',
|
|
||||||
' return noise * 0.5 - 1.0;',
|
|
||||||
'}',
|
|
||||||
|
|
||||||
'void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) {',
|
|
||||||
' vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );',
|
|
||||||
' float direction = max( 0.0, dot( eyeDirection, reflection ) );',
|
|
||||||
' specularColor += pow( direction, shiny ) * sunColor * spec;',
|
|
||||||
' diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;',
|
|
||||||
'}',
|
|
||||||
|
|
||||||
THREE.ShaderChunk['common'],
|
|
||||||
THREE.ShaderChunk['packing'],
|
|
||||||
THREE.ShaderChunk['bsdfs'],
|
|
||||||
THREE.ShaderChunk['fog_pars_fragment'],
|
|
||||||
THREE.ShaderChunk['lights_pars'],
|
|
||||||
THREE.ShaderChunk['shadowmap_pars_fragment'],
|
|
||||||
THREE.ShaderChunk['shadowmask_pars_fragment'],
|
|
||||||
|
|
||||||
'void main() {',
|
|
||||||
' vec4 noise = getNoise( worldPosition.xz * size );',
|
|
||||||
' vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );',
|
|
||||||
|
|
||||||
' vec3 diffuseLight = vec3(0.0);',
|
|
||||||
' vec3 specularLight = vec3(0.0);',
|
|
||||||
|
|
||||||
' vec3 worldToEye = eye-worldPosition.xyz;',
|
|
||||||
' vec3 eyeDirection = normalize( worldToEye );',
|
|
||||||
' sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );',
|
|
||||||
|
|
||||||
' float distance = length(worldToEye);',
|
|
||||||
|
|
||||||
' vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;',
|
|
||||||
' vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.z + distortion ) );',
|
|
||||||
|
|
||||||
' float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );',
|
|
||||||
' float rf0 = 0.3;',
|
|
||||||
' float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );',
|
|
||||||
' vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;',
|
|
||||||
' vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance);',
|
|
||||||
' vec3 outgoingLight = albedo;',
|
|
||||||
' gl_FragColor = vec4( outgoingLight, alpha );',
|
|
||||||
|
|
||||||
THREE.ShaderChunk['tonemapping_fragment'],
|
|
||||||
THREE.ShaderChunk['fog_fragment'],
|
|
||||||
|
|
||||||
'}'
|
|
||||||
].join('\n')
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var material = new THREE.ShaderMaterial({
|
|
||||||
fragmentShader: mirrorShader.fragmentShader,
|
|
||||||
vertexShader: mirrorShader.vertexShader,
|
|
||||||
uniforms: THREE.UniformsUtils.clone(mirrorShader.uniforms),
|
|
||||||
transparent: true,
|
|
||||||
lights: true,
|
|
||||||
side: side,
|
|
||||||
fog: fog
|
|
||||||
});
|
|
||||||
|
|
||||||
material.uniforms.mirrorSampler.value = renderTarget.texture;
|
|
||||||
material.uniforms.textureMatrix.value = textureMatrix;
|
|
||||||
material.uniforms.alpha.value = alpha;
|
|
||||||
material.uniforms.time.value = time;
|
|
||||||
material.uniforms.normalSampler.value = normalSampler;
|
|
||||||
material.uniforms.sunColor.value = sunColor;
|
|
||||||
material.uniforms.waterColor.value = waterColor;
|
|
||||||
material.uniforms.sunDirection.value = sunDirection;
|
|
||||||
material.uniforms.distortionScale.value = distortionScale;
|
|
||||||
|
|
||||||
material.uniforms.eye.value = eye;
|
|
||||||
|
|
||||||
scope.material = material;
|
|
||||||
|
|
||||||
scope.onBeforeRender = function (renderer, scene, camera)
|
|
||||||
{
|
|
||||||
|
|
||||||
mirrorWorldPosition.setFromMatrixPosition(scope.matrixWorld);
|
|
||||||
cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
|
|
||||||
|
|
||||||
rotationMatrix.extractRotation(scope.matrixWorld);
|
|
||||||
|
|
||||||
normal.set(0, 0, 1);
|
|
||||||
normal.applyMatrix4(rotationMatrix);
|
|
||||||
|
|
||||||
view.subVectors(mirrorWorldPosition, cameraWorldPosition);
|
|
||||||
|
|
||||||
// Avoid rendering when mirror is facing away
|
|
||||||
|
|
||||||
if (view.dot(normal) > 0) return;
|
|
||||||
|
|
||||||
view.reflect(normal).negate();
|
|
||||||
view.add(mirrorWorldPosition);
|
|
||||||
|
|
||||||
rotationMatrix.extractRotation(camera.matrixWorld);
|
|
||||||
|
|
||||||
lookAtPosition.set(0, 0, - 1);
|
|
||||||
lookAtPosition.applyMatrix4(rotationMatrix);
|
|
||||||
lookAtPosition.add(cameraWorldPosition);
|
|
||||||
|
|
||||||
target.subVectors(mirrorWorldPosition, lookAtPosition);
|
|
||||||
target.reflect(normal).negate();
|
|
||||||
target.add(mirrorWorldPosition);
|
|
||||||
|
|
||||||
mirrorCamera.position.copy(view);
|
|
||||||
mirrorCamera.up.set(0, 1, 0);
|
|
||||||
mirrorCamera.up.applyMatrix4(rotationMatrix);
|
|
||||||
mirrorCamera.up.reflect(normal);
|
|
||||||
mirrorCamera.lookAt(target);
|
|
||||||
|
|
||||||
mirrorCamera.far = camera.far; // Used in WebGLBackground
|
|
||||||
|
|
||||||
mirrorCamera.updateMatrixWorld();
|
|
||||||
mirrorCamera.projectionMatrix.copy(camera.projectionMatrix);
|
|
||||||
|
|
||||||
// Update the texture matrix
|
|
||||||
textureMatrix.set(
|
|
||||||
0.5, 0.0, 0.0, 0.5,
|
|
||||||
0.0, 0.5, 0.0, 0.5,
|
|
||||||
0.0, 0.0, 0.5, 0.5,
|
|
||||||
0.0, 0.0, 0.0, 1.0
|
|
||||||
);
|
|
||||||
textureMatrix.multiply(mirrorCamera.projectionMatrix);
|
|
||||||
textureMatrix.multiply(mirrorCamera.matrixWorldInverse);
|
|
||||||
|
|
||||||
// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
|
|
||||||
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
|
|
||||||
mirrorPlane.setFromNormalAndCoplanarPoint(normal, mirrorWorldPosition);
|
|
||||||
mirrorPlane.applyMatrix4(mirrorCamera.matrixWorldInverse);
|
|
||||||
|
|
||||||
clipPlane.set(mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant);
|
|
||||||
|
|
||||||
var projectionMatrix = mirrorCamera.projectionMatrix;
|
|
||||||
|
|
||||||
q.x = (Math.sign(clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
|
|
||||||
q.y = (Math.sign(clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
|
|
||||||
q.z = - 1.0;
|
|
||||||
q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
|
|
||||||
|
|
||||||
// Calculate the scaled plane vector
|
|
||||||
clipPlane.multiplyScalar(2.0 / clipPlane.dot(q));
|
|
||||||
|
|
||||||
// Replacing the third row of the projection matrix
|
|
||||||
projectionMatrix.elements[2] = clipPlane.x;
|
|
||||||
projectionMatrix.elements[6] = clipPlane.y;
|
|
||||||
projectionMatrix.elements[10] = clipPlane.z + 1.0 - clipBias;
|
|
||||||
projectionMatrix.elements[14] = clipPlane.w;
|
|
||||||
|
|
||||||
eye.setFromMatrixPosition(camera.matrixWorld);
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
var currentRenderTarget = renderer.getRenderTarget();
|
|
||||||
|
|
||||||
var currentVrEnabled = renderer.vr.enabled;
|
|
||||||
var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
|
|
||||||
|
|
||||||
scope.visible = false;
|
|
||||||
|
|
||||||
renderer.vr.enabled = false; // Avoid camera modification and recursion
|
|
||||||
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
|
|
||||||
|
|
||||||
renderer.render(scene, mirrorCamera, renderTarget, true);
|
|
||||||
|
|
||||||
scope.visible = true;
|
|
||||||
|
|
||||||
renderer.vr.enabled = currentVrEnabled;
|
|
||||||
renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
|
||||||
|
|
||||||
renderer.setRenderTarget(currentRenderTarget);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
THREE.Water.prototype = Object.create(THREE.Mesh.prototype);
|
|
||||||
THREE.Water.prototype.constructor = THREE.Water;
|
|
@ -1,341 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Mugen87 / https://github.com/Mugen87
|
|
||||||
*
|
|
||||||
* References:
|
|
||||||
* http://www.valvesoftware.com/publications/2010/siggraph2010_vlachos_waterflow.pdf
|
|
||||||
* http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
THREE.Water = function (width, height, options)
|
|
||||||
{
|
|
||||||
|
|
||||||
THREE.Mesh.call(this, new THREE.PlaneBufferGeometry(width, height));
|
|
||||||
|
|
||||||
this.type = 'Water';
|
|
||||||
|
|
||||||
var scope = this;
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var color = (options.color !== undefined) ? new THREE.Color(options.color) : new THREE.Color(0xFFFFFF);
|
|
||||||
var textureWidth = options.textureWidth || 512;
|
|
||||||
var textureHeight = options.textureHeight || 512;
|
|
||||||
var clipBias = options.clipBias || 0;
|
|
||||||
var flowDirection = options.flowDirection || new THREE.Vector2(1, 0);
|
|
||||||
var flowSpeed = options.flowSpeed || 0.03;
|
|
||||||
var reflectivity = options.reflectivity || 0.02;
|
|
||||||
var scale = options.scale || 1;
|
|
||||||
var shader = options.shader || THREE.Water.WaterShader;
|
|
||||||
|
|
||||||
var textureLoader = new THREE.TextureLoader();
|
|
||||||
|
|
||||||
var flowMap = options.flowMap || undefined;
|
|
||||||
var normalMap0 = options.normalMap0 || textureLoader.load('textures/water/Water_1_M_Normal.jpg');
|
|
||||||
var normalMap1 = options.normalMap1 || textureLoader.load('textures/water/Water_2_M_Normal.jpg');
|
|
||||||
|
|
||||||
var cycle = 0.15; // a cycle of a flow map phase
|
|
||||||
var halfCycle = cycle * 0.5;
|
|
||||||
var textureMatrix = new THREE.Matrix4();
|
|
||||||
var clock = new THREE.Clock();
|
|
||||||
|
|
||||||
// internal components
|
|
||||||
|
|
||||||
if (THREE.Reflector === undefined) {
|
|
||||||
|
|
||||||
console.error('THREE.Water: Required component THREE.Reflector not found.');
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (THREE.Refractor === undefined) {
|
|
||||||
|
|
||||||
console.error('THREE.Water: Required component THREE.Refractor not found.');
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var reflector = new THREE.Reflector(width, height, {
|
|
||||||
textureWidth: textureWidth,
|
|
||||||
textureHeight: textureHeight,
|
|
||||||
clipBias: clipBias
|
|
||||||
});
|
|
||||||
|
|
||||||
var refractor = new THREE.Refractor(width, height, {
|
|
||||||
textureWidth: textureWidth,
|
|
||||||
textureHeight: textureHeight,
|
|
||||||
clipBias: clipBias
|
|
||||||
});
|
|
||||||
|
|
||||||
reflector.matrixAutoUpdate = false;
|
|
||||||
refractor.matrixAutoUpdate = false;
|
|
||||||
|
|
||||||
// material
|
|
||||||
|
|
||||||
this.material = new THREE.ShaderMaterial({
|
|
||||||
uniforms: THREE.UniformsUtils.merge([
|
|
||||||
THREE.UniformsLib['fog'],
|
|
||||||
shader.uniforms
|
|
||||||
]),
|
|
||||||
vertexShader: shader.vertexShader,
|
|
||||||
fragmentShader: shader.fragmentShader,
|
|
||||||
transparent: true,
|
|
||||||
fog: true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (flowMap !== undefined) {
|
|
||||||
|
|
||||||
this.material.defines.USE_FLOWMAP = '';
|
|
||||||
this.material.uniforms.tFlowMap = {
|
|
||||||
type: 't',
|
|
||||||
value: flowMap
|
|
||||||
};
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
this.material.uniforms.flowDirection = {
|
|
||||||
type: 'v2',
|
|
||||||
value: flowDirection
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// maps
|
|
||||||
|
|
||||||
normalMap0.wrapS = normalMap0.wrapT = THREE.RepeatWrapping;
|
|
||||||
normalMap1.wrapS = normalMap1.wrapT = THREE.RepeatWrapping;
|
|
||||||
|
|
||||||
this.material.uniforms.tReflectionMap.value = reflector.getRenderTarget().texture;
|
|
||||||
this.material.uniforms.tRefractionMap.value = refractor.getRenderTarget().texture;
|
|
||||||
this.material.uniforms.tNormalMap0.value = normalMap0;
|
|
||||||
this.material.uniforms.tNormalMap1.value = normalMap1;
|
|
||||||
|
|
||||||
// water
|
|
||||||
|
|
||||||
this.material.uniforms.color.value = color;
|
|
||||||
this.material.uniforms.reflectivity.value = reflectivity;
|
|
||||||
this.material.uniforms.textureMatrix.value = textureMatrix;
|
|
||||||
|
|
||||||
// inital values
|
|
||||||
|
|
||||||
this.material.uniforms.config.value.x = 0; // flowMapOffset0
|
|
||||||
this.material.uniforms.config.value.y = halfCycle; // flowMapOffset1
|
|
||||||
this.material.uniforms.config.value.z = halfCycle; // halfCycle
|
|
||||||
this.material.uniforms.config.value.w = scale; // scale
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
function updateTextureMatrix(camera)
|
|
||||||
{
|
|
||||||
|
|
||||||
textureMatrix.set(
|
|
||||||
0.5, 0.0, 0.0, 0.5,
|
|
||||||
0.0, 0.5, 0.0, 0.5,
|
|
||||||
0.0, 0.0, 0.5, 0.5,
|
|
||||||
0.0, 0.0, 0.0, 1.0
|
|
||||||
);
|
|
||||||
|
|
||||||
textureMatrix.multiply(camera.projectionMatrix);
|
|
||||||
textureMatrix.multiply(camera.matrixWorldInverse);
|
|
||||||
textureMatrix.multiply(scope.matrixWorld);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateFlow()
|
|
||||||
{
|
|
||||||
|
|
||||||
var delta = clock.getDelta();
|
|
||||||
var config = scope.material.uniforms.config;
|
|
||||||
|
|
||||||
config.value.x += flowSpeed * delta; // flowMapOffset0
|
|
||||||
config.value.y = config.value.x + halfCycle; // flowMapOffset1
|
|
||||||
|
|
||||||
// Important: The distance between offsets should be always the value of "halfCycle".
|
|
||||||
// Moreover, both offsets should be in the range of [ 0, cycle ].
|
|
||||||
// This approach ensures a smooth water flow and avoids "reset" effects.
|
|
||||||
|
|
||||||
if (config.value.x >= cycle) {
|
|
||||||
|
|
||||||
config.value.x = 0;
|
|
||||||
config.value.y = halfCycle;
|
|
||||||
|
|
||||||
} else if (config.value.y >= cycle) {
|
|
||||||
|
|
||||||
config.value.y = config.value.y - cycle;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
this.onBeforeRender = function (renderer, scene, camera)
|
|
||||||
{
|
|
||||||
|
|
||||||
updateTextureMatrix(camera);
|
|
||||||
updateFlow();
|
|
||||||
|
|
||||||
scope.visible = false;
|
|
||||||
|
|
||||||
reflector.matrixWorld.copy(scope.matrixWorld);
|
|
||||||
refractor.matrixWorld.copy(scope.matrixWorld);
|
|
||||||
|
|
||||||
reflector.onBeforeRender(renderer, scene, camera);
|
|
||||||
refractor.onBeforeRender(renderer, scene, camera);
|
|
||||||
|
|
||||||
scope.visible = true;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
THREE.Water.prototype = Object.create(THREE.Mesh.prototype);
|
|
||||||
THREE.Water.prototype.constructor = THREE.Water;
|
|
||||||
|
|
||||||
THREE.Water.WaterShader = {
|
|
||||||
|
|
||||||
uniforms: {
|
|
||||||
|
|
||||||
'color': {
|
|
||||||
type: 'c',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'reflectivity': {
|
|
||||||
type: 'f',
|
|
||||||
value: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
'tReflectionMap': {
|
|
||||||
type: 't',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'tRefractionMap': {
|
|
||||||
type: 't',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'tNormalMap0': {
|
|
||||||
type: 't',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'tNormalMap1': {
|
|
||||||
type: 't',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'textureMatrix': {
|
|
||||||
type: 'm4',
|
|
||||||
value: null
|
|
||||||
},
|
|
||||||
|
|
||||||
'config': {
|
|
||||||
type: 'v4',
|
|
||||||
value: new THREE.Vector4()
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
vertexShader: [
|
|
||||||
|
|
||||||
'#include <fog_pars_vertex>',
|
|
||||||
|
|
||||||
'uniform mat4 textureMatrix;',
|
|
||||||
|
|
||||||
'varying vec4 vCoord;',
|
|
||||||
'varying vec2 vUv;',
|
|
||||||
'varying vec3 vToEye;',
|
|
||||||
|
|
||||||
'void main() {',
|
|
||||||
|
|
||||||
' vUv = uv;',
|
|
||||||
' vCoord = textureMatrix * vec4( position, 1.0 );',
|
|
||||||
|
|
||||||
' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
|
|
||||||
' vToEye = cameraPosition - worldPosition.xyz;',
|
|
||||||
|
|
||||||
' vec4 mvPosition = viewMatrix * worldPosition;', // used in fog_vertex
|
|
||||||
' gl_Position = projectionMatrix * mvPosition;',
|
|
||||||
|
|
||||||
' #include <fog_vertex>',
|
|
||||||
|
|
||||||
'}'
|
|
||||||
|
|
||||||
].join('\n'),
|
|
||||||
|
|
||||||
fragmentShader: [
|
|
||||||
|
|
||||||
'#include <fog_pars_fragment>',
|
|
||||||
|
|
||||||
'uniform sampler2D tReflectionMap;',
|
|
||||||
'uniform sampler2D tRefractionMap;',
|
|
||||||
'uniform sampler2D tNormalMap0;',
|
|
||||||
'uniform sampler2D tNormalMap1;',
|
|
||||||
|
|
||||||
'#ifdef USE_FLOWMAP',
|
|
||||||
' uniform sampler2D tFlowMap;',
|
|
||||||
'#else',
|
|
||||||
' uniform vec2 flowDirection;',
|
|
||||||
'#endif',
|
|
||||||
|
|
||||||
'uniform vec3 color;',
|
|
||||||
'uniform float reflectivity;',
|
|
||||||
'uniform vec4 config;',
|
|
||||||
|
|
||||||
'varying vec4 vCoord;',
|
|
||||||
'varying vec2 vUv;',
|
|
||||||
'varying vec3 vToEye;',
|
|
||||||
|
|
||||||
'void main() {',
|
|
||||||
|
|
||||||
' float flowMapOffset0 = config.x;',
|
|
||||||
' float flowMapOffset1 = config.y;',
|
|
||||||
' float halfCycle = config.z;',
|
|
||||||
' float scale = config.w;',
|
|
||||||
|
|
||||||
' vec3 toEye = normalize( vToEye );',
|
|
||||||
|
|
||||||
// determine flow direction
|
|
||||||
' vec2 flow;',
|
|
||||||
' #ifdef USE_FLOWMAP',
|
|
||||||
' flow = texture2D( tFlowMap, vUv ).rg * 2.0 - 1.0;',
|
|
||||||
' #else',
|
|
||||||
' flow = flowDirection;',
|
|
||||||
' #endif',
|
|
||||||
' flow.x *= - 1.0;',
|
|
||||||
|
|
||||||
// sample normal maps (distort uvs with flowdata)
|
|
||||||
' vec4 normalColor0 = texture2D( tNormalMap0, ( vUv * scale ) + flow * flowMapOffset0 );',
|
|
||||||
' vec4 normalColor1 = texture2D( tNormalMap1, ( vUv * scale ) + flow * flowMapOffset1 );',
|
|
||||||
|
|
||||||
// linear interpolate to get the final normal color
|
|
||||||
' float flowLerp = abs( halfCycle - flowMapOffset0 ) / halfCycle;',
|
|
||||||
' vec4 normalColor = mix( normalColor0, normalColor1, flowLerp );',
|
|
||||||
|
|
||||||
// calculate normal vector
|
|
||||||
' vec3 normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) );',
|
|
||||||
|
|
||||||
// calculate the fresnel term to blend reflection and refraction maps
|
|
||||||
' float theta = max( dot( toEye, normal ), 0.0 );',
|
|
||||||
' float reflectance = reflectivity + ( 1.0 - reflectivity ) * pow( ( 1.0 - theta ), 5.0 );',
|
|
||||||
|
|
||||||
// calculate final uv coords
|
|
||||||
' vec3 coord = vCoord.xyz / vCoord.w;',
|
|
||||||
' vec2 uv = coord.xy + coord.z * normal.xz * 0.05;',
|
|
||||||
|
|
||||||
' vec4 reflectColor = texture2D( tReflectionMap, uv );',
|
|
||||||
' vec4 refractColor = texture2D( tRefractionMap, uv );',
|
|
||||||
|
|
||||||
// multiply water color with the mix of both textures
|
|
||||||
' gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );',
|
|
||||||
|
|
||||||
' #include <tonemapping_fragment>',
|
|
||||||
' #include <encodings_fragment>',
|
|
||||||
' #include <fog_fragment>',
|
|
||||||
|
|
||||||
'}'
|
|
||||||
|
|
||||||
].join('\n')
|
|
||||||
};
|
|
Loading…
Reference in new issue