Skip to main content
Rollback to Revision 1
Source Link
Sam
  • 198
  • 5
float D(float NoH, float roughness) {
    float a = sqr(roughness);
    float a2 = sqr(a);
    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
    return a2 / denom;
}
float G1(float NoV, float k) {
    float denom = NoV * (1.0 - k) + k;
    return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
    float k = sqr(roughness + 1) / 8.0;
    return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
    float f0 = sqr((1.0-ior)/(1.0+ior));
    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
    vec3 H = normalize(V+L);
    float NoL = dot(N, L);
    float NoV = dot(N, V);

    float nom = D(dot(N, H), mat.roughness)
        * F(dot(V, H), mat.ior)
        * G(NoL, NoV, mat.roughness);
 
    // Prevent division by zero, even when the GPU uses 8-bit arithmetic
    float denom = max(4.0 * NoL * NoV, 1.0/256.0);NoV;

    return vec3(1) * nom / denom;
}

// ----------------------

void main() {
    // ...

    vec3 rd = normalize(frag_pos - camera_pos);
    Material mat = materials[mat_index];
    col = brdf(-rd, sun_dir, normal, mat);

    // ...
}

Any idea what I'm doing wrong?

EDIT:

I think the black patch in the center of the ring was caused by a division by zero. I fixed that in the above code, but the result still isn't correct. The specular highlights are a flat circle:

Circle artifact

float D(float NoH, float roughness) {
    float a = sqr(roughness);
    float a2 = sqr(a);
    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
    return a2 / denom;
}
float G1(float NoV, float k) {
    float denom = NoV * (1.0 - k) + k;
    return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
    float k = sqr(roughness + 1) / 8.0;
    return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
    float f0 = sqr((1.0-ior)/(1.0+ior));
    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
    vec3 H = normalize(V+L);
    float NoL = dot(N, L);
    float NoV = dot(N, V);

    float nom = D(dot(N, H), mat.roughness)
        * F(dot(V, H), mat.ior)
        * G(NoL, NoV, mat.roughness);
 
    // Prevent division by zero, even when the GPU uses 8-bit arithmetic
    float denom = max(4.0 * NoL * NoV, 1.0/256.0);

    return vec3(1) * nom / denom;
}

// ----------------------

void main() {
    // ...

    vec3 rd = normalize(frag_pos - camera_pos);
    Material mat = materials[mat_index];
    col = brdf(-rd, sun_dir, normal, mat);

    // ...
}

Any idea what I'm doing wrong?

EDIT:

I think the black patch in the center of the ring was caused by a division by zero. I fixed that in the above code, but the result still isn't correct. The specular highlights are a flat circle:

Circle artifact

float D(float NoH, float roughness) {
    float a = sqr(roughness);
    float a2 = sqr(a);
    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
    return a2 / denom;
}
float G1(float NoV, float k) {
    float denom = NoV * (1.0 - k) + k;
    return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
    float k = sqr(roughness + 1) / 8.0;
    return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
    float f0 = sqr((1.0-ior)/(1.0+ior));
    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
    vec3 H = normalize(V+L);
    float NoL = dot(N, L);
    float NoV = dot(N, V);

    float nom = D(dot(N, H), mat.roughness)
        * F(dot(V, H), mat.ior)
        * G(NoL, NoV, mat.roughness);
    float denom = 4.0 * NoL * NoV;

    return vec3(1) * nom / denom;
}

// ----------------------

void main() {
    // ...

    vec3 rd = normalize(frag_pos - camera_pos);
    Material mat = materials[mat_index];
    col = brdf(-rd, sun_dir, normal, mat);

    // ...
}

Any idea what I'm doing wrong?

Partially fixed
Source Link
Sam
  • 198
  • 5
float D(float NoH, float roughness) {
    float a = sqr(roughness);
    float a2 = sqr(a);
    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
    return a2 / denom;
}
float G1(float NoV, float k) {
    float denom = NoV * (1.0 - k) + k;
    return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
    float k = sqr(roughness + 1) / 8.0;
    return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
    float f0 = sqr((1.0-ior)/(1.0+ior));
    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
    vec3 H = normalize(V+L);
    float NoL = dot(N, L);
    float NoV = dot(N, V);

    float nom = D(dot(N, H), mat.roughness)
        * F(dot(V, H), mat.ior)
        * G(NoL, NoV, mat.roughness); 

    // Prevent division by zero, even when the GPU uses 8-bit arithmetic
    float denom = max(4.0 * NoL * NoV;NoV, 1.0/256.0);

    return vec3(1) * nom / denom;
}

// ----------------------

void main() {
    // ...

    vec3 rd = normalize(frag_pos - camera_pos);
    Material mat = materials[mat_index];
    col = brdf(-rd, sun_dir, normal, mat);

    // ...
}

Any idea what I'm doing wrong?

EDIT:

I think the black patch in the center of the ring was caused by a division by zero. I fixed that in the above code, but the result still isn't correct. The specular highlights are a flat circle:

Circle artifact

float D(float NoH, float roughness) {
    float a = sqr(roughness);
    float a2 = sqr(a);
    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
    return a2 / denom;
}
float G1(float NoV, float k) {
    float denom = NoV * (1.0 - k) + k;
    return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
    float k = sqr(roughness + 1) / 8.0;
    return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
    float f0 = sqr((1.0-ior)/(1.0+ior));
    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
    vec3 H = normalize(V+L);
    float NoL = dot(N, L);
    float NoV = dot(N, V);

    float nom = D(dot(N, H), mat.roughness)
        * F(dot(V, H), mat.ior)
        * G(NoL, NoV, mat.roughness);
    float denom = 4.0 * NoL * NoV;

    return vec3(1) * nom / denom;
}

// ----------------------

void main() {
    // ...

    vec3 rd = normalize(frag_pos - camera_pos);
    Material mat = materials[mat_index];
    col = brdf(-rd, sun_dir, normal, mat);

    // ...
}

Any idea what I'm doing wrong?

float D(float NoH, float roughness) {
    float a = sqr(roughness);
    float a2 = sqr(a);
    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
    return a2 / denom;
}
float G1(float NoV, float k) {
    float denom = NoV * (1.0 - k) + k;
    return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
    float k = sqr(roughness + 1) / 8.0;
    return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
    float f0 = sqr((1.0-ior)/(1.0+ior));
    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
    vec3 H = normalize(V+L);
    float NoL = dot(N, L);
    float NoV = dot(N, V);

    float nom = D(dot(N, H), mat.roughness)
        * F(dot(V, H), mat.ior)
        * G(NoL, NoV, mat.roughness); 

    // Prevent division by zero, even when the GPU uses 8-bit arithmetic
    float denom = max(4.0 * NoL * NoV, 1.0/256.0);

    return vec3(1) * nom / denom;
}

// ----------------------

void main() {
    // ...

    vec3 rd = normalize(frag_pos - camera_pos);
    Material mat = materials[mat_index];
    col = brdf(-rd, sun_dir, normal, mat);

    // ...
}

Any idea what I'm doing wrong?

EDIT:

I think the black patch in the center of the ring was caused by a division by zero. I fixed that in the above code, but the result still isn't correct. The specular highlights are a flat circle:

Circle artifact

Source Link
Sam
  • 198
  • 5

Microfacet BRDF artifacts

I've been trying to implement a microfacet specular BRDF based on the equations in Real Shading in UE4, but I'm getting weird ring-shaped artifacts in the highlights of rough surfaces:

The artifacts

Here's the relevant pieces of the fragment shader:

float D(float NoH, float roughness) {
    float a = sqr(roughness);
    float a2 = sqr(a);
    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
    return a2 / denom;
}
float G1(float NoV, float k) {
    float denom = NoV * (1.0 - k) + k;
    return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
    float k = sqr(roughness + 1) / 8.0;
    return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
    float f0 = sqr((1.0-ior)/(1.0+ior));
    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
    vec3 H = normalize(V+L);
    float NoL = dot(N, L);
    float NoV = dot(N, V);

    float nom = D(dot(N, H), mat.roughness)
        * F(dot(V, H), mat.ior)
        * G(NoL, NoV, mat.roughness);
    float denom = 4.0 * NoL * NoV;

    return vec3(1) * nom / denom;
}

// ----------------------

void main() {
    // ...

    vec3 rd = normalize(frag_pos - camera_pos);
    Material mat = materials[mat_index];
    col = brdf(-rd, sun_dir, normal, mat);

    // ...
}

Any idea what I'm doing wrong?