Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос по теням (из Example DirectX8/StencilBuffer/ShadowVolume) [Delphi, DirectX 9]


Страницы:   1 2 3

ElectriC ©   (2007-05-11 17:35:00) 

Как сделать, чтобы тени не рисовались на камере?


ElectriC   (2007-06-23 15:18:00) [1]

.


ElectriC   (2007-06-15 18:50:00) [2]

Так что посоветуете делать?


Sapersky   (2007-06-15 15:36:00) [3]

В некоторых ракурсах есть.
Эффект от WeldVertices виден на самолёте и без тени, освещение  становится более гладким.


ElectriC   (2007-06-15 15:18:00) [4]

Так почему в SDK нет "белых точек"?


Sapersky   (2007-06-15 14:47:00) [5]

Я для проверки воткнул в CD3DMesh.Create_ после D3DXLoadMeshFromX:

FillChar(eps, SizeOf(eps), 0);
eps.Flags := D3DXWELDEPSILONS_WELDALL;
Result := D3DXWeldVertices(m_pSysMemMesh, @eps,
           pAdjacencyBuffer.GetBufferPointer,
           pAdjacencyBuffer.GetBufferPointer, nil, nil);

Самолёт - тоже кривой, да.


ElectriC   (2007-06-14 16:09:00) [6]


> Похоже, из-за кривых мешей, в которых имеются избыточные
> вершины.

Тогда получатся, что самолёт (из SDK) тоже кривая мешь, т.к. на тени тоже
появляются точки,а в SDK их нет?((((
Что делать?


ElectriC   (2007-06-13 21:19:00) [7]

Так белые точки как были, так и остались.
Может я что-то не так делаю или ещё что:
...
var
 AdjBuffer : ID3DXBuffer;
 Epsilons  : TD3DXWeldEpsilons;
...

ZeroMemory(@Epsilons, SizeOf(TD3DXWeldEpsilons));
D3DXWeldVertices(SLMeshObj, D3DXWELDEPSILONS_WELDPARTIALMATCHES, @Epsilons,
               AdjBuffer.GetBufferPointer,
               AdjBuffer.GetBufferPointer, nil, nil);
D3DXValidMesh(SLMeshObj, AdjBuffer.GetBufferPointer, nil);
...


Sapersky   (2007-06-13 18:38:00) [8]

В ProgressiveMesh (SDK) есть пример.


ElectriC   (2007-06-13 18:06:00) [9]

Может объяснить, как работать с D3DXWeldVertices?
P.S. Если можно, то на примере.


ElectriC   (2007-06-13 17:14:00) [10]


> Подозреваю, что теневые объёмы пересчитываются на каждом
> кадре для всех объектов.

Кстати пересчитываются только один раз - при первом запуске программы!!!


Sapersky   (2007-06-13 17:10:00) [11]

почему на тенях пояляются  артефакты ввиде белых точек?

Похоже, из-за кривых мешей, в которых имеются избыточные вершины.
Удалить такие вершины - D3DXWeldVertices.

Творение посмотрел... ну что сказать... неплохо для начала.
С тенями на встроенной видео страшно тормозит - 2-3 fps, без - около 30.
Подозреваю, что теневые объёмы пересчитываются на каждом кадре для всех объектов. Так вот, для статичных объектов (школы) можно сделать это один раз в начале, ещё хорошо бы загнать их в VB вместо рисования через DrawPrimitiveUP.

"Отражения" в окнах можно сделать динамическими, см. пример SphereMap из SDK. В SDK8.1 его зачем-то переделали на шейдер, но только Delphi-вариант, С++ остался (видимо, Cooltie забыл обновить) на автоматической генерации текстурных координат, что ИМХО проще:

       // Generate spheremap texture coords, and shift them over
       D3DXMATRIX mat;
       mat._11 = 0.5f; mat._12 = 0.0f; mat._13 = 0.0f; mat._14 = 0.0f;
       mat._21 = 0.0f; mat._22 =-0.5f; mat._23 = 0.0f; mat._24 = 0.0f;
       mat._31 = 0.0f; mat._32 = 0.0f; mat._33 = 1.0f; mat._34 = 0.0f;
       mat._41 = 0.5f; mat._42 = 0.5f; mat._43 = 0.0f; mat._44 = 1.0f;
       m_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat );
       m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
       m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );

Само собой, окна тогда нужно рендерить отдельно от всего.
Некоторые пояснения есть в readme к примеру.


ElectriC   (2007-06-13 15:04:00) [12]

.


ElectriC   (2007-06-12 18:56:00) [13]

Кстати, если не лень, можешь посмотреть, почему на тенях пояляются
артефакты ввиде белых точек?
P.S. Если не лень скачай моё первое творение ;))) -> http://slil.ru/24404040/874845188/School_54.rar


ElectriC   (2007-06-12 18:19:00) [14]

За перевод спасибо (хотя и не надо было - перевёл давно уже сам).
Мне бы разобраться, как не рисовать тень на камере.


Sapersky   (2007-06-12 17:40:00) [15]

А я вот, в свою очередь, не понимаю, что мешает попытаться понять самостоятельно.
Ну, кроме лени, конечно. А мне, что ли, не лень писать за тебя?

