0

openGL バージョン 3.3 で全方向/点照明を作成しようとしています。私はインターネットとこのサイトを検索しましたが、これまでのところこれを達成できませんでした. 私の理解から、私はすることになっています

深度コンポーネントを使用してフレーム バッファを生成する

キューブマップを生成し、それを上記のフレームバッファにバインドします

列挙型 GL_TEXTURE_CUBE_MAP_* によって参照されるように、キューブマップの個々の部分に描画します

シーンを通常どおりに描画し、フラグメントの深度値をキューブマップの深度値と比較します

今、キューブマップのルックアップが簡単になるため、フラグメントの深さを保存するよりも、ライトからフラグメントまでの距離を使用する方が良いと読みました(個々のテクスチャをチェックする必要がないことについての何か?)

私の現在の問題は、出てくる光が実際には球であり、影を生成しないことです。もう 1 つの問題は、フレーム バッファーが完全でないと文句を言うことですが、テクスチャにレンダリングする場合、フレーム バッファーはレンダー バッファーを必要としないという印象を受けました。

フレームバッファとキューブ マップの初期化は次のとおりです。

framebuffer = 0;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

glGenTextures(1, &shadowTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadowTexture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);GL_COMPARE_R_TO_TEXTURE);
for(int i = 0; i < 6; i++){
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i , 0,GL_DEPTH_COMPONENT16, 800, 800, 0,GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
}

glDrawBuffer(GL_NONE);

シャドウ頂点シェーダー

void main(){
    gl_Position = depthMVP * M* vec4(position,1);
    pos =(M * vec4(position,1)).xyz;
}

シャドウ フラグメント シェーダー

void main(){
    fragmentDepth = distance(lightPos, pos);
}

Vertex Shader (無関係な部分を切り取ったもの)

uniform mat4 depthMVP;
void main() {
    PositionWorldSpace = (M * vec4(position,1.0)).xyz;
    gl_Position = MVP * vec4(position, 1.0 );

    ShadowCoord = depthMVP * M* vec4(position, 1.0);
}

Fragment Shader (無関係なコードカット)

uniform samplerCube shadowMap;
void main(){
    float bias = 0.005;
    float visibility = 1;
    if(texture(shadowMap, ShadowCoord.xyz).x < distance(lightPos, PositionWorldSpace)-bias)
        visibility = 0.1
}

おそらく考えているように、depthMVP とは何ですか? 深度射影行列は現在、各方向の範囲が [-10, 10] の正射影です。これらは次のように定義されています。

glm::mat4 depthMVP = depthProjectionMatrix* ??? *i->getModelMatrix();

ここでの問題は、??? が何なのかわからないということです。価値があるはずです。以前はカメラマトリックスでしたが、それが本来あるべきものかどうかはわかりません。次に、キューブマップの側面に対して描画コードが次のように実行されます。

for(int loop = 0; loop < 6; loop++){
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X+loop, shadowTexture,0);
    glClear( GL_DEPTH_BUFFER_BIT);
    for(auto i: models){
        glUniformMatrix4fv(modelPos, 1, GL_FALSE, glm::value_ptr(i->getModelMatrix()));
        glm::mat4 depthMVP = depthProjectionMatrix*???*i->getModelMatrix();
        glUniformMatrix4fv(glGetUniformLocation(shadowProgram, "depthMVP"),1, GL_FALSE, glm::value_ptr(depthMVP));
        glBindVertexArray(i->vao);
        glDrawElements(GL_TRIANGLES, i->triangles, GL_UNSIGNED_INT,0);
    }
}

最後に、シーンが正常に描画されます (詳細は省きます)。キューブマップへの描画を呼び出す前に、フレームバッファーを以前に生成したものに設定し、ビューポートを 800 x 800 に変更します。通常の描画を行う前に、フレームバッファーを 0 に戻し、ビューポートを 800 x 600 にリセットします。この件に関するヘルプは大歓迎です。

更新 1

いくつかの微調整とバグ修正の後、これが得られる結果です。depthMVP が機能しないというエラーを修正しました。ここで描画しているのは、キューブマップに格納されている距離です。 http://imgur.com/JekOMvf

基本的に何が起こるかは、両側に同じ片側投影を描画することです。両側に同じビュー マトリックスを使用するため、これは理にかなっていますが、どのような種類のビュー マトリックスを使用すればよいかわかりません。中心に位置し、立方体マップ側の方向を見るlookAt()行列であるはずだと思います。ただし、発生する問題は、これらの複数のプロジェクションをメインの描画呼び出しでどのように使用することになっているのかということです。

