Пятница, 19 Апреля 2024, 17:53

Приветствую Вас Гость

Меню сайта
Категории каталога
Создание игр [355]
Статьи об общих понятиях связанных с созданием игр.
Программирование [82]
Гайды по программированию на разных ЯП.
Движки и Гейммейкеры [145]
Статьи о программах для создания игр, уроки и описания.
Софт [43]
Различные программы, в том числе в помощь игроделам.
2D-графика [14]
Уроки по рисованию, растр, пиксель-арт, создание спрайтов и пр.
3D-графика [16]
Уроки по моделированию, ландшафт, модели, текстурирование и пр.
Моддинг игр [5]
Модификация компьютерных игр, создание дополнений, перевод, хакинг.
Игры [161]
Статьи об играх, в том числе и сделанных на гейммейкерах.
Разное [129]
Статьи, которые не вошли в определённые разделы.
Наш опрос
Вы создаете собственные сайты?
Всего ответов: 1919
Главная » Статьи » Программирование

Программирование 3D графики на Visual Basic 6 и DirectX 8. Часть 3
2.1. Организация проекта
До сих пор все наши проекты состояли из одной единственной формы. Весь код проекта не был распределен по модулям. Это, конечно, неправильный подход, он применялся для более легкого освоения начальных понятий программирования с использованием Direct3D, ведь пока вы не уясните основные принципы такого программирования, не будет понятна и логика деления кода на модули.
Однако постепенно у нас выделились процедуры, которые мы переносили из проекта в проект практически не меняя. В первую очередь это D3DInit – инициализация Direct3D. Создадим новый модуль, в котором будем собирать самые необходимые процедуры, относящиеся к Direct3D. Объявим в нем глобальные переменные:

Code
Public dx8 As New DirectX8
Public d3d As Direct3D8
Public d3dx As New D3DX8
Public d3dDevice As Direct3DDevice8

Также имеет смысл объявить константу Pi:

Code
Public Const Pi = 3.141593

И сама процедура D3DInit:

Code
Public Sub D3DInit(hWnd As Long)
Dim DispMode As D3DDISPLAYMODE
Dim d3dpp As D3DPRESENT_PARAMETERS

  Set d3d = dx8.Direct3DCreate
  d3d.GetAdapterDisplayMode D3DADAPTER_DEFAULT, DispMode

  d3dpp.Windowed = True
  d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD
  d3dpp.BackBufferFormat = DispMode.Format
  d3dpp.BackBufferCount = 1
  d3dpp.EnableAutoDepthStencil = True
  d3dpp.AutoDepthStencilFormat = D3DFMT_D16

  Set d3dDevice = d3d.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd _
  , D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp)  
End Sub

Для уничтожения объектных переменных, созданных в модуле, послужит процедура D3DTerminate:

Code
Public Sub D3DTerminate()
  Set d3dx = Nothing
  Set d3dDevice = Nothing
  Set d3d = Nothing
  Set dx8 = Nothing
End Sub

Так же сюда может войти неизменная функция vec3:

Code
Public Function vec3(x As Single, y As Single, z As Single) As D3DVECTOR
  vec3.x = x
  vec3.y = y
  vec3.z = z
End Function

В форме желательно держать только код обработки событий контролов формы. Один из них – таймер, поместим на форму соответствующий контрол и настроим его на 1000 мс интервал. С помощью таймера мы будем в дальнейшем замерять быстродействие. Еще одно важнейшее событие формы – ее закрытие. Немного изменим код его обработки:

Code
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  If Running Then Cancel = 1: Running = False
End Sub

А вот для синхронизации движения таймер применять мы больше не будем, он применялся для простоты в самых начальных проектах. Дело в том, что таймер обладает невысокой точностью при измерении небольших интервалов времени, теперь для этого мы применим более современную API функцию – QueryPerformanceCounter.
Для функций API можно создать отдельный модуль и поместить туда такой код:

Code
Option Explicit

Private Type int64
  dw1 As Long
  dw2 As Long
End Type

Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As int64) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As int64) As Long
Dim QSpeed As Double

Public Function QTime() As Double
Dim QD As int64, t As Double
  QueryPerformanceCounter QD
  If QD.dw1 < 0& Then t = QD.dw1 + 4294967296# Else t = QD.dw1
  If QD.dw2 < 0& Then t = t + (QD.dw2 + 4294967296#) * 4294967296# _
Else t = t + QD.dw2 * 4294967296#
  QTime = t * QSpeed
End Function

Public Sub QFreqIni()
Dim QD As int64
  QueryPerformanceFrequency QD
  If QD.dw1 < 0& Then QSpeed = QD.dw1 + 4294967296# Else QSpeed = QD.dw1
  If QD.dw2 < 0& Then QSpeed = QSpeed + (QD.dw2 + 4294967296#) * 4294967296# _
  Else QSpeed = QSpeed + QD.dw2 * 4294967296#
  QSpeed = 1# / QSpeed
End Sub

В начале работы программы однократно вызываем QFreqIni, и для получения значения текущего времени в секундах пользуемся функцией QTime.
И создадим еще один, пока последний, модуль – modMain, в свойствах проекта укажем, что стартовым должен быть именно этот модуль, а не форма. В этом модуле будут находиться все наши «эксперименты» до тех пор, пока они не удостоятся переноса в уже существующий или вновь созданный модуль. Если поместить в modMain такой код:

Code
Option Explicit

Public Running As Boolean
Public FPS As Long

Public Sub Main()
  frmD3D.Show
  QFreqIni
  D3DInit frmD3D.hWnd
  Running = True
  Do While Running
  DoEvents
  Render
  FPS = FPS + 1
  Loop
  Unload frmD3D
  ClearAll
End Sub

Private Sub Render()
  d3dDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &HFFFFFF * Rnd, 1, 0
  d3dDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub

Private Sub ClearAll()
  D3DTerminate
End Sub

Мы получим приблизительный аналог нашего первого проекта, где мы закрашивали форму в разные цвета.
Можно в обработчик события Timer формы поместить следующий код, чтобы измерять быстродействие нашей программы:

Code
Private Sub TimerFPS_Timer()
  Me.Caption = FPS
  FPS = 0
End Sub

Этот проект находится на компакт-диске в папке Pr12.
Теперь, когда наша «перестройка» завершена, продолжим заниматься изучением Direct3D.

2.2. Мип-мэппинг, фильтрация текстур
При текстурировании существует проблема. Текстура состоит из конечного числа точек, которые называются текселями. На текстурируемой поверхности текстурные координаты могут располагаться с различной плотностью, кроме того сама поверхность может находиться дальше или ближе к камере, что приводит к изменению видимых размеров. В результате текстура накладывается некорректно. Представьте, что текстура, шириной в 16 текселей должна отобразиться на участок бэкбуфера, шириной в 17 или 15 пикселей. В первом случае один из текселей должен будет отобразиться на два пикселя, во втором одному из текселей не хватает места. Когда размер изображения значительно превышает размер текстуры, последняя, как говорят, «распадается на клетки».
Для наглядности сделаем проект. В модуль modMain предыдущего проекта добавьте все необходимое для создания вертексного буфера на четыре вертекса и одной текстуры. Вертекс должен содержать координаты XYZ и текстурные координаты. Создайте квадрат, размером 2 * 2 с центром в начале координат так, чтобы текстура десять раз укладывалась на поверхность квадрата:

Code
Private Sub InitGeometry()
Dim Vert(3) As vFormat
  vSize = Len(Vert(0))
  Set vBuf = d3dDevice.CreateVertexBuffer(4 * vSize, 0, vFlag, D3DPOOL_DEFAULT)
  Vert(0) = Vertex(-1, 0, -1, -5, -5)
  Vert(1) = Vertex(-1, 0, 1, -5, 5)
  Vert(2) = Vertex(1, 0, -1, 5, -5)
  Vert(3) = Vertex(1, 0, 1, 5, 5)
  D3DVertexBuffer8SetData vBuf, 0, 4 * vSize, 0, Vert(0)
End Sub

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

Code
D3DXMatrixLookAtLH Mtrx, vec3(0, 0.03, -1), vec3(0, -0.39, 0), vec3(0, 1, 0)
  d3dDevice.SetTransform D3DTS_VIEW, Mtrx

Проинициализируйте остальные необходимые трансформации. Поместите в процедуру Render команду рисования квадрата, используя D3DPT_TRIANGLESTRIP для двух треугольников. Можно взять уже знакомую текстуру кирпичей.
Если при запуске программы вы видите черное поле, видимо вы забыли запретить использование света. Так же поместите перед основным циклом команду инициализации QueryPerformanceCounter – QFreqIni, а в сам цикл вращение трансформации мира:

Code
D3DXMatrixRotationY Mtrx, QTime * 0.1

Теперь мы видим медленно вращающийся квадрат, в таком ракурсе прекрасно видно все виды искажения текстуры. Вдали текстура вообще превращается в мелкую рябь, вблизи распадается на клетки и, лишь на небольшом отдалении, где истинный размер текстуры близок к отображаемому, поле выглядит достаточно прилично. Для начала избавимся от самого неприятного искажения – ряби в удалении. Для этого применяется мип-мэппинг. Суть его состоит в том, что для отображения мелких или удаленных объектов, когда истинный размер текстуры превышает отображаемый, используется другая текстура более мелкого размера, полученная из первоначальной. При загрузке текстуры сразу создаются эти дополнительные изображения – их называют мип-уровнями. Линейные размеры каждого следующего мип-уровня вдвое меньше, чем у предыдущего. Последний мип-уровень, если мы явно не указали другое, имеет размер 1 * 1. Текстурой в Direct3D называется не отдельное изображение, а весь этот набор мип-уровней, при текстурировании Direct3D сам выбирает из них наиболее подходящий.
И самое интересное, что все эти мип-уровни уже созданы, нам лишь осталось разрешить их применение. Для этого в инициализацию добавим всего одну строку:

Code
d3dDevice.SetTextureStageState 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR

И вот рябь исчезла, а быстродействие даже возросло! Но текстура по-прежнему распадается на клетки, для борьбы с этим применяется другой метод – фильтрация. При выборке из текстуры берется усредненное значение текселей, соседних с точкой выборки. Способ вычисления может быть разный, но, как правило, применяется линейная фильтрация. Для ее включения достаточно одной строки:

Code
d3dDevice.SetTextureStageState 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR

Это мы включили фильтрацию на увеличение текстуры. Картинка вблизи стала лучше, но при удалении клетки все еще есть. Включим такую же фильтрацию и на уменьшение:

Code
d3dDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR

Теперь картинка почти идеальна, есть лишь один недостаток – при удалении текстура сильно «размазана» по поверхности. Это происходит оттого, что мы видим поверхность под острым углом, и при подборке такого мип-уровня, чтобы размер текселя «вдоль» направления взгляда примерно соответствовал размеру пикселя, размер текселя в направлении «поперек» значительно превышает размер пикселя, что сильно заметно на глаз. С этим тоже можно бороться, для этого существует так называемая анизотропная фильтрация. Заменим MINFILTER на такой:

Code
d3dDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC

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

Code
d3dDevice.SetTextureStageState 0, D3DTSS_MAXANISOTROPY, 4

Это ограничение нужно потому, что анизотропная фильтрация – это очень тяжелые вычисления, сильно снижающие производительность, мы вынуждены искать баланс между качеством и скоростью. Кроме того, различные видеоадаптеры поддерживают различный максимальный уровень анизотропии, и желательно не превышать этот уровень, хотя опыт показывает, что превышение этого уровня не приводит к сбою работы программы. Вполне возможно, что вы сейчас не увидели эффекта от включения анизотропной фильтрации, это означает, что ваш видеоадаптер ее не поддерживает.
Этот проект находится на компакт-диске в папке Pr13.

2.3. Caps. Проверка совместимости
До сих пор мы применяли в основном стандартные функции Direct3D, совместимые практически с любыми современными видеоадаптерами. И только в предыдущем проекте мы столкнулись с возможной несовместимостью. Возникает вопрос, а можно ли написать программу так, чтобы она узнавала «на месте» возможности оборудования и автоматически выбирала наиболее оптимальный режим работы, либо отказывалась работать при необходимости? Можно. Для этого в DirectX имеется структура Caps, содержащая всю необходимую информацию об оборудовании. Пользоваться ей очень просто. Добавьте в модуль modDX общую переменную типа D3DCAPS8:

Code
Public Caps As D3DCAPS8

А в процедуру D3DInit строку для ее заполнения:

Code
d3d.GetDeviceCaps D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Caps

Теперь мы можем узнавать необходимые нам сведения. Например, в предыдущем проекте можно таким образом выбрать уровень анизотропии:

Code
If Caps.MaxAnisotropy >= 4 Then
  d3dDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC
  d3dDevice.SetTextureStageState 0, D3DTSS_MAXANISOTROPY, 4
  ElseIf Caps.MaxAnisotropy >= 2 Then
  d3dDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC
  d3dDevice.SetTextureStageState 0, D3DTSS_MAXANISOTROPY, 2
  Else
  d3dDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR
  End If

Можно также предоставить возможность пользователю программы самому выбрать режим фильтрации из возможных вариантов. Полный список всех полей Caps имеется в DirectX SDK. Мы еще не раз будем возвращаться к этой полезной структуре.

2.4. Мультитекстурирование
До сих пор мы накладывали на наши модели не более одной текстуры, в то время как Direct3D позволяет использовать одновременно до восьми текстур. Мы уже не раз использовали такую команду:

Code
d3dDevice.SetTextureStageState

Далее шло три аргумента – первый 0, далее константа из набора (Enum) CONST_D3DTEXTURESTAGESTATETYPE, определяющая какой именно параметр текстурирования мы хотим установить, например D3DTSS_MIPFILTER означает выбор типа мип-фильтрации. Последний параметр функции – непосредственное значение для данного параметра. Для большинства параметров текстурирования созданы наборы констант с допустимыми значениями, но для некоторых, например D3DTSS_MAXANISOTROPY, далее идет просто численное, типа Long, значение.
Текстуры накладываются стадиями. То есть некоторое количество текстур (до трех) определенным образом смешиваются, и результат уже выводится на экран. Точнее так обстоит дело для последней используемой стадии, результаты предыдущих стадий являются одним из аргументов для следующих. Наравне с текстурами в стадиях текстурирования участвуют и некоторые другие величины, например Diffuse – цвет вертекса либо материала.
Вспомним, что первым аргументом d3dDevice.SetTextureStageState был 0. Это и есть номер стадии текстурирования, настройку параметров которой мы производим. Максимальное количество стадий, как и текстур – восемь. К сожалению, такое количество текстур и стадий текстурирования поддерживает далеко не любая видеокарта. Допустимые количества можно узнать из Caps.MaxSimultaneousTextures и Caps.MaxTextureBlendStages.
Со стадиями и текстурами немного разобрались. А как же параметры текстурирования? Мы пользовались уже текстурой в сочетании с цветом (Diffuse), и они сочетались корректно, хотя мы не указывали никаких конкретных способов их смешивания. Дело в том, что многие настройки в Direct3D сделаны заранее и являются настройками по умолчанию. Так по умолчанию используется одна стадия текстурирования, в которой происходит умножение текстуры и цвета (Diffuse). Если мы не установили текстуру либо цвет – по умолчанию используется белый цвет. «Внутри» Direct3D любой цвет представлен так же, как мы привыкли, компонентами R, G и B (есть еще A, но об этом позже). Но в Direct3D это не байты от 0 до 255, а дробные значения от 0 до 1. Таким образом, при умножении любого цвета на белый, цвет не меняется. Давайте вспомним наш первый пример с цилиндром. Вместо того, чтобы увидеть текстуру, мы сначала увидели черный цвет, текстура стала видна лишь после запрещения использования света. А все дело в том, что если свет разрешен, но не включено ни одного источника света, Diffuse будет черным, а значит, черным будет и произведение на Diffuse любой текстуры. Вместо строки:

Code
d3dDevice.SetRenderState D3DRS_LIGHTING, 0

Можно было написать:

Code
d3dDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1

И текстура станет видимой! Вместо того, чтобы выключить свет, мы изменили способ, каким смешиваются
аргументы нулевой стадии текстурирования. По умолчанию действовали следующие установки:

Code
d3dDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE
  d3dDevice.SetTextureStageState 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE
  d3dDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_MODULATE

То есть первый аргумент – текстура, второй – цвет, действие – умножение. Мы заменили умножение D3DTOP_MODULATE на выбор первого аргумента D3DTOP_SELECTARG1.
Попробуем добиться какого-нибудь полезного эффекта, используя две текстуры. За основу берем проект из главы «Мип-мэппинг, фильтрация текстур». Для начала то, что мы уже отладили – фильтрация текстур, перенесем в модуль ModDX. Для этого создадим такую процедуру:

Code
Public Sub TexFilter(Stage As Long, TF As TexF, Optional MaxAnisotropy As Long = 2)
  Select Case TF
  Case TexF_None
  d3dDevice.SetTextureStageState Stage, D3DTSS_MIPFILTER, D3DTEXF_NONE
  d3dDevice.SetTextureStageState Stage, D3DTSS_MAGFILTER, D3DTEXF_NONE
  d3dDevice.SetTextureStageState Stage, D3DTSS_MINFILTER, D3DTEXF_NONE
  Case TexF_BiLinear
  d3dDevice.SetTextureStageState Stage, D3DTSS_MIPFILTER, D3DTEXF_POINT
  d3dDevice.SetTextureStageState Stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR
  d3dDevice.SetTextureStageState Stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR
  Case TexF_TriLinear
  d3dDevice.SetTextureStageState Stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR
  d3dDevice.SetTextureStageState Stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR
  d3dDevice.SetTextureStageState Stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR
  Case TexF_Anisotropic
  d3dDevice.SetTextureStageState Stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR
  d3dDevice.SetTextureStageState Stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR
  If Caps.MaxAnisotropy >= MaxAnisotropy Then
  d3dDevice.SetTextureStageState Stage, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC
  d3dDevice.SetTextureStageState Stage, D3DTSS_MAXANISOTROPY, MaxAnisotropy
  ElseIf Caps.MaxAnisotropy >= 2 Then
  d3dDevice.SetTextureStageState Stage, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC
  d3dDevice.SetTextureStageState Stage, D3DTSS_MAXANISOTROPY, Caps.MaxAnisotropy
  Else
  d3dDevice.SetTextureStageState Stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR
  End If
  End Select
End Sub

Аргументами процедуры TexFilter являются номер стадии текстурирования, один из четырех стандартных вариантов фильтрации и, необязательный аргумент – уровень анизотропии. Для вариантов фильтрации можно сделать набор констант, чтобы обращаться к ним по именам:

Code
Public Enum TexF
TexF_None
TexF_BiLinear
TexF_TriLinear
TexF_Anisotropic
End Enum

Имена констант говорят сами за себя, так что расшифровывать не буду.
Теперь нам понадобится две пары текстурных координат, поэтому переделаем формат вертекса:

Code
Private Type vFormat
  Pos As D3DVECTOR
  tu0 As Single
  tv0 As Single
  tu1 As Single
  tv1 As Single
End Type

Так же переделаем его флаговое описание:

Code
Private Const vFlag = D3DFVF_XYZ Or D3DFVF_TEX2

И функцию Vertex:

Code
Private Function Vertex(x As Single, y As Single, z As Single, tu0 As Single _
, tv0 As Single, tu1 As Single, tv1 As Single) As vFormat
  Vertex.Pos = vec3(x, y, z)
  Vertex.tu0 = tu0
  Vertex.tv0 = tv0
  Vertex.tu1 = tu1
  Vertex.tv1 = tv1
End Function

Вспомним, как мы генерировали цилиндр, и немного переделаем с учетом применения двух текстур:

Code
Private Sub InitGeometry()
Dim Vert(1) As vFormat
Dim n As Long
  vSize = Len(Vert(0))
  Set vBuf = d3dDevice.CreateVertexBuffer(2 * 65 * vSize, 0, vFlag, D3DPOOL_DEFAULT)
  For n = 0 To 64
  Vert(0) = Vertex(Sin(2 * Pi * n / 64), 1, Cos(2 * Pi * n / 64), _
  3 * n / 64, 0, 12 * n / 64, 0)
  Vert(1) = Vertex(Sin(2 * Pi * n / 64), -1, Cos(2 * Pi * n / 64), _
  3 * n / 64, 1, 12 * n / 64, 4)
  D3DVertexBuffer8SetData vBuf, vSize * 2 * n, vSize * 2, 0, Vert(0)
  Next n
End Sub

Создадим две текстуры:

Code
Set Tex0 = d3dx.CreateTextureFromFile(d3dDevice, App.Path & "\brick.jpg")
  Set Tex1 = d3dx.CreateTextureFromFile(d3dDevice, App.Path & "\detail.jpg")

Файлы brick.jpg и detail.jpg есть в папке Pr14 на компакт-диске.
Также подберите подходящие матрицы для основных трансформаций (это вы уже можете), впишите все необходимое для создания и уничтожения цилиндра с двумя текстурами и инициализации QueryPerformanceCounter. В основной цикл можно вписать такие строки:

Code
D3DXMatrixRotationY Mtrx, QTime * 0.5
  d3dDevice.SetTransform D3DTS_WORLD, Mtrx
  D3DXMatrixLookAtLH Mtrx, vec3(0, 0, -7 + 5 * Sin(QTime * 0.5)), vec3(0, 0, 0), vec3(0, 1, 0)
  d3dDevice.SetTransform D3DTS_VIEW, Mtrx

Здесь мы заставляем выводимую геометрию вращаться, а камеру циклично приближаться и удаляться от начала координат. Можно также включить фильтрацию текстур обеих стадий, не зря же мы писали процедуру TexFilter:

Code
TexFilter 0, TexF_TriLinear
  TexFilter 1, TexF_TriLinear

Запускаем программу – цилиндр черный. Это мы уже проходили! Настраиваем нулевую стадию текстурирования:

Code
d3dDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1
  d3dDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE

Теперь все в порядке, цвет появился, но текстура только одна, первая стадия текстурирования выключена. Во-первых, в процедуре Render нужно указывать не одну, а две текстуры:

Code
d3dDevice.SetTexture 0, Tex0
  d3dDevice.SetTexture 1, Tex1

Во-вторых, укажем аргументы и оператор для первой стадии:

Code
d3dDevice.SetTextureStageState 1, D3DTSS_COLOROP, D3DTOP_MODULATE2X
  d3dDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_TEXTURE
  d3dDevice.SetTextureStageState 1, D3DTSS_COLORARG2, D3DTA_CURRENT

Здесь мы первый аргумент, текстуру, умножаем на второй – D3DTA_CURRENT, этот аргумент – результат работы предыдущей стадии текстурирования. Обратите внимание, что умножение используется не D3DTOP_MODULATE, а D3DTOP_MODULATE2X. Этот оператор домножает результат перемножения аргументов на 2, что позволяет использовать одну текстуру в качестве карты теней для другой. Вспомните, что в Direct3D компоненты цвета лежат в диапазоне от 0 до 1. Если использовать в качестве второго аргумента серую текстуру (R = 128, G = 128, B = 128), мы умножаем первый аргумент сначала на 0.5, потом на 2 – то есть не меняем. Если на серой текстуре сделать более темные и более светлые места – в этих местах первый аргумент будет соответственно затемняться и высветляться.
Обратите внимание, что текстурные координаты у первой текстуры расположены более «густо», чем у нулевой. Это позволяет добиться детализации нулевой текстуры при сильном приближении.
Этот проект находится на компакт-диске в папке Pr14.

Продолжение

Категория: Программирование | Добавил: -Mikle- (15 Января 2011)
Просмотров: 6969 | Рейтинг: 5.0/1 |
Теги: vb, DirectX 8.1, D3D, программирование, DirectX 8, Direct3D, VB6, Visual Basic, Visual Basic 6, Программирование 3D графики
Дополнительные опции:
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:

Игровые объявления и предложения:
Если вас заинтересовал материал «Программирование 3D графики на Visual Basic 6 и DirectX 8. Часть 3», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела. Предлагаются такие схожие материалы: Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.

Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск по сайту
10 случ. движков
  • Harfang 3D
  • Neobook
  • FOnline
  • PrBoom-plus
  • PopCap Games Framework
  • Yami RPG Editor
  • Devana
  • Silent Walk: RENAISSANCE
  • Genesis3D
  • Away3D
  • Друзья сайта
    Игровой форум GFAQ.ru Перевод консольных игр
    Все права сохранены. GcUp.ru © 2008-2024 Рейтинг