Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Где я туплю? Спекулярная компонента по Фонгу для неосвещенных (отвернутых) поверхностей

Где я туплю? Спекулярная компонента по Фонгу для неосвещенных (отвернутых) поверхностей

Dmitry_MilkПостоялецwww11 янв. 20180:45#0
Делал свою модель освещения для специфических условий, отталкиваясь от Фонга.
Вроде все нормально получилось, но на неосвещенных/отвернутых поверхностях (угол между вектором на источник света и нормалью больше 90 градусов) заметил глюк освещения.

Разбор полетов показал, что "виновата" спекулярная компонента, коэффициент которой при некоторых углах обзора может оказываться больше нуля. Вроде бы понятно - на поверхностях с такой ориентацией освещение должно быть занулено (за исключением амбъента и эмиссии). Стал искать, где же я что-то потерял, когда переделывал исходный Фонг-алгоритм.

И ... не нашел!
Смотрю на исходный шейдер (конкретно этот взят с википедии)

+ Показать

и понимаю (то есть, не понимаю, как это так), что в нем эта проблема точно также должна проявляться!

А именно - max(dot(r, e), 0.0) на неосвещенной поверхности точно также как и у меня может оказаться больше нуля: предположим, что угол между l и n совсем чуть-чуть больше 90, тогда r хоть и смотрит "под поверхность", угол между r и e может быть меньше 90 градусов, если я смотрю на поверхность "вскользь". То есть, этот алгоритм тоже может давать ненулевой спекуляр на неосвещенной поверхности.

В каком месте у меня в ДНК ошибка? почему нигде не пишут о таком глюке (да и я его вроде не наблюдал, когда делал этот алгоритм напрямую).

Great V.Пользовательwww11 янв. 20181:35#1
Dmitry_Milk
1. Скрины
2. Обнуляй при (n,l) < 0
Были бы тени - не заметил бы.
innuendoПостоялецwww11 янв. 20189:47#2

vec4 Ispec = gl_FrontLightProduct[li].specular * pow(max(dot(r, e), 0.0), gl_FrontMaterial.shininess) * max(dot(n, l), 0.0);;
Dmitry_MilkПостоялецwww11 янв. 201812:07#3
Great V.
> 2. Обнуляй при (n,l) < 0

innuendo
> * max(dot(n, l), 0.0)

Да это понятно (кстати, все же правильнее * step(0, dot(n, l)), как Great V. предложил).

Меня просто смутило, почему этот момент не упоминается ни в одной из найденных мной статей по фонг-освещению (везде в лоб ищется отраженный вектор и берется pow от скалярного произведения нормализованных отражения и взора), и в результате, если освещение чисто фонговское без теней и самозатенения, то на теневой стороне действительно может вылезать спекуляр (скажем, заметно на шарах при невысоком shininess,  ярком specular-цвете и слабом ambient-цвете материала). Впрочем, возможно на это просто забивают на фоне тех недостатков чистого фонга, что проявляются из-за отсутствия честного замозатенения на сложных выпукло/вогнутых фигурах (правда вышеописанный глюк проявляется даже на шарах).

g-contПостоялецwww11 янв. 201813:38#4
Dmitry_Milk
я тоже обращал на это внимание но никогда не придавал значения. Всегда умножал спекуляр на NdotL и не парился.
MisanthropeЗабаненwww27 янв. 20180:24#5
Dmitry_Milk
> Да это понятно (кстати, все же правильнее * step(0, dot(n, l))
пардоньте, не понял, почему правильнее?
хотя да, при определенных условиях вроде можно и резко спекуляр рубануть, так как под тем углом он уже затухнет полностью.

Правка: 27 янв. 2018 0:34

Dmitry_MilkПостоялецwww27 янв. 20189:58#6
Misanthrope
> не понял, почему правильнее?

Потому что в идеальном зеркале яркость отражения (мы же про спекуляр говорим, не про диффуз) источника света, воспринимаемая глазом, не зависит от угла падения. Ты рассматриваешь в зеркале лампочку - ее яркость не меняется (если зеркало не грязное), под каким бы углом к лампочке зеркало не находилось, главное, чтоб лампа находилась в той области, отражение которой видит глаз.

Впрочем, уже не важно. Я нашел ошибку в своих преобразованиях - при переиспользовании уже вычисленных компонентов в реализации функции reflect я случайно вместо уже вычисленного dot(n,l) воспользовался Cdiff (они совпадают, пока угол меньше прямого). После исправления ложный спекуляр (он все же есть) действительно стал почти незаметен.

innuendoПостоялецwww27 янв. 201811:55#7
Dmitry_Milk
> реализации функции reflect

у тебя свой reflect?

Dmitry_MilkПостоялецwww27 янв. 201812:08#8
Фактически он такой же, 2 * dotLN * N - L, но я не был уверен, что встроенный reflect честно реализован для четырехмерных векторов. Проверил с встроенным reflect - результаты такие же.
innuendoПостоялецwww27 янв. 201812:59#9
Dmitry_Milk
> что встроенный reflect честно реализован для четырехмерных векторов.

зачем reflect для vec4 ? рекомендуют использовать встроенное

Dmitry_MilkПостоялецwww27 янв. 201814:21#10
innuendo
> зачем reflect для vec4 ?

Потому что упомянутые в первом посте специфические условия - четырехмерные координаты :)

ronnikoЗабаненwww27 янв. 201815:51#11
Думаю надо Фонгу позвонить и спросить.
Dmitry_MilkПостоялецwww27 янв. 201816:58#12
Уже не надо, уже все работает (в плане диффуза и спекуляра).

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр