0

それでSSAOを実装しようとしましたが、意図したとおりに機能していません。位置 z=0 (ワールド空間) で分割されているように見えます。位置 z=0 に白い線があります。また、オクルージョンが正しく見えません。

ここに画像の説明を入力

さらに距離が離れているため、カメラを移動すると、オクルージョンがさらに奇妙になります ここに画像の説明を入力

ジオメトリをレンダリングするためのマイ シェーダー (インスタンス化):

バーテックス:

#version 330 core

 layout(location = 0) in vec3 vertexPosition;
 layout(location = 1) in vec2 vertexUV;
 layout(location = 2) in vec3 vertexColor;
 layout(location = 3) in vec3 vertexNormal;
 layout(location = 4) in mat4 offset;
 layout(location = 8) in vec4 instanceColor;

uniform mat4 Projection;
uniform mat4 View;

out vec2 UV;
out vec4 Color;
out vec3 Normal;

void main()
{

        mat4 Model = offset;
    mat4 MVP = Projection * View * Model;



vec4 Pos = MVP * vec4(endpos,1);

gl_Position = Pos;

UV = vertexUV;

Color = instanceColor;
    Normal = normalize((Model * vec4(vertexNormal,0)).xyz);

}

断片:

    #version 330 core

    in vec2 UV;
    in vec4 Color;
    in vec3 Normal;

    uniform sampler2D Diffuse;

void main()
{
    gl_FragData[0] = vec4(Color);
    gl_FragData[1] = (vec4(Normal,1)+1)/2;
}

ジオメトリ パスの後、SSAO パスを法線情報と深度情報とともに適用します。

これは私のNoiseTextureです: ここに画像の説明を入力

ハードウェアの深度バッファを使用します。ワールド空間ですべてを計算します。

フラグメント シェーダーは次のとおりです。

    #version 330 core

#define KERNEL_SIZE 16
uniform sampler2D NormalMap;
uniform sampler2D DepthMap;
uniform sampler2D NoiseTexture;
uniform vec2 NoiseScale;

uniform vec2 Resolution;

uniform mat4 InvertViewProjection;

uniform float g_sample_rad = 0.1;
uniform float g_intensity = 2.0;
uniform float g_scale = 0.1;
uniform float g_bias = 0.0;

vec2 CalcTexCoord()
{
    return gl_FragCoord.xy / Resolution;
}

vec3 getPosition(vec2 uv)
{
    vec4 worldpos;

    float depth = texture2D(DepthMap, uv).r;

    worldpos.x = uv.x * 2.0f - 1.0f;

    worldpos.y = uv.y * 2.0f - 1.0f;

    worldpos.z = depth * 2.0f - 1.0f;

    worldpos.w = 1.0;

    worldpos = InvertViewProjection * worldpos;

    worldpos /= worldpos.w;

    return worldpos.rgb;
}

vec3 getNormal(vec2 uv)
{
    return normalize(texture2D(NormalMap, uv).xyz * 2.0f - 1.0f);
}

vec2 getRandom(vec2 uv)
{
    return normalize(texture2D(NoiseTexture, Resolution*uv / NoiseScale).xy * 2.0f - 1.0f);
}

float doAmbientOcclusion(in vec2 tcoord, in vec2 uv, in vec3 p, in vec3 cnorm)
{
    vec3 diff = getPosition(tcoord + uv) - p;
    vec3 v = normalize(diff);
    float d = length(diff)*g_scale;

    return max(0.0, dot(cnorm, v) - g_bias)*(1.0 / (1.0 + d))*g_intensity;
}



void main()
{

    vec4 Kernels[KERNEL_SIZE] =
    vec4[](
        vec4(0.355512,  -0.709318,  -0.102371,  0.0 ),
        vec4(0.534186,  0.71511,    -0.115167,  0.0 ),
        vec4(-0.87866,  0.157139,   -0.115167,  0.0 ),
        vec4(0.140679,  -0.475516,  -0.0639818, 0.0 ),
        vec4(-0.0796121,    0.158842,   -0.677075,  0.0 ),
        vec4(-0.0759516,    -0.101676,  -0.483625,  0.0 ),
        vec4(0.12493,   -0.0223423, -0.483625,  0.0 ),
        vec4(-0.0720074,    0.243395,   -0.967251,  0.0 ),
        vec4(-0.207641,     0.414286,   0.187755,   0.0 ),
        vec4(-0.277332,     -0.371262,  0.187755,   0.0 ),
        vec4(0.63864,   -0.114214,  0.262857,   0.0 ),
        vec4(-0.184051,     0.622119,   0.262857,   0.0 ),
        vec4(0.110007,  -0.219486,  0.435574,   0.0 ),
        vec4(0.235085,  0.314707,   0.696918,   0.0 ),
        vec4(-0.290012,     0.0518654,  0.522688,   0.0 ),
        vec4(0.0975089,     -0.329594,  0.609803,   0.0 )

    );
    vec2 uv = CalcTexCoord(); //same as UV Coordinate from Vertex
    vec3 p = getPosition(uv);
    vec3 n = getNormal(uv);
    vec2 rand = getRandom(uv);

    float ao = 0.0f;
    float rad = g_sample_rad / p.z;

    for (int j = 0; j < KERNEL_SIZE; ++j)
    {
        vec2 coord = reflect(Kernels[j].xy, rand)*rad;
        ao += doAmbientOcclusion(uv, coord, p, n);
    }
    ao /= KERNEL_SIZE;

    ao = 1 - (ao);
    gl_FragColor = vec4(ao,ao,ao, 1);
}
4

1 に答える 1

0

コードを段階的にデバッグすることで、それを理解しました。

ワールド空間ですべてを計算します。そこですべてを処理する方が簡単です。ビュー空間を使用するチュートリアルを見て、必要なものをすべてワールド空間に変更しました。

エラーは次のとおりです。

 float rad = g_sample_rad / p.z;

これにより、距離に基づいてサンプリング半径が計算されます。ビュー空間では、これはカメラからの距離のサンプリング半径を計算します。しかし、ワールド空間では、これはワールド座標からの距離を計算するため、z=0 では奇妙に見え、遠くにあるとさらに奇妙に見えます。

だから私がそれを修正するためにしたことは、これは簡単です:

vec4 viewpos = CamView * vec4(p,1);
float ao = 0.0f;
float rad = g_sample_rad/viewpos.z;

ポイントをビュー空間に変更し、ビュー空間でのサンプリング半径を計算して、カメラからの距離を考慮しました。

これで修正されます。

ここに画像の説明を入力

g_values を少しいじって、自分のニーズに合わせました。どこでも同じように見えることを確認してください。それはそれがどのように見えるべきかです。

于 2015-06-04T14:32:14.247 に答える