2016-06-28 1 views
2

Ich folge 'Moving Frostbite to PBR course notes', um IBL in meiner Rendering-Engine in OpenGL zu implementieren, aber ich habe einige Probleme vor der Integration der spiegelnden Komponente der Gleichung.IBL-Sonde BRDF-Präintegrationsartefakte

Wie Sie aus meinen nächsten Bildern sehen können, ist das Problem in den Mipmaps des Cubemap-Ergebnisses der vorfiltrierten Wichtigkeitsabtastung sichtbar.

Dies ist die positive Gesicht mip Kette X: enter image description here

Dies ist die negative Gesicht mip Kette X: enter image description here

Dies ist die Umgebungskarte I (es verwenden, wird dynamisch physikalisch basierten Himmel Textur erstellt in einem HDR-Format): enter image description here

Dies ist die positive mip Kette der Umgebungskarte X Gesicht: enter image description here

Wie Sie sehen können, scheint auf der rechten Seite der Mips der positiven X-Fläche die Sampling-Richtung ähnlich der Sampling-Richtung der linken Seite der Mip.

Es gibt auch diese "punktförmigen" Formen, die auf dem zweiten Mip des positiven X-Gesichtes sichtbar sind, von denen ich denke, dass sie auf eine geringe Anzahl von Proben zurückzuführen sind.

Dies ist der Code, den ich die spiegelnde IBL Pre-Integration verwenden:

float radicalInverse_VdC(uint bits) 
{ 
    bits = (bits << 16u) | (bits >> 16u); 
    bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); 
    bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); 
    bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); 
    bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); 
    return float(bits) * 2.3283064365386963e-10; ///0x100000000 
} 

// 
// Attributed to: 
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html 
// Holger Dammertz. 
// 
vec2 Hammersley(uint i, uint N) 
{ 
    return vec2(float(i)/float(N), radicalInverse_VdC(i)); 
} 

// Based on GGX example in: 
// http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf 
vec3 importanceSampleGGX(vec2 u, float roughness, vec3 N, vec3 upVector, vec3 tangentX, vec3 tangentY) 
{ 
    float a = roughness * roughness; 

    float phiH = u.x * PI * 2.0f; 
    float cosThetaH = sqrt((1.0f - u.y)/(1.0f + (a * a - 1.0f) * u.y)); 
    float sinThetaH = sqrt(1.0f - min(1.0f, cosThetaH * cosThetaH)); 

    vec3 H = vec3(sinThetaH * cos(phiH), sinThetaH * sin(phiH), cosThetaH); 
    H = normalize(tangentX * H.x + tangentY * H.y + N * H.z); 
    return H; 
} 

// D(h) for GGX. 
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html 
float D_GGX(float roughness, float NdotH) 
{ 
    float a = roughness * roughness; 
    float a2 = a * a; 
    float NdotH2 = NdotH * NdotH; 
    float f = 1.0f + (NdotH2 * (a2 - 1.0f)); 
    return a2/(f * f); 
} 

float D_GGX_Divide_Pi(float roughness, float NdotH) 
{ 
    return D_GGX(roughness, NdotH)/PI; 
} 

vec3 ImportanceSample (vec3 N) 
{ 
    vec3 V = N; 

    float size2 = ConvolutionSrcSize * ConvolutionSrcSize; 
    vec3 upVector = abs(N.z) < 0.999 ? vec3(0.0f, 0.0f, 1.0f) : vec3(1.0f, 0.0f, 0.0f); 
    vec3 tangentX = normalize(cross(upVector, N)); 
    vec3 tangentY = cross(N, tangentX); 

    vec3 accBrdf = vec3(0.0f); 
    float accBrdfWeight = 0.0f; 
    float roughness = ConvolutionRoughness; 

    uint samplesCount = uint(ConvolutionSampleCount); 
    for(uint i = uint(0); i < samplesCount; i++) 
    { 
     vec2 eta = Hammersley(i, samplesCount); 

     vec3 H = importanceSampleGGX(eta, roughness, N, upVector, tangentX, tangentY); 
     vec3 L = 2.0f * dot(V, H) * H - V; 
     float NdotL = dot(N, L); 

     if(NdotL > 0.0f) 
     { 
      float NdotH = saturate(dot(N, H)); 
      float LdotH = saturate(dot(L, H)); 
      float pdf = D_GGX_Divide_Pi(roughness, NdotH) * NdotH/(4.0f * LdotH); 

      float omegaS = 1.0f/(samplesCount * pdf); 
      float omegaP = 4.0f * PI/(6.0f * size2); 

      float mipLevel = roughness == 0.0f ? 0.0f : clamp(0.5f * log2(omegaS/omegaP), 0.0f, ConvolutionMipCount); 

      vec4 Li = textureLod(ConvolutionSrc, L, mipLevel); 

      accBrdf += Li.rgb * NdotL; 
      accBrdfWeight += NdotL; 
     } 
    } 

    if(accBrdfWeight > 0.0f) 
     return accBrdf * (1.0f/accBrdfWeight); 
    else 
     return accBrdf; 
} 

void main() 
{ 
    // VertexIn.textureCoord is the normal of a sphere I use as mesh to draw to the IBL cubemap 
    FragColor = vec4(ImportanceSample(VertexIn.textureCoord), 1.0f); 
} 

Antwort

0

Fand heraus, es war wegen Problem mit dem Cubemap Naht in der Nähe der Würfelkanten zugewandt ist. Aktivieren GL_TEXTURE_CUBE_MAP_SEAMLESS löste das Problem. Ich habe das nicht bemerkt, seit ich NSight verwende, um die Shader zu debuggen, aber NSight unterstützt glTexParameteri mit GL_TEXTURE_CUBE_MAP_SEAMLESS nicht, also habe ich es immer deaktiviert, um die Shader zu debuggen, aber ich fand heraus, dass NSight glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS) akzeptiert.

Ein Problem bleibt jedoch, die Mips sind sehr sehr laut, auch mit einer großen Anzahl von Proben. Bei 1024 Samples bekomme ich folgendes:

enter image description here