Glsl — Ошибка: Слишком Резкие Блики В Pbr.

  • Автор темы Arinvaphoriff51
  • Обновлено
  • 22, Oct 2024
  • #1

Я все еще работаю над уравнениями BRDF. Теоретически все уравнения верны, но блики очень резкие. Я не уверен, является ли это результатом того, что я не использую освещение на основе изображений (сейчас я использую только карту окружения с функцией LOD). Я использую материалы отсюда: http://freepbr.com/c/base-materials/ - Я использую Specular/Gloss, но для преобразования материалов используется фрагментный шейдер.

glsl — Ошибка: слишком резкие блики в PBR.

Material Frag Shader (Отрывок) (В частности, шейдер Metalness-Roughness):

 
 
 vec3 LightCalc(in vec3 Albedo, in vec4 WorldPos, in vec4 Specular, in vec3 Normal, in samplerCube envMap, in vec3 lightPos, in float lightAtten, in vec4 lightColor) {

vec3 lightDir   = WorldPos.xyz - lightPos;

vec3 eyeDir = normalize(eyePos - WorldPos.xyz);

vec3 eyeReflect = reflect(-eyeDir, Normal);

float Distance  = length(lightDir);

lightDir        = -normalize(lightDir);

float Attenuation = clamp(1 - pow(Distance / lightAtten, 4), 0, 1);

Attenuation = Attenuation*Attenuation/(Distance*Distance+1);

vec3 AmbientColor = vec3(Albedo.xyz)*0.01;

float Roughness = 1-Specular.a;

float alpha = Roughness * Roughness;

vec3 H = normalize(eyeDir + lightDir);

float NL = clamp(dot(Normal, lightDir), 0, 1);

float NH = clamp(dot(Normal, H), 0, 1);

float NV = clamp(dot(Normal, eyeDir), 0, 1);

float LH = clamp(dot(lightDir, H), 0, 1);

float VH = clamp(dot(eyeDir, H), 0, 1);

float lod = compute_lod(alpha, 1, NH);

vec3 reflectDir = normalize(eyeReflect);

vec3 reflectPix = textureLod(envMap, reflectDir, lod).rgb;

float D = Light_D(alpha, NH);

vec3 F = Light_F(clamp(Specular.rgb, 0.018, 0.95), LH);

float Vis = Light_V(NL, NV, alpha);

vec3 Spec = (D * F * Vis) * reflectPix;

vec3 Diffuse = Light_Diffuse(NV, NL, Normal, alpha, Albedo.rgb, eyeDir, lightDir);

vec3 lightModifier = lightColor.xyz*lightColor.w*Attenuation;

return NL*(Spec + max(Diffuse, AmbientColor))*lightModifier;
}
 

Функции освещения:

vec3 Light_F(in vec3 Specular, in float VH) { // Fresnel Schlick return Specular + (1-Specular) * pow(1-VH, 5.0f); } float Light_D(in float alpha, in float NH) { // GGX float alphaSqr = alpha*alpha; float denom = NH * NH * (alphaSqr - 1) + 1; return alphaSqr / (pi * denom * denom); } float Light_V( in float NL, in float NV, in float alpha ) { // Frostbite's GGX float Lambda_GGXV = NL * sqrt (( - NV * alpha + NV ) * NV + alpha ); float Lambda_GGXL = NV * sqrt (( - NL * alpha + NL ) * NL + alpha ); return 0.5f / ( Lambda_GGXV + Lambda_GGXL ); } vec3 Light_Diffuse(in float NV, in float NL, in vec3 Normal, in float alpha, in vec3 Albedo, in vec3 eyeDir, in vec3 lightDir) { // Oren-Nayar float gamma = dot( eyeDir - Normal * NV, lightDir - Normal * NL); float A = 1.0f - 0.5f * (alpha / (alpha + 0.57f)); float B = 0.45f * (alpha / (alpha + 0.09)); float diffAlpha = max( acos( NV ), acos( NL ) ); float diffBeta = min( acos( NV ), acos( NL ) ); float C = sin(diffAlpha) * tan(diffBeta); return Albedo * (A + B * max( 0.0f, gamma ) * C) / pi; }

Финальная функция освещения в отложенном рендерере:

float Roughness = baseSpecular.a; if (uTexRoughEnabled == 1) Roughness = texture(texRoughness, UV).r; float Metalness = texture(texSpecular, UV).r; // 1 - Roughness becomes Glossiness specular = vec4(mix(vec3(0.4), albedo.rgb, Metalness), 1-Roughness); albedo = vec4(mix(albedo.rgb, vec3(0), Metalness), 1-Roughness);

Не стесняйтесь указывать на любые ошибки, которые я допустил, даже если они не имеют отношения к проблеме. Я протестировал материалы в Unreal, и они выглядели правильно. Я сомневаюсь, что это происходит исключительно из-за отсутствия освещения на основе изображения. Я также сомневаюсь, что это проблема с использованием точечного освещения. Кроме того, если я сильно уменьшу шероховатость, она станет слишком темной, а высокая шероховатость не будет проблемой.

#glsl #brdf #specular #pbr

Arinvaphoriff51


Рег
25 Oct, 2024

Тем
77

Постов
176

Баллов
611
  • 26, Oct 2024
  • #2

Просто прокомментирую термин 0.16*Specular^2, упомянутый Каримом в комментариях:

Только обморожение переназначает зеркальность для своих внутренних целей, чтобы они могли упаковать зеркальность драгоценных камней в 8-битный канал. Они просто теряют некоторую точность в пользу большего разнообразия. Значение зеркальности является исходным при рендеринге.

Проверьте программу просмотра Disney BRDF, которая является отличным началом для PBR, поскольку она содержит весь BRDF от Disney. БРДФ Эксплорер | Анимационные студии Уолта Диснея

Кроме того, если вы ищете лучшую функцию Френеля, чем

 
 vec3 Light_F(in vec3 Specular, in float VH, in float gloss) 
{

return Specular + (max(vec3(gloss), Specular) - Specular) * pow(1-VH, 5.0f);
}
 

Вместо этого используйте это, поскольку оно учитывает шероховатость/глянец:

vec3 Light_F(in vec3 Specular, in float VH) { // Fresnel Schlick return Specular + (1-Specular) * pow(1-VH, 5.0f); }
 

Ethervish90


Рег
04 Oct, 2010

Тем
68

Постов
192

Баллов
582
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно