SSAO実装で望ましい結果が得られない


12

遅延レンダリングを実装した後、このチュートリアルを使用してSSAO実装を試してみました。残念ながら、SSAOのように見えるものは何も得られません。私の結果を以下で見ることができます。

失敗したサオの試み

奇妙なパターンが形成されており、オクルージョンシェーディングが必要な場所(つまり、オブジェクト間および地面)がないことがわかります。私が実装したシェーダーは次のとおりです。


#VS
#version 330 core

uniform mat4 invProjMatrix;

layout(location = 0) in vec3 in_Position;
layout(location = 2) in vec2 in_TexCoord;

noperspective out vec2 pass_TexCoord;
smooth out vec3 viewRay;

void main(void){
    pass_TexCoord = in_TexCoord;
    viewRay = (invProjMatrix * vec4(in_Position, 1.0)).xyz;
    gl_Position = vec4(in_Position, 1.0);
}

#FS
#version 330 core

uniform sampler2D DepthMap;
uniform sampler2D NormalMap;
uniform sampler2D noise;

uniform vec2 projAB;
uniform ivec3 noiseScale_kernelSize;
uniform vec3 kernel[16];
uniform float RADIUS;
uniform mat4 projectionMatrix;

noperspective in vec2 pass_TexCoord;
smooth in vec3 viewRay;

layout(location = 0) out float out_AO;

vec3 CalcPosition(void){
    float depth = texture(DepthMap, pass_TexCoord).r;
    float linearDepth = projAB.y / (depth - projAB.x);
    vec3 ray = normalize(viewRay);
    ray = ray / ray.z;
    return linearDepth * ray;
}

mat3 CalcRMatrix(vec3 normal, vec2 texcoord){
    ivec2 noiseScale = noiseScale_kernelSize.xy;
    vec3 rvec = texture(noise, texcoord * noiseScale).xyz;
    vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
    vec3 bitangent = cross(normal, tangent);

    return mat3(tangent, bitangent, normal);
}

void main(void){

    vec2 TexCoord = pass_TexCoord;
    vec3 Position = CalcPosition();
    vec3 Normal = normalize(texture(NormalMap, TexCoord).xyz);

    mat3 RotationMatrix = CalcRMatrix(Normal, TexCoord);

    int kernelSize = noiseScale_kernelSize.z;

    float occlusion = 0.0;

    for(int i = 0; i < kernelSize; i++){
        // Get sample position
        vec3 sample = RotationMatrix * kernel[i];
        sample = sample * RADIUS + Position;
        // Project and bias sample position to get its texture coordinates
        vec4 offset = projectionMatrix * vec4(sample, 1.0);
        offset.xy /= offset.w;
        offset.xy = offset.xy * 0.5 + 0.5;
        // Get sample depth
        float sample_depth = texture(DepthMap, offset.xy).r;
        float linearDepth = projAB.y / (sample_depth - projAB.x);
        if(abs(Position.z - linearDepth ) < RADIUS){
            occlusion += (linearDepth <= sample.z) ? 1.0 : 0.0;
        }
    }
    out_AO = 1.0 - (occlusion / kernelSize);
}

フルスクリーンクワッドを描画し、DepthおよびNormalテクスチャを渡します。法線はRGBA16Fにあり、アルファチャネルはブラーパスのAOファクター用に予約されています。深度を非線形深度バッファ(32F)に保存し、次を使用して深度を回復します。


float linearDepth = projAB.y / (depth - projAB.x);

どこprojAB.yで計算されます:

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

およびprojAB.xとして:

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

これらはglm :: perspective(gluperspective)マトリックスから派生しています。z_nおよびz_fは、近いクリップ距離と遠いクリップ距離です。

上に掲載したリンクで説明したように、このメソッドは、中心に近い高分布の半球にサンプルを作成します。次に、テクスチャからのランダムベクトルを使用して、半球をZ方向にランダムに回転させ、最終的に指定されたピクセルで法線に沿って方向付けます。結果はノイズが多いため、SSAOパスの後にぼかしパスが続きます。

とにかく、位置の再構築は間違っていないようです。同じことを試みましたが、位置は再構築される代わりにテクスチャから渡されました。

また、Radius、ノイズテクスチャサイズ、サンプル数、さまざまな種類のテクスチャフォーマットを試してみましたが、うまくいきませんでした。何らかの理由で半径を変更しても、何も変わりません。

誰か提案はありますか?何が間違っているのでしょうか?


ぼかしは別のパスにする必要があると思います。ぼかしなしでシェーダーのスクリーンショットを投稿できますか?
knight666

ぼかしパスは個別です。ぼかし前のスクリーンショットを確認できます。
グライフハート

回答:


6

問題が見つかりました。それは本当にばかげた間違いglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);でした。正しい深さの値を取得するためにあなたが指定しなければならないことは知らなかったので、深さの値をサンプリングしていませんでした。これで、素敵なSSAO効果が得られました。

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


あなたがあなたのソリューションを見つけたことを人々が知っているように、これを正しい答えとして自由にフラグを立ててください:P
SomeGuy

はい、残念ながら、正しい回答としてフラグを立てられるようになるまで1日待つ必要があります。
グライフハート

私の間違いは、タイムスタンプをチェックしませんでした。
SomeGuy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.