更新 2

先に進んでこれらのマトリックスを作成しましたが、それらがどれほど有効かはわかりません (DX キューブマップの Web サイトから取得したため、Z 座標を反転させました)。

case 1://Negative X
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(-1,0,0),glm::vec3(0,-1,0));
    break;
case 3://Negative Y
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,-1,0),glm::vec3(0,0,-1));
    break;
case 5://Negative Z
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,0,-1),glm::vec3(0,-1,0));
    break;
case 0://Positive X
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(1,0,0),glm::vec3(0,-1,0));
    break;
case 2://Positive Y
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,1,0),glm::vec3(0,0,1));
    break;
case 4://Positive Z
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,0,1),glm::vec3(0,-1,0));
    break;

これらは6つの個別の行列であるため、depthMVPビュー部分を何によって翻訳することになっているのかという問題がまだ残っています。これは、同じ frag シェーダ (つまり、実際に影をレンダリングする) を使用した現在の外観のスクリーンショット ですhttp://i.imgur.com/HsOSG5v.png問題。これを生成するために使用したビュー マトリックスは、カメラの位置の逆変換にすぎません (lookAt() 関数が行うように)。

アップデート 3

現在のコード: Shadow Vertex

void main(){
    gl_Position = depthMVP * vec4(position,1);
    pos =(M * vec4(position,1)).xyz;
}

影の欠片

void main(){
    fragmentDepth = distance(lightPos, pos);
}

主頂点

void main(){
    PositionWorldSpace = (M*vec4(position, 1)).xyz;
    ShadowCoord = vec4(PositionWorldSpace - lightPos, 1);
}

メインフラグ

void main(){
    float texDist = texture(shadowMap, ShadowCoord.xyz/ShadowCoord.w).x;
    float dist = distance(lightPos, PositionWorldSpace);
    if(texDist < distance(lightPos, PositionWorldSpace)
        visibility = 0.1;
    outColor = vec3(texDist);//This is to visualize the depth maps
}

使用されている透視マトリックス

glm::mat4 depthProjectionMatrix = glm::perspective(90.f, 1.f, 1.f, 50.f);

現在、すべてが機能しています。テクスチャが格納するデータ (つまり、距離) は、奇妙な方法で格納されているようです。すべての値が 0 から 1 の間であるため、正規化されているように見えます。また、ビューアの周りに投影のない 1x1x1 の領域がありますが、これは視錐台によるものであり、簡単に修正できると思います (カメラを中央に 0.5 オフセットします)。

4

1 に答える 1

3

フラグメントの深さを OpenGL に任せて決定すると、ハードウェアの階層的な Z 最適化を利用できるようになります。基本的にgl_FragDepth、フラグメント シェーダーに書き込むと (新しい保守的な深度 GLSL 拡張を使用せずに)、階層 Z と呼ばれるハードウェアの最適化が妨げられます。Hi-Z とは、略して、一部のプリミティブのラスター化を基本的にスキップできる手法です。プリミティブ全体の深度値が、深度バッファーに既にある値の背後にあること。ただし、シェーダーが に任意の値を書き込まない場合にのみ機能しますgl_FragDepth

ライトからキューブ マップまでのフラグメントの距離を書き込む代わりに、従来の深度に固執する場合、シャドウ マップを書き込むときに理論的にはより高いスループットが得られるはずです (遮蔽されたプリミティブをスキップできるため)。

次に、デプス キューブ マップをサンプリングするフラグメント シェーダーで、次のようなコード スニペットを使用して距離値をデプス値に変換します ( f と n は、デプス キューブの作成時に使用した遠距離と近距離の平面距離です)。マップ):


float VectorToDepthValue(vec3 Vec)
{
    vec3 AbsVec = abs(Vec);
    float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));

    const float f = 2048.0;
    const float n = 1.0;
    float NormZComp = (f+n) / (f-n) - (2*f*n)/(f-n)/LocalZcomp;
    return (NormZComp + 1.0) * 0.5;
}

SO の質問から借用したコード:深度キューブマップを使用した全方向シャドウ マッピング

その余分なコードをシェーダーに適用すると、次のようになります。


void main () {
    float shadowDepth = texture(shadowMap, ShadowCoord.xyz/ShadowCoord.w).x;
    float testDepth   = VectorToDepthValue(lightPos - PositionWorldSpace);
    if (shadowDepth < testDepth)
        visibility = 0.1;
}

于 2013-08-12T20:46:41.837 に答える