11

目がオブジェクトAの表面点P1にあり、ターゲットオブジェクトBがあり、オブジェクトBの後ろに点光源があると仮定します。

質問:光源を見て、オブジェクトBのために光が見えない場合は、「私は影になっています」と言うのは正しいですか?次に、オブジェクトAのそのポイントを「A上のBのシャドウポイントの1つ」としてフラグを立てます。

ここに画像の説明を入力してください

もしこれが本当なら、Aの表面に「影の幾何学」(黒い色)のオブジェクトを構築し、それをリアルタイムで光、B、Aなどの動きのために絶えず変更することができますか?球(A)には1000の頂点があり、他の球(B)にも1000の頂点があるとしましょう。これは、100万の比較を意味しますか?(シャドウイング、O(N ^ 2)(時間)の複雑さですか?)P1(目)を変更するとBの視点(P1と光源点の間)も変更されるため、複雑さについてはよくわかりません。2次以上の影(2つのオブジェクト間で光が何度も反射するなど)はどうですか?

現在java-3Dを使用していますが、シャドウ機能がないため、他のjava互換ライブラリに移行することを考えています。

ありがとう。

編集:その影を構築するためにカメラを移動するときに「カメラ」を無効にする必要があります。これどうやってするの?これによりパフォーマンスが大幅に低下しますか?

新しいアイデア: java3Dには衝突検出機能が組み込まれています。光からターゲットのポリゴン頂点までの線(非表示)を作成してから、別のオブジェクトからの衝突をチェックします。衝突が発生した場合は、その頂点コードを追加します。シャドウリストに追加しますが、これはポイントライトに対してのみ機能します:(。

java3d用の実際のシェードライブラリを提供している人は誰でも大いに役立ちます。

java3Dの非常に小さなサンプルGeomlibシャドウ/レイトレーシングがおそらく最良 のレイトレーシングの例でしょうか?

これは少し難しいことですが、少なくとも100人が試してみることができたはずです。

ありがとう。

4

4 に答える 4

3

影はおそらく3Dグラフィックプログラミングで最も複雑なトピックであり、多くのアプローチがありますが、タスクの要件に応じて最適なオプションを特定する必要があります。あなたが話しているアルゴリズムは、スポット光源から平面に影を実装する最も簡単な方法です。すでに3DレンダリングにGPUを使用しているため、CPUで実行しないでください。

基本的に、アプローチは同じオブジェクトを2回レンダリングすることです。1回はカメラの視点から、もう1回は光源の視点からです。これら2つのビュー間で変換するには、モデルビューマトリックスを準備する必要があります。ライトポイントからオブジェクトをレンダリングすると、各ポイントが光源に最も近い深度マップが得られます。次に、通常のレンダリングの各ピクセルについて、その3D座標を前のビューに変換し、対応する深度値と照合する必要があります。これにより、基本的に、どのピクセルが影で覆われているかを知ることができます。

パフォーマンスへの影響は、同じオブジェクトを2回レンダリングすることによって発生します。あなたのタスクがシャドウキャスティングソリューションの高いスケーラビリティを想定していない場合、それは進むべき道かもしれません。

関連する質問の数:

OpenGLで安価なシャドウを作成するにはどうすればよいですか?

OpenGLでシャドウを取得する簡単な方法はありますか?

OpenGLでシーンに影をレンダリングするための最も簡単な方法は何ですか?

于 2012-10-05T20:04:57.813 に答える
2

あなたのアプローチは次のように要約できます。

foreach (point p to be shaded) {
    foreach (light) {
        if (light is visible from p)
            // p is lit by that light
        else
            // p is in shadow
    }
}

面白い事実は、GPUでリアルタイムシャドウが今日どのように行われるかということです。

ただし、これが効率的に機能することは簡単ではありません。シーンのレンダリングは、三角形ごとの合理化されたプロセスです。すべての単一の三角形のすべての単一のポイント(ピクセル、フラグメント)について、光線の交差をチェックするために他のすべての三角形を考慮する必要がある場合は、非常に面倒です。

では、それを効率的に行う方法は?回答:プロセスを逆にします。

通常、シーン上のピクセルよりもはるかに少ないライトがあります。この事実を利用して、いくつかの前処理を行いましょう。

// preprocess
foreach (light) {
    // find all pixels p on the scene reachable from the light
}
// then render the whole scene...
foreach (point p to be shaded) {
    foreach (light) {
        // simply look up into what was calculated before...
        if (p is visible by the light)
            // p is lit
        else
            // p is in shadow
    }
 }

それははるかに速いようです...しかし、2つの問題が残っています:

  1. 光で見えるすべてのピクセルを見つける方法は?
  2. レンダリング中にルックアップするためにそれらにすばやくアクセスできるようにする方法は?

トリッキーな部分があります:

  • ライトで見えるすべてのポイントを見つけるには、そこにカメラを配置してシーン全体をレンダリングします。深度テストは、見えないポイントを拒否します。
  • この結果に後でアクセスできるようにするには、結果をテクスチャとして保存し、そのテクスチャを実際のレンダリング段階でのルックアップに使用します。

この手法はシャドウマッピングと呼ばれ、ライトから見えるピクセルを持つテクスチャはシャドウマップと呼ばれます。より詳細な説明については、たとえばWikipediaの記事を参照してください。

于 2012-10-10T14:11:00.877 に答える
1

基本的にそうです、あなたのアプローチは影を生み出します。ただし、GPUで実行しない限り、ポイントごとに実行することは、パフォーマンスに関して(リアルタイムで)実行可能ではありません。私は今日のAPIの提供内容に精通していませんが、最近のエンジンはすぐに使える影を提供すると確信しています。

あなたの「新しいアイデア」は、レンダリングがまだCPUで行われていた時代にシャドウがどのように実装されたかです。ポリゴンの数が多すぎない場合(またはボリュームをグループ化するなどしてバンチ全体を効率的に拒否できる場合)、かなり少ないCPUパワーで実行できます。

于 2012-10-09T15:26:24.543 に答える
1

バニラJavaでの3Dシャドウレンダリングは決して効率的ではありません。OpenGLやDirectXなど、グラフィカルカードの全機能を利用するように作成されたグラフィカルライブラリを使用するのが最適です。Canvasを使用している場合(提供したスクリーンショットから)、JNIを使​​用してネイティブコードからそのCanvasをペイントすることもできます。したがって、グラフライブラリのすべてのテクノロジーを使用し、少し手を加えて、ネイティブコードから直接Canvasをペイントすることができます。独自の3Dエンジンを作成する場合と比較して、それを機能させるために必要な作業はほとんどありません。

AWTネイティブアクセスに関するWikiリンク:http://en.wikipedia.org/wiki/Java_AWT_Native_Interface ドキュメント:http ://docs.oracle.com/javase/7/docs/technotes/guides/awt/AWT_Native_Interface.html

于 2012-10-10T13:53:50.850 に答える