Đang cố gắng thực hiện Microfacet BRDF nhưng hình ảnh kết quả của tôi bị sai


9

Tôi đang cố gắng thực hiện mô hình BRDF microfacet. Tôi đang đọc slide của Sebastien Lagarde . Tôi đã triển khai các công thức cho mã của mình nhưng tôi nghĩ hình ảnh kết quả là sai.

Màu vàng là màu cơ bản của vật liệu. Màu sắc đặc trưng là màu đỏ để xem đúng.

Mã của tôi:

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

Kết quả sai

BIÊN TẬP

Độ nhám = 0,2f; nhập mô tả hình ảnh ở đây

Độ nhám = 0,04f; nhập mô tả hình ảnh ở đây


1
Tôi đã không nhìn quá nhiều chi tiết vào mã, nhưng hình ảnh có vẻ ổn. Hiệu ứng Fresnel hiện lên như một vòng màu đỏ. Với độ nhám quá cao (0,9), có nghĩa là phần còn lại của hình ảnh chủ yếu là màu vàng (nghĩa là phần lớn là khuếch tán). Nếu bạn hạ thấp độ gồ ghề, bạn có thể có một điểm nổi bật màu đỏ
RichieSams

@RichieSams Tôi đã thêm hình ảnh mới cho các giá trị độ nhám khác nhau nhưng chưa thể thấy nổi bật màu đỏ sáng bóng.
hmkum

1
Hình ảnh thứ 2 và thứ 3 của bạn dường như có ít màu đỏ nói chung (trong khu vực khuếch tán màu vàng) so với hình ảnh gốc của bạn. Điều này không rõ ràng lắm vì thêm một chút màu đỏ vào vùng màu vàng sẽ khiến nó có màu tương tự (màu vàng cam chứ không phải màu vàng). Bạn có thấy chi tiết nào về phân phối màu đỏ nếu bạn giảm màu vàng đáng kể không? Bỏ hoàn toàn màu vàng có thể giúp xác định những gì đang xảy ra.
trichoplax

@trichoplax tôi giảm màu vàng nhưng một lần nữa không thấy màu đỏ đặc biệt. Tôi chỉ thấy hiệu ứng vòng màu đỏ (fresnel). Không quan trọng những gì tôi đặt giá trị cho độ nhám Tôi không thể thấy hiệu ứng cụ thể mà tập trung một điểm.
hmkum

2
Đầu tiên bình thường hóa vectơ Bình thường trước khi sử dụng và thứ hai, viewDirection là vectơ đi từ Vị trí đến máy ảnh: uCameraPocation - Position.
xpicox

Câu trả lời:


3

Sự cố được khắc phục bởi RichieSams, trichoplax và xpicox. Cảm ơn tất cả các bạn cho câu trả lời.

Tôi hạ thấp độ gồ ghề, thay đổi màu sắc của vật liệu và đảo ngược ViewDirection sau đó cuối cùng tôi bắt đầu thấy đặc điểm chính xác :).

Mã cố định:

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

Hình ảnh cuối cùng:

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.