พยายามใช้ Microfacet BRDF แต่ภาพผลลัพธ์ของฉันไม่ถูกต้อง


9

ฉันกำลังพยายามใช้โมเดล BRDF ของ microfacet ฉันอ่านสไลด์ Sebastien Lagarde ของ ฉันใช้สูตรกับรหัสของฉัน แต่ฉันคิดว่าภาพผลลัพธ์ไม่ถูกต้อง

สีเหลืองเป็นสีฐานของวัสดุ สีของ specular เป็นสีแดงเพื่อดูอย่างถูกต้อง

รหัสของฉัน:

// 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;
}

ผลผิดพลาด

แก้ไข

ความหยาบ = 0.2f; ป้อนคำอธิบายรูปภาพที่นี่

ความหยาบ = 0.04f ป้อนคำอธิบายรูปภาพที่นี่


1
ฉันไม่ได้ดูรายละเอียดของรหัสมากเกินไป แต่ภาพดูเหมือนจะไม่เป็นไร เอฟเฟกต์ Fresnel แสดงเป็นวงแหวนสีแดง ด้วยความหยาบที่สูงมาก (0.9) ทำให้รู้สึกว่าส่วนที่เหลือของรูปภาพนั้นส่วนใหญ่เป็นสีเหลือง (เช่นกระจายส่วนใหญ่) หากคุณลดความหยาบคุณอาจได้ไฮไลท์สีแดง
RichieSams

@RichieSams ฉันได้เพิ่มรูปภาพใหม่สำหรับค่าความหยาบที่แตกต่างกัน แต่ไม่สามารถมองเห็นไฮไลท์ specular เงาสีแดงได้
hmkum

1
ภาพที่ 2 และ 3 ของคุณมีสีแดงโดยทั่วไปน้อยกว่า (ในพื้นที่กระจายสีเหลือง) กว่าภาพต้นฉบับของคุณ สิ่งนี้ไม่ชัดเจนมากนักเนื่องจากการเพิ่มสีแดงเล็กน้อยลงในพื้นที่สีเหลืองทำให้มีสีคล้ายกัน (สีส้มเหลืองมากกว่าสีเหลือง) คุณเห็นรายละเอียดเพิ่มเติมของการกระจายสีแดงถ้าคุณลดสีเหลืองลงอย่างมากหรือไม่? การละเว้นสีเหลืองทั้งหมดอาจช่วยในการระบุสิ่งที่ผิดพลาด
trichoplax

@trichoplax ฉันลดสีเหลือง แต่ก็ไม่มีทางเห็น specular สีแดงอีก ฉันเพิ่งเห็นเอฟเฟ็กต์วงแหวนสีแดง (เฟรส) ไม่สำคัญว่าสิ่งที่ฉันกำหนดค่าสำหรับความหยาบฉันไม่เห็นผล specular ที่มุ่งเน้นจุด
hmkum

2
อันดับแรกให้ปรับเวกเตอร์ปกติก่อนใช้งานและอันดับที่สอง viewDirection เป็นเวกเตอร์ที่ส่งออกจากตำแหน่งไปยังกล้อง: uCameraPosition - ตำแหน่ง
xpicox

คำตอบ:


3

แก้ไขปัญหาโดย RichieSams, trichoplax และ xpicox ขอบคุณทุกคนสำหรับคำตอบ

ฉันลดความหยาบกร้านเปลี่ยนสีของวัสดุและกลับรายการ ViewDirection จากนั้นในที่สุดฉันก็เริ่มเห็น specular ที่เหมาะสม :)

รหัสคงที่:

#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;
}

ภาพสุดท้าย:

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.