forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Проекты C++ (http://forum.boolean.name/forumdisplay.php?f=56)
-   -   [TrueHorror] - разработка (http://forum.boolean.name/showthread.php?t=17293)

Arton 14.05.2014 22:44

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от tirarex (Сообщение 280757)
А хрен его знает как правильно , я поглядел разные игры и можно увидеть что в кадре динамического света очень мало (1-10) редко где больше 10 светильников было .

Даже меньше чем 10 и в зависимости от антуража.
Например на дневной локации будет только один источник света - солнце.

Те же пещеры (то что я замечал), делают с учётом того что бы в одной части не больше 2-3 источников, остальное скрыто. То бишь из просторной пещеры вошёл в "кишку", дальше опять большое пространство. В каждой такой части и будет не больше 2-3 источников. Свет активен только в той части где игрок, + совмещают с картами освещённости. И ещё дизайн локации, то есть две части пещеры не на одной линии, что бы из одной части нельзя было видеть что в следующей.
По большей части это мои предположения.

mr.DIMAS 15.05.2014 12:20

Ответ: [TrueHorror] - разработка
 
Народ ну чё за ботва. Подкиньте идеек по оптимизации.

Mr_F_ 15.05.2014 12:54

Ответ: [TrueHorror] - разработка
 
Нужно сцену смотреть.
Куча лайтов с пересекающейся зоной влияния - много овердро.
Куча отдельных маленьких - должно норм пахать.


А, Ну дак у тебя на каждый лайт фулскрин квад рисуется!
Надо кваду ограничивать зону влияния, иначе тут в любом случае жутчайший овердро.
Известные способы (не мешающие друг другу):
1. Рисовать не фулскрин квад, а квад поменьше, в который вписывается зона влияния лайта. Часто лайты не влияют на весь экран.
2. Рисовать грубый меш по форме зоны влияния лайта (лоуполи сферу для поинта, конус для спота). Рисовать его только в стенсил (не в глубину, не в цвет). Юзать настройки стенсила, как со стенсильными тенями в Depth Fail методе (2 раза не надо только волум рисовать, есть хардварный two-sided stencil):
http://en.wikipedia.org/wiki/Shadow_volume
Это даст тебе помеченные в стенсиле пиксели, куда влияет лайт (где он пересекается со сценой). Дальше рисуешь экранный квад, но настраиваешь стенсил так, чтобы он проявлялся только в помеченых волумом местах. Стенсил тест идёт до выполнения шейдеров.
Это точнее, чем вариант 1, который не учитывает пересечение с збуфером, но вариант 1 тоже не помешает, чтобы сократить число пикселей квада, тестящих стенсил.


---
По мелочам из кода:
Цитата:

vertexShaderPassOne->GetConstantTable()->SetMatrix( g_device, v1View, &view );
vertexShaderPassOne->GetConstantTable()->SetMatrix( g_device, v1Proj, &proj );
vertexShaderPassOne->GetConstantTable()->SetMatrix( g_device, v1World, &world );
Цитата:

pixelShaderPassTwo->GetConstantTable()->SetFloatArray( g_device, p2LightPos, temp, 3 );
pixelShaderPassTwo->GetConstantTable()->SetFloat( g_device, p2LightRange, light->radius );
- многовато лишних действий. много за 1 вызов заливать все матрицы и за 1 все параметры лайта:
SetVertexShaderConstantF
SetPixelShaderConstantF
необязательно по имени брать константы из шейдера, можно замаппить их напрямую в нужные регистры типа
const float4x4 MatWorldViewProj : register(c0);
const float4x4 MatWorld : register(c4);

с# - номера констант, они измеряются в float4, это нативный формат видюшной константы (на самом деле флоаты и флоаты2/3, это все равно неполные флоаты4 или их части).

Но если у тебя там не тысячи объектов, это всё мелочи - просто так удобнее, быстрее, контроллируемее, имхо.

mr.DIMAS 15.05.2014 16:19

Ответ: [TrueHorror] - разработка
 
Спасибо ОГРОМНОЕ! Как сделаю, так сразу отпишусь о результате.

mr.DIMAS 16.05.2014 00:36

Ответ: [TrueHorror] - разработка
 
Вложений: 5
Раньше никогда не работал с буфером трафарета и вот наткнулся на грабли. Вроде все работает как надо - да вот только когда попадаешь в несколько ограничивающих сфер сразу( у меня точечные источники света ) - фпс падает в 2 раза. Причем если источники стоят не пересекаясь между собой - то все норм - фпс 60 ( при разрешении 2560х1440 ). Все норм и при взгляде на всю сцену.

Гляньте код( особенно где трафарет настраивается ) - Mr_F_ я взываю к тебе :-D

http://pastebin.com/FxUaau8D

Демка в аттаче - 60 источников света.

Комменты к скринам: 1 - камера в нескольких ограничивающих сферах одновременно. 2 - там же, взгляд в пол. 3 - вся сцена из далека. 4 - в сцене между источниками света( не попадаю ни в одну ограничивающую сферу )

Mr_F_ 16.05.2014 01:15

Ответ: [TrueHorror] - разработка
 
Цитата:

Гляньте код( особенно где трафарет настраивается ) - Mr_F_ я взываю к тебе
Цитата:

g_device->Clear( 0, 0, D3DCLEAR_STENCIL, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0, 0 );
Clear на каждый лайт не надо делать - это считай тот же фулскрин квад рисовать по филлрейту, медленно.
Вместо этого, когда рисуешь обрезаемый стенсилом квад с шейдингом лайта, ставь ему STENCILPASS = D3DSTENCILOP_ZERO, он тогда автоматически собой затрёт только в нужном месте.

Цитата:

g_device->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
g_device->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
g_device->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
g_device->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE );

// draw a sphere bounds light into stencil buffer
g_device->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
g_device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, icosphereVertexCount, 0, icosphereFaceCount );

// now stecil buffer contains bounding sphere of the light
g_device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
g_device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
Не то делаешь. Ты, похоже, рисуешь в стенсил шарик и маркируешь его единицей. Естественно, когда ты внутри шарика, он занимает весь экран.
Так ты мог и без стенсила обойтись, а сразу рисовать шарик с шейдером лайта.

А идея со стенсилом в том, чтобы пометить только пиксели, с которыми соприкасается (!) шарик. В которые он въехал. Где intersection с z-буфером. Тогда неважно, если ты внутри шарика. По сути задача получить реальную 1-битную маску конкретно освещения от лайта.

Могу перепутать что-то местами (incr/decr), но вроде суть такова (псевдокод):

TwoSidedStencilMode = TRUE
CullMode = None

StencilFunc = Always
StencilZFail = D3DSTENCILOP_DECR

CCW_StencilFunc = Always
CCW_StencilZFail = D3DSTENCILOP_INCR

Представь, что рисуешь шарик, нанизанный на столб. Где внутри шарика не виден столб - там за фронтфейсами всегда видны бекфейсы.
Где фронтфейсы и бекфейсы не пересекаются с тем, что в збуфере - ничего не меняется (ZFail не вызывается).
Где и те и другие где-то под землёй/в стене - одни делают +1, другие -1, ничего не меняется.
А вот там, где у тебя в шарике столб, только бекфейсы вызовут ZFail, в результате столб внутри шара пометится чем-то отличным от 0.
Дальше рисуешь квад с шейдингом лайта с StencilFunc = NotEqual нулю, получается только этот столб осветится, а не целый шар на экране.

mr.DIMAS 16.05.2014 01:25

Ответ: [TrueHorror] - разработка
 
Тоесть Z-буфер не очищать после первого прохода, только запрещать в него запись. Затем для каждого источника света рисовать шарик и проверять, где он не прошел тест глубины, тогда получим силуэт реально освещенной части объекта, находящийся в буфере трафарета. А затем уже рисуем экранный квад с отсечением по трафарету. Так?

Arton 16.05.2014 01:39

Ответ: [TrueHorror] - разработка
 
Цитата:

Сообщение от Arton (Сообщение 280763)
Даже меньше чем 10 и в зависимости от антуража.
Например на дневной локации будет только один источник света - солнце.

Те же пещеры (то что я замечал), делают с учётом того что бы в одной части не больше 2-3 источников, остальное скрыто. То бишь из просторной пещеры вошёл в "кишку", дальше опять большое пространство. В каждой такой части и будет не больше 2-3 источников. Свет активен только в той части где игрок, + совмещают с картами освещённости. И ещё дизайн локации, то есть две части пещеры не на одной линии, что бы из одной части нельзя было видеть что в следующей.
По большей части это мои предположения.

Добавлю. Пример из Dark Souls 2. На первом скриншоте, несмотря на источник света в тёмном помещение, по логике от предметов должны быть тени, но их нет:


Но стоило зажечь факел, как главным источником света стал он и чудесным образом появились тени:


Да, не самый лучший пример, DS это всё таки изначально консольный проект, а значит в первую очередь оптимизировали под них.

P. S. Судя по всему этот "закон" актуален для всех локаций. В DS нету смены дня и ночи, каждая локация статична, и как правило тёмная, или хотя бы закат :)

P. P. S. На одно локации, в маленькой пещере костёр, он главный источник света и теней, зажёг факел, стало два источника, но тени только от факела в руке персонажа.

mr.DIMAS 16.05.2014 01:39

Ответ: [TrueHorror] - разработка
 
Вложений: 1
Цитата:

Тоесть Z-буфер не очищать после первого прохода, только запрещать в него запись. Затем для каждого источника света рисовать шарик и проверять, где он не прошел тест глубины, тогда получим силуэт реально освещенной части объекта, находящийся в буфере трафарета. А затем уже рисуем экранный квад с отсечением по трафарету. Так?
Походу реально так.

Вот код
http://pastebin.com/3x732dwj

Работает все очень шустро - в любом месте 60 фпс.

Демка в аттаче ( 60 источников света )

2Mr_F_ Просто огромное спасибо за разъяснения. То чувство, когда пришло прозрение.

Mr_F_ 16.05.2014 01:51

Ответ: [TrueHorror] - разработка
 
Цитата:

Тоесть Z-буфер не очищать после первого прохода, только запрещать в него запись. Затем для каждого источника света рисовать шарик и проверять, где он не прошел тест глубины, тогда получим силуэт реально освещенной части объекта, находящийся в буфере трафарета. А затем уже рисуем экранный квад с отсечением по трафарету. Так?
типа того, только не просто где шарик не прошёл тест глубины, а именно где только одной стороной повернутые фейсы прошли, а другой не прошли - это будет часть именно внутри шарика.

Цитата:

Работает все очень шустро - в любом месте 60 фпс.
ура!

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

mr.DIMAS 16.05.2014 01:57

Ответ: [TrueHorror] - разработка
 
Вложений: 1
Цитата:

для дебага можно тупо один цвет вывести в шейдере лайта - сразу будет видно на каких пикселях считается лайт, убедиться что всё как надо.
Вот:

LLI.T.A.L.K.E.R. 16.05.2014 02:31

Ответ: [TrueHorror] - разработка
 
хочу просто сказать, что после закрытия приложения выходит ошибка:

tirarex 16.05.2014 14:27

Ответ: [TrueHorror] - разработка
 
Хех , 60фпс , а как такого эффекта добиться ?
С моим деферредом 60 фпс при 10 светильниках :(

Mr_F_ 16.05.2014 14:37

Ответ: [TrueHorror] - разработка
 
на самом деле способ со стенсилом ещё далеко не самый быстрый ;)
на directcompute можно ещё круче наворотить (чем сейчас и занимаюсь)

tirarex 16.05.2014 14:58

Ответ: [TrueHorror] - разработка
 
Как я понимаю там сферы рендерятся ?


Часовой пояс GMT +4, время: 14:49.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot