我正在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