我正在three.js中创建水,到目前为止我还没有在three.js中实现反射和折射的任何水示例,但是如果你这样做,请链接。 在我被Slayvin在上Mirror.js的顶部建筑工作的那一刻 https://threejs.org/examples/webgl_mirror.htmlMirror.js中的矩阵操作(三个j)
我的计划是使用第二渲染目标渲染refractiontexture以类似的方式为反射,然后混合两种纹理着色器。
现在我有一个临时折射rendertarget,我用于混合,它工作。然而,由于我没有对纹理应用正确的矩阵乘法,因此此时的临时折射被严重扭曲。它应该比我想象的镜子容易得多,但是这不起作用,因为我认为它会。我怎么知道最初的纹理矩阵应该设置为什么?
this.updateMatrixWorld();
this.camera.updateMatrixWorld();
// Update the texture matrix
this.textureMatrixRefraction.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);
this.textureMatrixMirror.multiply(this.camera.projectionMatrix);
this.textureMatrixMirror.multiply(this.camera.matrixWorldInverse);
我试图找出对镜子里的矩阵运算是如何工作的,因为我失去了一些东西很重要。我试图从这是上面的代码做一个简单的版本。代码中的上限注释是我的,所以如果你能解释一些我认为很好的问题标记。
THREE.Water.prototype.updateTextureMatrixMirror = function() {
//UPDATE TO CURRENT WORLD AND CAMERA FOR MIRROROBJECT
this.updateMatrixWorld();
this.camera.updateMatrixWorld();
//COPY VALUES FROM WORLD AND CAMERA, GETTING TRANSFORMATIONS IN WORLD
this.mirrorWorldPosition.setFromMatrixPosition(this.matrixWorld);
this.cameraWorldPosition.setFromMatrixPosition(this.camera.matrixWorld);
this.rotationMatrix.extractRotation(this.matrixWorld);
//SET NORMAL AND APPLY ROTATION
this.normal.set(0, 0, 1);
this.normal.applyMatrix4(this.rotationMatrix);
//CREATE NEW CAMERA VIEW, THIS IS ONLY RELEVANT FOR THE REFLECTION
var view = this.mirrorWorldPosition.clone().sub(this.cameraWorldPosition);
view.reflect(this.normal).negate(); //tHIS IS NOT NEEDED FOR REFRACTION?
view.add(this.mirrorWorldPosition);
this.rotationMatrix.extractRotation(this.camera.matrixWorld);
//SET LOOKAT... NOT REALLY GRASPING WHAT IT CHANGES?
this.lookAtPosition.set(0, 0, -1);
this.lookAtPosition.applyMatrix4(this.rotationMatrix);
this.lookAtPosition.add(this.cameraWorldPosition);
//TARGET, ALSO TROUBLY UNDERSTANDING WHAT IT CHANGES
var target = this.mirrorWorldPosition.clone().sub(this.lookAtPosition);
target.reflect(this.normal).negate(); //WHAT HAPPENS HERE??
target.add(this.mirrorWorldPosition);
this.up.set(0, -1, 0); //CHANGING TO NEG Y
this.up.applyMatrix4(this.rotationMatrix);
this.up.reflect(this.normal).negate(); // IS THIS NEEDED?
//MIRRORCAMERA COPIES THE GENERATED VALUES AND UPDATES
this.mirrorCamera.position.copy(view);
this.mirrorCamera.up = this.up;
this.mirrorCamera.lookAt(target);
this.mirrorCamera.updateProjectionMatrix();
this.mirrorCamera.updateMatrixWorld();
this.mirrorCamera.matrixWorldInverse.getInverse(this.mirrorCamera.matrixWorld); // IS THIS NEEDED FOR REFRACTION?
//THIS IS WHERE THE MAGIC HAPPENS, TEXTURE MATRIX IS UPDATED
// Update the texture matrix
this.textureMatrixMirror.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);
//USE THE GENERATED MIRRORCAMERA TO GET MATRIX MULTIPLICATIONS
this.textureMatrixMirror.multiply(this.mirrorCamera.projectionMatrix);
this.textureMatrixMirror.multiply(this.mirrorCamera.matrixWorldInverse);
// AS I UNDERSTAND, THIS PART DEALS WITH THE CLIPPING USING OBLIQUE FRUSTUMS
// 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
this.waterPlane.setFromNormalAndCoplanarPoint(this.normal, this.mirrorWorldPosition);
this.waterPlane.applyMatrix4(this.mirrorCamera.matrixWorldInverse);
this.clipPlane.set(this.waterPlane.normal.x, this.waterPlane.normal.y, this.waterPlane.normal.z, this.waterPlane.constant);
var q = new THREE.Vector4();
var projectionMatrix = this.mirrorCamera.projectionMatrix;
q.x = (Math.sign(this.clipPlane.x) + projectionMatrix.elements[ 8 ])/projectionMatrix.elements[ 0 ];
q.y = (Math.sign(this.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
var c = new THREE.Vector4();
c = this.clipPlane.multiplyScalar(2.0/this.clipPlane.dot(q));
// Replacing the third row of the projection matrix
projectionMatrix.elements[ 2 ] = c.x;
projectionMatrix.elements[ 6 ] = c.y;
projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
projectionMatrix.elements[ 14 ] = c.w;
更新:所以我得到了一个半血统的视觉效果,但是,也有一些错误,我知道我不能正常产生,因为错误的矩阵变换的折射质感。此外,我正努力为我已经实现的dudv-map的偏移量获得良好的流量,目前我正在使用正弦函数,但这会导致摇摆运动,看起来非常不自然,尽管它可以避免一个“跳跃切割”,只是用剩余的分割值循环rippleMoveFactor。看到当前结果和全码:Demo