0

上記で説明したように、レイトレーシングを使用して 3D シーンを 2D プレーンにレンダリングしたいと考えています。最終的にはボリューム レンダリングに使用したいと考えていますが、ここでの基本に苦労しています。ビュープレーンがカメラに接続された (もちろんカメラの前にある) three.js シーンがあります。

セットアップ: シーン

次に (シェーダーで) 平面の​​各ポイント (250x250) を通してカメラから光線を放ちます。平面の後ろには 41x41x41 のボリューム (本質的に立方体) があります。光線が立方体を通過する場合、光線が交差したビュー プレーン内のポイントは赤くレンダリングされ、それ以外の場合、ポイントは黒になります。残念ながら、これは立方体を正面から見た場合にのみ機能します。例は次のとおりです: http://ec2-54-244-155-66.us-west-2.compute.amazonaws.com/example.html

立方体をさまざまな角度から見ようとすると (マウスでカメラを動かすことができます)、希望どおりにビュー プレーンに立方体がレンダリングされませんが、側面にいくつかの奇妙なピクセルがある正方形が表示されます..

これがレイトレーシングのコードです。

頂点シェーダー:

bool inside(vec3 posVec){
        bool value = false;

        if(posVec.x <0.0 ||posVec.x > 41.0 ){
            value = false;
        }
        else if(posVec.y <0.0 ||posVec.y > 41.0 ){
            value = false;
        }
        else if(posVec.z <0.0 ||posVec.z > 41.0 ){
            value = false;
     }
     else{
        value = true;
     }
     return value;
    }





float getDensity(vec3 PointPos){

    float stepsize = 1.0;
    float emptyStep = 15.0;

    vec3 leap;
    bool hit = false;
    float density = 0.000;
    // Ray direction from the camera through the current point in the Plane
    vec3 dir = PointPos- camera;
    vec3 RayDirection = normalize(dir);
    vec3 start = PointPos;   

    for(int i = 0; i<STEPS; i++){

         vec3 alteredPosition = start;
         alteredPosition.x += 20.5;
         alteredPosition.y += 20.5;
         alteredPosition.z += 20.5;

        bool insideTest = inside(alteredPosition);

        if(insideTest){


         // advance from the start position
        start = start + RayDirection * stepsize;

          hit = true;

     }else{
        leap = start + RayDirection * emptyStep;
        bool tooFar = inside(leap);
        if(tooFar){
            start = start + RayDirection * stepsize;
        }else{
            start = leap;
        }
     }

    }
    if(hit){
        density = 1.000;
    }

    return density; 
}


        void main() {


    PointIntensity = getDensity(position);
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;

}

フラグメント シェーダー:

varying float PointIntensity;

void main() {

   //Rays that have traversed the volume (cube) should leave a red point on the viewplane, Rays that just went through empty space a black point
       gl_FragColor= vec4(PointIntensity, 0.0, 0.0, 1.0);



}

完全なコード: http://pastebin.com/4YmWL0u1

同じコードで実行中: http://ec2-54-244-155-66.us-west-2.compute.amazonaws.com/example.html

ここで私が間違っていたことについて誰かが何かヒントを持っていれば、とてもうれしいです

編集:

Mark Lundin が提案した変更を加えて例を更新しましたが、残念ながら、カメラを動かしたときにまだ赤い四角しか表示されません (側面に奇妙なピクセルはありません)。

mat4 uInvMVProjMatrix = modelViewMatrix *inverseProjectionMatrix;

inverseProjectionMatrix は Three.js のカメラ プロパティ ProjectionMatrixInverse であり、ユニフォームとしてシェーダーに渡されます。次に、UV 座標を使用して、ビュープレーン内のすべてのポイントに対して unproject 関数が呼び出されます。

新しいコードは次のとおりです。

http://pastebin.com/Dxh5C9XX

ここで実行しています:

http://ec2-54-244-155-66.us-west-2.compute.amazonaws.com/example.html

カメラが実際に移動していることを確認するには、x、y、z を押して現在のカメラの x、y、z 座標を取得します。

4

1 に答える 1

4

3D ボリュームではなく正方形が表示されているのは、レイトレーシング方法がカメラの向きや投影を考慮していないためです。トラックボールでカメラを動かすと向きが変わるため、これを計算に含める必要があります。次に、カメラの射影行列を使用して、平面の座標を 3D 空間に射影する必要があります。これは、次のような方法で実現できます。

vec3 unproject( vec2 coord ){
    vec4 screen = vec4( coord, 0, 1.0 );
    vec4 homogenous = uInvMVProjMatrix * 2.0 * ( screen - vec4( 0.5 )  );
    return homogenous.xyz / homogenous.w;
}

ここcoordで、 は平面の 2 次元座標でuInvMVProjMatrixあり、モデル ビューの射影行列の逆数です。これによりvec3、交差に対するテストに使用できる が返されます。

于 2013-10-02T11:32:51.997 に答える