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

Возьмем наш предыдущий проект, оставив в InitMesh генерацию чайника:

код на языке vb
 
Private Sub InitMesh()
  Set Mesh = d3dx.CreateTeapot(d3dDevice, Nothing)
End Sub
 

Так же уберем все, связанное с использованием света и материала. Добавим в модуль modMain текстуру Tex и процедуру Setting, где будем испытывать нововведения, не забываем вписать вызов Setting перед главным циклом. Текстуру загрузим из файла sky.jpg, находящегося в папке Pr17. Содержимое Setting сначала будет таким:

код на языке vb
 
Private Sub Setting()
  d3dDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_CCW
  d3dDevice.SetRenderState D3DRS_ZENABLE, D3DZB_TRUE
 
  Set Tex = d3dx.CreateTextureFromFile(d3dDevice, "sky.jpg")
  TexFilter 0, TexF_TriLinear
 
  d3dDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1
  d3dDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE
  d3dDevice.SetTexture 0, Tex
End Sub
 

Пока все по старому, загрузили текстуру, настроили нулевую стадию текстурирования. Однако текстуры не видно, ведь мы не указали текстурные координаты, вся модель закрашена цветом, взятым из текстуры с координат 0, 0. Добавим в Setting такую строку:

код на языке vb
 
  d3dDevice.SetTextureStageState 0, D3DTSS_TEXCOORDINDEX, _
  D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
 

Теперь чайник затекстурирован, но текстура не очень похожа на отражение. Описать работу этой команды, не вдаваясь в подробности, можно так – вычисляется направление нормали вертекса относительно направления на камеру. Если нормаль направлена на камеру – результирующие значения u и v текстурных координат равны нулю. Если нормаль направлена левее – значение u уменьшается, правее – увеличивается. Если нормаль направлена выше – значение v уменьшается, ниже – увеличивается. Изменения u и v лежат в диапазоне от -1 до 1, причем u и v не могут принять крайние значения диапазона одновременно, они лежат в пределах окружности с центром в начале координат и радиусом 1 на координатной плоскости. Но на нашей текстуре изображение отражения лежит на вчетверо меньшей (по площади) окружности с центром в точке 0.5, 0.5 и радиусом 0.5.

Познакомимся с четвертой трансформацией, помогающей исправить эту ситуацию. Это трансформация D3DTS_TEXTURE0, позволяющая с помощью матриц задавать изменения текстурных координат нулевой стадии текстурирования, аналогичные трансформации существуют для всех восьми стадий. Добавим в процедуру Setting такие строки:

код на языке vb
 
  D3DXMatrixTranslation Mtrx, 0.5, 0.5, 0
  d3dDevice.SetTransform D3DTS_TEXTURE0, Mtrx
  D3DXMatrixScaling Mtrx, 0.5, 0.5, 1
  d3dDevice.MultiplyTransform D3DTS_TEXTURE0, Mtrx
 

Необходимо там же объявить переменную Mtrx типа D3DMATRIX.
Запускаем программу, но картинка не поменялась, все потому, что использование этой трансформации по умолчанию запрещено. Такой строкой мы разрешаем ее использовать для изменения двух текстурных координат:

код на языке vb
 
  d3dDevice.SetTextureStageState 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2
 

Теперь изображение гораздо больше похоже на натуральное.