Estoy tratando de implementar el modelo de microfacet BRDF. Estoy leyendo las diapositivas de Sebastien Lagarde . Implementé fórmulas en mi código, pero creo que la imagen del resultado es incorrecta.
El amarillo es el color base del material. El color especular es rojo para ver correctamente.
Mi código:
// 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;
}
EDITAR
1
No he mirado con demasiados detalles el código, pero la imagen parece estar bien. El efecto Fresnel aparece como un anillo rojo. Con una rugosidad tan alta (0.9), tiene sentido que el resto de la imagen sea mayormente amarilla (es decir, mayormente difusa). Si reduce la aspereza, puede obtener un resaltado especular rojo
—
RichieSams
@RichieSams Agregué nuevas imágenes para diferentes valores de rugosidad, pero aún no puedo ver el resaltado especular rojo brillante.
—
hmkum
Sus imágenes segunda y tercera parecen tener menos rojo en general (en el área difusa amarilla) que su imagen original. Esto no es muy evidente porque agregar un poco de rojo a un área amarilla le deja un color similar (naranja-amarillo en lugar de amarillo). ¿Ves más detalles de la distribución roja si reduces significativamente el amarillo? Omitir el amarillo por completo puede ayudar a identificar lo que va mal.
—
Trichoplax
@trichoplax reduje el amarillo pero de nuevo no hay forma de ver especular rojo. Solo veo un efecto de anillo rojo (fresnel). No importa qué valor establezca para la rugosidad. No puedo ver el efecto especular que enfoca un punto.
—
hmkum
Primero normalice el vector Normal antes de usarlo y, en segundo lugar, viewDirection es el vector saliente desde la Posición a la cámara: uCameraPosition - Posición.
—
xpicox