14 Ноября 2024, 13:59:58
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Навигация по форуму







guest3d
Quest3D - Русскоязычное сообщество > Quest3D > Визуализация, Шейдеры > [sh]Oren-Nayar
[sh]Oren-Nayar
(Прочитано 12451 раз)
  [1]
Печать
Alteste | *** | Постоялец | Сообщений: 224 | « 01 Января 2011, 17:04:40 »
[sh]Oren-Nayar |
0
Хочу прикрутить в квест шейдер с моделью освещения Орена-Наяра.
http://wiki.gamedev.net/index.php/D3DBook:%28Lighting%29_Oren-Nayar
Никак не могу победить косяки на объекте. Может у кого получалось реализовать под квест эту модель освещения?

* oren_nayar.jpg (15.7 Кб, 346x361 - просмотрено 2661 раз.)
* Oren-Nayar.rar (74.77 Кб - загружено 1236 раз.)
Sqwer | ***** | Ветеран | Сообщений: 540 | «Ответ #1 02 Января 2011, 21:56:08 »
Re: [sh]Oren-Nayar |
1
на вскидку  -  нет    добротного тангент спейса


 наложи на бублик  кубовый анврап    1*1*1
Alteste | *** | Постоялец | Сообщений: 224 | «Ответ #2 06 Января 2011, 19:28:33 »
Re: [sh]Oren-Nayar |
2
Решил проблему, вот такой вот должен быть пиксельный шейдер:
Код:
	float3 N = normalize(IN.wnormal);
    float3 L = normalize(IN.LightVector);
float3 V = normalize(IN.EyeVector);

float NdotL = dot(N,L);
float NdotV = dot(N,V);

float alpha = max(acos(NdotL), acos(NdotV));
float beta = min(acos(NdotL), acos(NdotV));
float gamma = dot(V - N * NdotV, L - N * NdotL);

float Roughness1 = 1.0;
float roug_sq = Roughness1 * Roughness1;

float A = 1.0 - 0.5 * (roug_sq / (roug_sq + 0.33));
float B = 0.45 * (roug_sq / (roug_sq + 0.09));


float3 diffuse = max (NdotL, 0.0) * DiffuseColor * (A + B * max(0.0, gamma) * sin(alpha) * tan(beta));

float3 result = diffuse;
return float4(result,1);
тангент и битангент не используем
Sqwer | ***** | Ветеран | Сообщений: 540 | «Ответ #3 06 Января 2011, 19:39:29 »
Re: [sh]Oren-Nayar |
3
а если  потребуется     выпонить рельефное текстурирование (нормал бамп/параллакс/ POM и т.д)?     или  анизотропное освещение (волосы например)?

лучше сделай хороший анврап

ибо

тангент спейс расчитывается   по приращению тексурных
координат  соседних точек и  также их приращению  позиции.

хороший анврап залог хорошего просчёта    пространства касательных.(уж сколько людей на эти грабли  наступали  Веселый)


а вот и твой пример бублика из "0" поста с применённым  кубовым анврапом.



* unwrap.jpg (93.78 Кб, 492x700 - просмотрено 2749 раз.)
« Последнее редактирование: 06 Января 2011, 19:53:49 от Sqwer »
Alteste | *** | Постоялец | Сообщений: 224 | «Ответ #4 06 Января 2011, 20:16:56 »
Re: [sh]Oren-Nayar |
4
Ну если требуется, то можно и с тангент/бинормал, суть не в этом.
Косяк крылся в формуле и я ее исправил, хотя она и сейчас далека от идеала.
Вот так будет выглядеть более-менее грамотная модель освещения Орен-Наяр:
Код:
	const float PI = 3.14159f;

float3 N = normalize(IN.wnormal );
float3 L = normalize(IN.LightVector);
float3 V = normalize(IN.EyeVector);

float NdotL = dot(N,L);
float NdotV = dot(N,V);

    // Compute the other aliases
    float alpha    = max(acos(NdotV), acos(NdotL));
    float beta     = min(acos(NdotV), acos(NdotL));
    float gamma    = dot(V - N * NdotV, L - N * NdotL);

float Roughness = 1.0;
    float rough_sq = Roughness * Roughness;
 
    float C1       = 1.0 - 0.5 * (rough_sq / (rough_sq + 0.33));
 
    float C2       = 0.45 * (rough_sq / (rough_sq + 0.09));
    if( gamma >= 0 )
    {
        C2 *= sin(alpha);
    }
    else
    {
        C2 *= (sin(alpha) - pow((2 * beta) / PI, 3));
    }
 
    float C3  = (1.0 / 8.0) ;
    C3       *= (rough_sq / (rough_sq + 0.09));
    C3       *= pow((4.0 * alpha * beta) / (PI * PI), 2);
 
    float A = gamma * C2 * tan(beta);
    float B = (1 - abs(gamma)) * C3 * tan((alpha + beta) / 2.0);
 
    float3 final = DiffuseColor * max(0.0, NdotL) * (C1 + A + B);
 
    return float4(final, 1.0);
Sqwer | ***** | Ветеран | Сообщений: 540 | «Ответ #5 06 Января 2011, 20:24:34 »
Re: [sh]Oren-Nayar |
5
Цитировать
Косяк крылся в формуле и я ее исправил
и в анврапе также,    я открыл  твой пример с 0 поста, наложел кубовый анврап и всё исправилось.


Ну и одно замечание:
шейдер  очень толстый  при большом кол-ве ИС  и   если в добавок   форвард рендеринг (с большим овердравом), то  о высоком  ФПС  лучше не мечтать.

Лучше использовать  старый  Фонга или  метод освещения из (Half-Life2)  "Пол Ламберта".  Строит глазки

Вот тут   много бумажек  от Валв

про ПолЛамберта можно посмотреть пэпер  за 2004 год.
http://www.valvesoftware.com/company/publications.html
« Последнее редактирование: 06 Января 2011, 20:43:42 от Sqwer »
Alteste | *** | Постоялец | Сообщений: 224 | «Ответ #6 06 Января 2011, 20:53:56 »
Re: [sh]Oren-Nayar |
6
Речь идет о диффузной модели освещения, причем тут фонг?
Пол-Ламберта это так:
Код:
	float3 diffuse = max(dot(N,L), 0.0);
diffuse = diffuse*0.5+0.5;
diffuse *= diffuse;
правильно ли я понял?
Sqwer | ***** | Ветеран | Сообщений: 540 | «Ответ #7 06 Января 2011, 21:08:17 »
Re: [sh]Oren-Nayar |
7
Цитировать
Речь идет о диффузной модели освещения, причем тут фонг?
http://ru.wikipedia.org/wiki/Затемнение_Фонга  не?

вроде дифузнее некуда

Цитировать
правильно ли я понял?
ага

только зачем тут   мах ??
float3 diffuse = max(dot(N,L), 0.0);
« Последнее редактирование: 06 Января 2011, 21:15:25 от Sqwer »
Alteste | *** | Постоялец | Сообщений: 224 | «Ответ #8 06 Января 2011, 21:29:55 »
Re: [sh]Oren-Nayar |
8
для гарантии от отрицательных значений
можно конечно и saturate(dot(N,L)) ну конечно можно и просто dot(N,L) раз ты оптимизируешь код дальше некуда
Sqwer | ***** | Ветеран | Сообщений: 540 | «Ответ #9 06 Января 2011, 21:42:58 »
Re: [sh]Oren-Nayar |
9
Цитировать
для гарантии от отрицательных значений
Веселый


ПолЛамберта  - это физически не коректная модель "мягкого"  освещения.   
И те грани , которые направлены в противоположенную сторону  вектора направления ИС и надо чуть-чуть подсветить.
этими
Код:
max(dot(N,L), 0.0);  или  saturate(dot(N,L))   

ты просто режешь    результат  по отрицательным значениям

и что дальше?

дальше мы отрезанное  умножаем на 0,5,   график функции  сожмётся в 2 раза

далее мы прибавляем 0,5   и у нас  этот  график поднимется на половину по всему  спектру...

это значит , что  все  что ты отрезал окрасится в половинный цвет (если ИС  белый, то результат   будет серым 127 127 127 )

затем мы это всё возводим в квадрат, немного смягчив результат

посчитаем , что  при этом на  задних поликах..  0,5*0,5 = 0,25

Вобщем  лажа получится!!


Надо так и только так:

Цитировать
float3 diffuse = dot(N,L);
   diffuse = diffuse*0.5+0.5;
   diffuse *= diffuse;
Alteste | *** | Постоялец | Сообщений: 224 | «Ответ #10 06 Января 2011, 21:53:34 »
Re: [sh]Oren-Nayar |
10
Ах да точно Смеющийся
Немножко ступил, сенкс!
 
  [1]
Печать
 
Quest3D - Русскоязычное сообщество > Quest3D > Визуализация, Шейдеры > [sh]Oren-Nayar
Перейти в: