Microfacet BRDF'yi uygulamaya çalışıyorum, ancak sonuç resimlerim yanlış


9

Mikrofacet BRDF modelini uygulamaya çalışıyorum. Sebastien Lagarde'nin slaytlarını okuyorum . Koduma formüller uyguladım ama sonuç resminin yanlış olduğunu düşünüyorum.

Sarı, malzemenin temel rengidir. Aynasal renk düzgün görmek için kırmızıdır.

Kodum:

// Fragment Shader
#version 330 core

in vec3 Position;
in vec2 TexCoord0;
in vec3 Normal;
in vec3 Tangent;
out vec4 FinalColor;

uniform vec3 uCameraPosition; // init value: vec3(0, 0, 5)

#define PI 3.1415926f
#define EPSILON 10e-5f
#define saturate(value) clamp(value, 0.0f, 1.0f);

float BRDF_Lambert(float NdotL)
{
    return NdotL;
}

// Got these BRDF formulas Moving Frostbite to PBR slide by Sebastien Lagarde & Charles de Rousiers 
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf
float BRDF_D_GGX(float NdotH, float Roughness)
{
    float Roughness2 = Roughness * Roughness;
    float f = (NdotH * Roughness2 - NdotH) * NdotH + 1.0f;
    return Roughness2 / (f * f + EPSILON);
}


float BRDF_F_FresnelSchlick(float LdotH, float F0)
{
    float f = F0 + (1.0f - F0) * pow((1.0f - LdotH), 5);
    return f;
}

float BRDF_G_SmithGGXCorrelated(float NdotL, float NdotV, float Roughness)
{
    float Roughness2 = Roughness * Roughness;
    float GV = NdotL * sqrt((-NdotV * Roughness2 + NdotV) * NdotV + Roughness2);
    float GL = NdotV * sqrt((-NdotL * Roughness2 + NdotL) * NdotL + Roughness2);

    return 0.5f / (GV + GL + EPSILON);
}

float BRDF_Specular(float NdotV, float NdotL, float NdotH, float LdotH, float Roughness, float F0)
{
    float D = BRDF_D_GGX(NdotH, Roughness);
    float F = BRDF_F_FresnelSchlick(LdotH, F0);
    float G = BRDF_G_SmithGGXCorrelated(NdotL, NdotV, Roughness);
    return (D * F * G) / PI;
}

void main()
{
    FinalColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
    vec4 BaseColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);
    vec4 SpecularColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
    vec3 LightDirection = normalize(vec3(0, 4, 4));
    vec3 ViewDirection = normalize(Position - uCameraPosition);
    vec3 HalfVector = normalize(ViewDirection + LightDirection);
    float Roughness = 0.9f; // [0.04 - 0.1f] -> Dielectric, [0.7, 1.0f] -> Metallic

    float RefractiveIndex = 0.27049f; // RI for Gold materials. I got this from http://refractiveindex.info/
    float F0 = pow(((1.0f - RefractiveIndex) / (1.0f + RefractiveIndex)), 2);

    float NdotL = saturate(dot(LightDirection, Normal));
    float NdotV = abs(dot(ViewDirection, Normal)) + EPSILON; // Avoid artifact - Ref: SIGGRAPH14 - Moving Frosbite to PBR
    float LdotH = saturate(dot(LightDirection, HalfVector));
    float NdotH = saturate(dot(Normal, HalfVector));

    float DiffuseFactor = BRDF_Lambert(NdotL);
    float SpecularFactor = BRDF_Specular(NdotV, NdotL, NdotH, LdotH, Roughness, F0);

    FinalColor = BaseColor * DiffuseFactor + SpecularColor * SpecularFactor;
}

Yanlış sonuç

DÜZENLE

Pürüzlülük = 0.2f; resim açıklamasını buraya girin

Pürüzlülük = 0.04f; resim açıklamasını buraya girin


1
Ben koda çok fazla ayrıntı bakmadım, ama görüntü iyi görünüyor. Fresnel efekti kırmızı bir halka olarak görünür. Pürüzlülük çok yüksek olduğunda (0.9), görüntünün geri kalanının çoğunlukla sarı (yani çoğunlukla dağınık) olması mantıklıdır. Pürüzlülüğü
azaltırsanız

@RichieSams Farklı pürüz değerleri için yeni görüntüler ekledim ancak henüz kırmızı parlak speküler vurguları göremiyorum.
hmkum

