2

私はthree.jsで水を作るに取り組んでいるとこれまでのところ、してください私は反射と屈折の両方を実装するthree.js内の任意の水の例を見ていないが、あなたがしなければリンク。 はSlayvin によって私はMirror.jsの上に構築で働いている瞬間https://threejs.org/examples/webgl_mirror.html行列演算(三のJS)

で私の計画は、反射と同様の方法でrefractiontextureをレンダリングするために第2のレンダーターゲットを使用していたし、その後に2つのテクスチャをブレンドシェイダー。

今私はブレンドに使用する一時的な屈折レンダリングターゲットを持っています。これは機能します。しかし、テクスチャに正しい行列乗算を適用していないので、この一時的な屈折はひどく歪んでいます。それは私が思うミラーよりも簡単なはずですが、これは私が思ったようにはうまくいかないのです。最初のテクスチャマトリックスをどのように設定すべきかを知るにはどうすればよいですか?

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

答えて

1

::で、現在の結果と完全なコードを参照してください

「lookatPosition」の部分は役に立たないようだが、それは私が目の前に(Z軸上)離れた位置1単位を取得することができます現在のビュー:その位置をさらに計算に使用されると、それは-10または-0.5単位カメラから離れて、純粋に任意されている可能性がされて

this.lookAtPosition.set(0, 0, -1); // -1 unit on Z (depth axis) 
this.lookAtPosition.applyMatrix4(this.rotationMatrix); // applying camera rotation to that lookat vector, so they are both the same 
this.lookAtPosition.add(this.cameraWorldPosition); // adding that vector to the camera position 

は、それは知られています限り、問題ではありません。カメラの軸に立つ位置。私は「-1」を選んだので、扱いが簡単です。

だから、我々は今、カメラが見ている空間での確認の少なくとも1点のために知って、カメラの位置を知っている、と我々はまた、ミラーの位置と方向を知っています。 だから今、それは私たちのミラービューの方向を計算してみましょう:

var target = this.mirrorWorldPosition.clone().sub(this.lookAtPosition); 
target.reflect(this.normal).negate(); 
target.add(this.mirrorWorldPosition); 

まず、私がターゲットとミラー位置の差であるターゲットベクトルを、作成します。
次に、そのベクトルをミラーの法線軸に沿って反射し、それを反転(否定)してミラー位置に追加することができ、ミラーリングされたターゲットの最終位置を得ることができます。

最後に私は正しい、目標位置とミラーカメラ...

this.mirrorCamera.position.copy(view); 
this.mirrorCamera.up = this.up; 
this.mirrorCamera.lookAt(target); 

を設定...投影行列計算に進みます。