microfacet BRDF 모델을 구현하려고합니다. Sebastien Lagarde의 슬라이드를 읽고 있습니다 . 코드에 수식을 구현했지만 결과 이미지가 잘못되었다고 생각합니다.
노란색은 재료의 기본 색상입니다. 정반사 색상이 제대로 표시되도록 빨간색입니다.
내 코드 :
// 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;
}
편집하다
1
코드를 너무 자세하게 살펴 보지 않았지만 이미지는 괜찮은 것 같습니다. 프레 넬 효과가 빨간색 링으로 나타납니다. 거칠기가 너무 높으면 (0.9) 이미지의 나머지 부분이 대부분 노란색 (즉, 대부분 확산)임을 의미합니다. 당신은 조도가 낮은 경우에, 당신은 빨간색 반사 하이라이트받을 수 있습니다
—
RichieSams
@RichieSams 다른 거칠기 값에 대해 새로운 이미지를 추가했지만 아직 빨간색 반짝이는 반사 하이라이트를 볼 수 없습니다.
—
hmkum
두 번째 및 세 번째 이미지는 원래 이미지보다 일반적으로 빨간색 (노란색 확산 영역)이 적습니다. 노란색 영역에 작은 빨간색을 추가하면 비슷한 색 (노란색이 아닌 주황색)이 남기 때문에 이는 분명하지 않습니다. 노란색을 크게 줄이면 빨간색 분포에 대해 더 자세히 알 수 있습니까? 노란색을 생략하면 무엇이 잘못되었는지 식별하는 데 도움이 될 수 있습니다.
—
trichoplax 1
@ trichoplax 나는 노랑을 줄 였지만 다시 붉은 거울을 볼 수있는 방법이 없었습니다. 빨간 고리 (프레 넬) 효과가 나타납니다. 거칠기에 대한 값을 설정 한 내용에 상관없이 점에 초점을 맞춘 반사 효과를 볼 수 없습니다.
—
hmkum
먼저 사용하기 전에 법선 벡터를 정규화하고 두 번째로 viewDirection은 위치에서 카메라로 나가는 벡터입니다 : uCameraPosition-위치.
—
xpicox