1
2. ve 3. görüntülerinizin orijinal görüntünüzden genel olarak daha az kırmızı (sarı dağınık alanda) olduğu görülür. Bu çok açık değildir, çünkü sarı bir alana biraz kırmızı eklemek benzer bir renk bırakır (sarı yerine turuncu-sarı). Sarıyı önemli ölçüde azaltırsanız kırmızı dağılımının daha fazla ayrıntısını görüyor musunuz? Sarıyı tamamen atlamak, neyin yanlış gittiğini belirlemeye yardımcı olabilir.
trichoplax

@ trichoplax ben sarı azaltılmış ama yine kırmızı speküler görmek için hiçbir yolu. Sadece kırmızı halka (fresnel) etkisi görüyorum. Pürüz için ne değer ayarladığım önemli değil bir noktaya odaklanmış speküler etkisi göremiyorum.
hmkum

2
Önce Normal vektörü kullanmadan önce normalleştirin ve ikinci olarak viewDirection Konumdan kameraya giden giden vektördür: uCameraPosition - Position.
xpicox

Yanıtlar:


3

RichieSams, trichoplax ve xpicox ile ilgili sorun düzeltildi. Cevaplarınız için hepinize teşekkürler.

Pürüzlülüğü düşürdüm, malzemenin rengini değiştirdim ve ViewDirection'ı ters çevirdim, sonra nihayet uygun speküler görmeye başladım :).

Sabit Kod:

#version 330 core

in vec3 Position;
in vec2 TexCoord0;
in vec3 Normal;
in vec3 Tangent;
out vec4 FinalColor;

uniform vec3 uCameraPosition;

#define PI 3.1415926f
#define EPSILON 10e-5f
#define saturate(value) clamp(value, 0.0f, 1.0f);

float BRDF_Lambert(float NdotL)
{
    return NdotL;
}

// Got these BRDF formulas Moving Frostbite to PBR slide by Sebastien Lagarde & Charles de Rousiers 
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf
float BRDF_D_GGX(float NdotH, float Roughness)
{
    float Roughness2 = Roughness * Roughness;
    float f = (NdotH * Roughness2 - NdotH) * NdotH + 1.0f;
    return Roughness2 / (f * f + EPSILON);
}


float BRDF_F_FresnelSchlick(float LdotH, float F0)
{
    float f = F0 + (1.0f - F0) * pow((1.0f - LdotH), 5);
    return f;
}

float BRDF_G_SmithGGXCorrelated(float NdotL, float NdotV, float Roughness)
{
    float Roughness2 = Roughness * Roughness;
    float GV = NdotL * sqrt((-NdotV * Roughness2 + NdotV) * NdotV + Roughness2);
    float GL = NdotV * sqrt((-NdotL * Roughness2 + NdotL) * NdotL + Roughness2);

    return 0.5f / (GV + GL + EPSILON);
}

float BRDF_Specular(float NdotV, float NdotL, float NdotH, float LdotH, float Roughness, float F0)
{
    float D = BRDF_D_GGX(NdotH, Roughness);
    float F = BRDF_F_FresnelSchlick(LdotH, F0);
    float G = BRDF_G_SmithGGXCorrelated(NdotL, NdotV, Roughness);
    return (D * F * G) / PI;
}

void main()
{
    vec3 normal = normalize(Normal);

    vec4 BaseColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
    vec4 SpecularColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);

    vec3 LightDirection = normalize(vec3(0, 4, 4) - Position);
    vec3 ViewDirection = normalize(uCameraPosition - Position);
    vec3 HalfVector = normalize(ViewDirection + LightDirection);
    float Roughness = 0.04f;

    float RefractiveIndex = 0.24f; // RI for Gold materials. I got this from http://refractiveindex.info/
    float F0 = pow(((1.0f - RefractiveIndex) / (1.0f + RefractiveIndex)), 2);

    float NdotL = saturate(dot(LightDirection, normal));
    float NdotV = abs(dot(ViewDirection, normal)) + EPSILON; // Avoid artifact - Ref: SIGGRAPH14 - Moving Frosbite to PBR
    float LdotH = saturate(dot(LightDirection, HalfVector));
    float NdotH = saturate(dot(normal, HalfVector));

    float DiffuseFactor = BRDF_Lambert(NdotL);
    float SpecularFactor = 0.0f;
    if(DiffuseFactor > 0.0f)
    {
        SpecularFactor = BRDF_Specular(NdotV, NdotL, NdotH, LdotH, Roughness, F0);
    }
    FinalColor = BaseColor * DiffuseFactor + SpecularColor * SpecularFactor;
}

Son Resim:

resim açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.