[Главная] [Новости] [Статьи] [Игры] [Проекты] | [Автор] | |||
Основы 3D-программирования DirectX8.1 в Delphi 6-7: теоретические и практические основы создания игр. | ||||
[Все уроки] | ||||
Конечно, данная статья не является заменой DirectX SDK. В первую очередь нужно обращаться к нему, если Вы все-таки решили заняться созданием 3D-игр под DirectX. | Однако цель данной статьи - помочь Вам сделать первый шаг в освоении программирования под DirectX8.1 на Delphi 6-7. Поэтому здесь Вы не найдете исчерпывающих объяснений и описаний. Только подспорье в освоении DirectX'а!!! | |||
Итак, что же такое шейдеры? | ||||
Применительно к DirectX 8.1 - это небольшие куски кода (написанные на особом, шейдерном языке) в виде ascii-текста в обычном текстовом файле, но с расширением *.vsh или *.psh. Они позволяют видоизменить способ по-пиксельной и по-вершинной обработки информации участвующей в потоке рендеринга (отрисовки). Пиксельные шэйдеры (pixel shader) могут включать максимально до 12 команд; вершинные (vertex shader)- до 128 команд. Описание команд и их использования приводится в DirectX8.1 SDK. | ||||
В нашем уроке файлы шейдеров в папке media\shaders из архива, который Вы, надеюсь, уже скачали. | ||||
Следует отметить, что начинать изучение шейдеров лучше с пиксельных (pixel shaders). Они меньше по размеру и несколько проще для понимания. Однако всю мощь и силу шейдеров Вы обретете изучив и вершинные шейдеры. | ||||
Можно ли обойтись вообще без шейдеров? На первых этапах да, но когда Вы разберетесь с ними, то, наверное, уже и не сможете от них отказаться. Многие эффекты в играх реализованы именно при помощи шейдеров. Это не что-то сверхъестественное. Просто DirectX 8.1 предоставляет Вам большую свободу в выборе средств реализации эффектов в играх, поэтому пригодятся Вам и знания шэйдеров. К тому же, именно по такому принципу - принципу перевода ascii-текста в байт-коды - осуществляется, надо полагать, и скриптование в реализованных игровых движках. | ||||
Вот необходимые шаги для использования шейдера: в классе приложения объявить поля соответствующие обработчику шейдера - m_dwSubmarineVertexShader: Cardinal; в методе CSubmarineD3DApp.Create обнулить данный обработчик m_dwSubmarineVertexShader := 0; в методе CSubmarineD3DApp.RestoreDeviceObjects смотри содержимое метода RestoreRenderCausticsStates; т.е. ввести описания вершин var begin {...} //
Create vertex shader for the submarine {...} // и загрузить код шейдера из файла hr
:= D3DUtil_CreateVertexShader(m_pd3dDevice, 'media\shaders\submarine.vsh', end;
|
||||
в методе CSubmarineD3DApp.FrameMove смотри метод AnimateCausticTex; там в константные регистры АЛУ вершинного шейдера загружаются необходимые данные в таком виде m_pd3dDevice.SetVertexShaderConstant( 0, vZero, 1); {...} Если посмотреть на весь исходный код данного метода, то станет ясно, что это данные мировой, видовой и проекционной матриц, необходимые для обработки данных о вершинах моделей, поступающих в шейдер. |
||||
И наконец в методе CSubmarineD3DApp.RenderCaustic происходит установка и использование шейдеров для обработки вершин в таком виде: // Render the submarine
m_matWorldOfMesh := m_matSubmarine; т.е. вершины моделей должны быть предварительно скопированы в вершинный буфер, для того, чтобы их можно было обрабатывать шейдером. Следовательно, предварительно требуется еще и использование вершинных и индексных буферов, в нашем случае это m_pSubmarineVB, m_pSubmarineIB. Как они создаются и используются - смотрите в исходном коде данного примера, который Вы скачали. |
||||
Мы не затронули проблему разработки кода самого шейдера. Для этого Вам понадобится знание шейдерного языка. Но на первых порах Вы можете использовать имеющиеся в примере шейдеры - как основу для разработки своих шейдеров, когда они Вам потребуются. | ||||
Для отладки шейдеров желательно написать отдельное тестовое приложение, в котором помимо самого тестируемого участка кода отследить результаты создания или ассемблирования шейдера. При изучении шейдеров можно вначале проверить код приложения путем использования заведомо корректно написанного шейдера. | ||||
В нашем примере Вы можете получить следующие интересные эффекты, применив уже известную Вам методику комментирования отдельных участков кода и перекомпиляции приложения. | ||||
в исходном коде примера найдите реализацию метода CSubmarineD3DApp.RenderCaustic | ||||
применив комментирующие скобки {} закомментируйте следующий блок кода: // Render the submarine { m_matWorldOfMesh
:= m_matSubmarine; } |
||||
Откомпилируйте и запустите приложение. Теперь плавает не сама подлодка, а ее бликовая копия!! | ||||
То же самое можно проделать с другими участками кода, выяснив, где отрисовываются блики, а где сама модель. | ||||
Еще одно интересное упражнение. Обратите внимание, для отрисовки статичного дна используется один шейдер m_dwSeaFloorVertexShader3, а для подлодки - m_dwSubmarineVertexShader. | ||||
Попробуем поменять шейдеры местами: найдите кусочек кода - //
Render the seafloor и строку m_pd3dDevice.SetVertexShader(m_dwSeaFloorVertexShader3); перепишите так: m_pd3dDevice.SetVertexShader(m_dwSubmarineVertexShader{m_dwSeaFloorVertexShader3}); //этим мы добиваемся подмены используемого вершинного шейдера для морского дна на используемый для подлодки. Перекомпилируем и запускаем. Ничего не произошло! Что ж, тоже результат. Делаем вывод - эти шейдеры равнозначны! Если теперь попробовать открыть код данного шейдера и намеренно внести в него ошибку, то можно понять как тестировать код шейдера на корректность. Однако мы еще не закончили наши упражнения! |
||||
Теперь попробуем по-другому, найдите кусочек кода: //
Render the seafloor и закомментируйте так //SetMatWorldOfMesh; |
||||
Перекомпилируйте и запустите приложение. Ну как? Вращается морское дно? | ||||
Теперь Вы немного больше знаете о шейдерах и скоро перестанете бояться их! | ||||
[Назад] [Все уроки] | ||||
[Главная] [Новости] [Статьи] [Игры] | ||||
(c) Мега Информатик 2006-2007 |