Векторную алгебру, насколько помню, в школе изучают. Даже если ещё не - тем лучше, сейчас выучишь, потом не надо будет.
Фактически здесь нужно использовать:
1) для определения, какой стороной полигон повёрнут к ист. света - скалярное произведение (dot product) даёт косинус угла между векторами. Синусы/косинусы в школе изучают однозначно...
2) угол нужно искать между нормалью полигона и вектором от ист. света. Нормаль (перпендикуляр) получается векторным произведением (cross product) двух граней полигона.
3) для получения заднего среза теневого объёма - масштабирование (scale), сложение/вычитание (add/subtract) векторов.

Причём с нуля писать ничего не надо, всё это уже есть в TShadowVolume.BuildFromMesh (построение стандартного теневого объёма), но используется несколько по-другому. Т.е. нужно понять, что именно там происходит, и дописать на основе это кода "затычки" к теневому объёму.

Что касается переделки CMyD3DApplication.RenderShadow на z-fail - там чуть ли не каждая строчка откомментирована, даже не зная английского можно уловить знакомые словосочетания "z-pass" и "z-fail" и сделать выводы. Щёлкнув с Ctrl на любую константу вроде D3DRS_STENCILPASS можно найти в Direct3D.pas список других подходящих для этой функции констант, часто с поясняющими комментариями.

Могу даже сделать перевод (пока это всё ещё z-pass, я только выкинул кое-что лишнее):

function CMyD3DApplication.RenderShadow: HResult;
begin
m_pd3dDevice.SetTransform(D3DTS_WORLD, m_matObjectMatrix);

// Выключаем запись в z-буфер (но z-тест работает)
m_pd3dDevice.SetRenderState(D3DRS_ZWRITEENABLE,  iFALSE);
// включаем stencil-буфер
m_pd3dDevice.SetRenderState(D3DRS_STENCILENABLE, iTRUE);

// Выключить цветовую интерполяцию (для оптимизации, не обязательно)
m_pd3dDevice.SetRenderState(D3DRS_SHADEMODE,     D3DSHADE_FLAT);

// Выключаем вывод на экран теневых объёмов.
// Чтобы они рисовались - закомментировать
m_pd3dDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, iTRUE);
m_pd3dDevice.SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ZERO);
m_pd3dDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

// для большей наглядности при рисовании теневых объёмов можно ещё включить wireframe-режим
//  m_pd3dDevice.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

// Устанавливаем stencil-функцию сравнения, в данном случае stencil-тест
// всегда проходит (D3DCMP_ALWAYS). Другие константы в Direct3D8.pas.
m_pd3dDevice.SetRenderState(D3DRS_STENCILFUNC,  D3DCMP_ALWAYS);

// Если stencil и Z-тесты проходят, увеличиваем значения в буфере.
// поскольку stencil-тест проходит всегда, фактически получается "если Z-тест проходит"
m_pd3dDevice.SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR);
// Рисуем только передние грани
m_pd3dDevice.SetRenderState(D3DRS_CULLMODE,   D3DCULL_CСW);
// выводим объём
m_pShadowVolume.Render(m_pd3dDevice);

// Если stencil и Z-тесты проходят, уменьшаем значения в буфере
m_pd3dDevice.SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR);
// Рисуем только задние грани
m_pd3dDevice.SetRenderState(D3DRS_CULLMODE,   D3DCULL_CW);
// выводим объём
m_pShadowVolume.Render(m_pd3dDevice);

// Восстанавливаем стейты
m_pd3dDevice.SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
m_pd3dDevice.SetRenderState(D3DRS_CULLMODE,  D3DCULL_CCW);
m_pd3dDevice.SetRenderState(D3DRS_ZWRITEENABLE,     iTRUE);
m_pd3dDevice.SetRenderState(D3DRS_STENCILENABLE,    iFALSE);
m_pd3dDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, iFALSE);
m_pd3dDevice.SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);

Result := S_OK;
end;

Будут КОНКРЕТНЫЕ вопросы по деталям - задавай.


ElectriC   (2007-06-12 15:27:00) [16]

Так как же??? ;)))


ElectriC   (2007-06-12 15:25:00) [17]

Конечно ;))))))))))


Sapersky   (2007-06-12 13:14:00) [18]

Это тот же z-fail.
Как выяснилось отсюда:
http://developer.nvidia.com/attach/6831
отличие его в том, что нужно "заткнуть" теневой объём с двух сторон полигонами модели. Спереди (или сверху, в общем, с той стороны, которая ближе к источнику света) - лицевыми по отношению к источнику света, сзади - соответственно, задними, перемещёнными к заднему срезу теневого объёма и отмасштабированными под этот срез. Ну вот эти самые "задние грани модели, вытянутые в бесконечность".

Догадываюсь, какой будет следующий пост...
"Так я не понимаю, как реализовать это на дельфи?"


ElectriC   (2007-06-11 19:14:00) [19]

Кста:

>Исправляем ситуацию, когда камера находится внутри объёма.
>1. Отключим запись в буфер глубины и цвета
>2. Включим отсечение передних граней. Установим операция в >инкрементирование на единицу при провале теста глубины. Нарисуем >объём.
>3. Включим отсечение задних граней. Установим операцию трафарета в >уменьшение на единицу при провале теста глубины. Нарисуем объём.
>Все освещённые точки будут иметь значение 0 в буфере трафарета.
>Для нормальной работы метода может потребоваться отрисовка всех >задних граней модели, вытянутых в бесконечность, но в большинстве >случаев этого не требуется, так как эти грани в любом случае были бы >закрыты геометрией.

Как реализовать этот метод - может поможет???


ElectriC   (2007-06-11 18:42:00) [20]

Да, видимо, всё сложнее, чем думалось))


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо