Всем привет, вот решил создать класс небесной оболочки, используя файл эффекта из "Кнут"а.
После нескольких дней мучений, иправления тонны ошибок , просмотра десятков сайтов по этой тематике дошёл до того что эффект рисует этот куб, но кубическая текстура ресуется только с одной стороной, неправильно повёрнута да ещё и занимает 1/4 стороны куба...ППЦ
Вот файл класса куба
sky_model.cpp
#include "sky_model.h"
struct Vertex
{
Vertex(){}
Vertex(
float x, float y, float z
)
{
_x = x; _y = y; _z = z;
}
float _x, _y, _z;
};
#define FVF_VERTEX (D3DFVF_XYZ)
cSkyModel::cSkyModel(IDirect3DDevice9* device, Camera* TheCamera)
{
Device = device;
D3DXMatrixIdentity(&_world);
_bgtexture = 0;
_SkyBoxEffect = 0;
_WorldViewProjHandle = 0;
_TexHandle = 0;
_SkyBoxTechHandle = 0;
D3DXMatrixIdentity(&_WorldViewProj);
_TheCamera = TheCamera;
}
cSkyModel::~cSkyModel()
{
if(_vb){_vb->Release(); _vb = 0;}
if(_ib){_ib->Release(); _ib = 0;}
if(_bgtexture) _bgtexture->Release();
// Device->Release(); // закомить- иначе ошибка gпри закрытии приложения, уберается один раз
}
bool cSkyModel::CreateCube( void )
{
Device->CreateVertexBuffer(
24 * sizeof(Vertex),
D3DUSAGE_WRITEONLY,
FVF_VERTEX,
D3DPOOL_MANAGED,
&_vb,
0);
Vertex* v;
float W=1.0f, H=1.0f, L=1.0f;
_vb->Lock(0, 0, (void**)&v, 0);
// build box
// fill in the front face vertex data
v[0] = Vertex( -W, -H, -L);
v[1] = Vertex( -W, H, -L);
v[2] = Vertex( W, H, -L);
v[3] = Vertex( W, -H, -L);
// fill in the back face vertex data
v[4] = Vertex( -W, -H, L);
v[5] = Vertex( W, -H, L);
v[6] = Vertex( W, H, L);
v[7] = Vertex( -W, H, L);
// fill in the top face vertex data
v[8] = Vertex( -W, H, -L);
v[9] = Vertex( -W, H, L);
v[10] = Vertex( W, H, L);
v[11] = Vertex( W, H, -L);
// fill in the bottom face vertex data
v[12] = Vertex( -W, -H, -L);
v[13] = Vertex( W, -H, -L);
v[14] = Vertex( W, -H, L);
v[15] = Vertex( -W, -H, L);
// fill in the left face vertex data
v[16] = Vertex( -W, -H, L);
v[17] = Vertex( -W, H, L);
v[18] = Vertex( -W, H, -L);
v[19] = Vertex( -W, -H, -L);
// fill in the right face vertex data
v[20] = Vertex( W, -H, -L);
v[21] = Vertex( W, H, -L);
v[22] = Vertex( W, H, L);
v[23] = Vertex( W, -H, L);
_vb->Unlock();
Device->CreateIndexBuffer(
36 * sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&_ib,
0);
WORD* i = 0;
_ib->Lock(0, 0, (void**)&i, 0);
// fill in the front face index data
i[0] = 0; i[1] = 1; i[2] = 2;
i[3] = 0; i[4] = 2; i[5] = 3;
// fill in the back face index data
i[6] = 4; i[7] = 5; i[8] = 6;
i[9] = 4; i[10] = 6; i[11] = 7;
// fill in the top face index data
i[12] = 8; i[13] = 9; i[14] = 10;
i[15] = 8; i[16] = 10; i[17] = 11;
// fill in the bottom face index data
i[18] = 12; i[19] = 13; i[20] = 14;
i[21] = 12; i[22] = 14; i[23] = 15;
// fill in the left face index data
i[24] = 16; i[25] = 17; i[26] = 18;
i[27] = 16; i[28] = 18; i[29] = 19;
// fill in the right face index data
i[30] = 20; i[31] = 21; i[32] = 22;
i[33] = 20; i[34] = 22; i[35] = 23;
_ib->Unlock();
//////////////////////////////////////////////////////////////////////
//
// Создание эффекта
//
HRESULT hr = 0;
ID3DXBuffer* errorBuffer = 0;
hr = D3DXCreateEffectFromFile(
Device, // связанное устройство
"simple_skybox.fx", // имя файла эффекта
0, // нет определений препроцессора
0, // нет интерфейса ID3DXInclude
D3DXSHADER_DEBUG, // флаги компиляции
0, // нет совместного использования параметров
&_SkyBoxEffect, // возвращает указатель на интерфейс эффекта
&errorBuffer); // возвращает сообщения об ошибках
// Выводим любые сообщения об ошибках
if(errorBuffer)
{
::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);
errorBuffer->Release();
}
if(FAILED(hr))
{
::MessageBox(0, "D3DXCreateEffectFromFile() - FAILED", 0, 0);
return false;
}
//
// Сохраняем дескрипторы часто используемых параметров
//
_SkyBoxTechHandle = _SkyBoxEffect->GetTechniqueByName("BasicCubeMap");
_WorldViewProjHandle = _SkyBoxEffect->GetParameterByName(0, "mWorldViewProj");
_TexHandle = _SkyBoxEffect->GetParameterByName(0, "tex0");
//
// Устанавливаем параметры эффекта
//
// Матрица
_SkyBoxEffect->SetMatrix(_WorldViewProjHandle, &_WorldViewProj);
// Текстура
hr = D3DXCreateTextureFromFile(Device, "models/skybox1.dds", &_bgtexture); //skybox1.dds
if(FAILED(hr) )
{
::MessageBox(0, "SkyBox->D3DXCreateTextureFromFile() - FAILED", 0, 0);
return false;
}
_SkyBoxEffect->SetTexture(_TexHandle, _bgtexture);
return true;
}
bool cSkyModel::render(bool wireframe)
{
Device->SetTransform(D3DTS_WORLD, &_world);
// Устанавливаем используемую технику
_SkyBoxEffect->SetTechnique(_SkyBoxTechHandle);
UINT numPasses = 0;
_SkyBoxEffect->Begin(&numPasses, 0); // техника, пуск
// Устанавливаем переменные эффекта
_TheCamera->getSkyBoxMatrix(&_WorldViewProj, Device);
_SkyBoxEffect->SetMatrix(_WorldViewProjHandle, &_WorldViewProj);
for(int i = 0; i < numPasses; i++)
{
_SkyBoxEffect->BeginPass(i); // техника, проход
Device->SetStreamSource(0, _vb, 0, sizeof(Vertex));
Device->SetIndices(_ib);
Device->SetFVF(FVF_VERTEX);
Device->DrawIndexedPrimitive(
D3DPT_TRIANGLELIST,
0,
0,
24,
0,
12);
}
_SkyBoxEffect->End(); // техника остановка
D3DXMATRIX I;
D3DXMatrixIdentity(&I);
Device->SetTransform(D3DTS_WORLD, &I);
return true;
}
sky_model.h
#ifndef __sky_modelH__
#define __sky_modelH__
#include <string>
#include <vector>
#include "camera.h"
class cSkyModel
{
public:
cSkyModel(IDirect3DDevice9* device, Camera* TheCamera);
~cSkyModel();
bool CreateCube( void );
bool render(bool wireframe);
private:
IDirect3DDevice9* Device;
D3DXMATRIX _world;
IDirect3DVertexBuffer9* _vb;
IDirect3DIndexBuffer9* _ib;
// Effect
IDirect3DTexture9* _bgtexture; //текстура куба
Camera* _TheCamera;
ID3DXEffect* _SkyBoxEffect;
D3DXHANDLE _WorldViewProjHandle;
D3DXHANDLE _TexHandle;
D3DXHANDLE _SkyBoxTechHandle;
D3DXMATRIX _WorldViewProj;
};
#endif //CSKYBOX_H
Класс использует камеру(с огромным количеством ненужного кода), которая уже обсуждалась (где-то здесь я видел её, поэтому её код
приложен но не обсуждается), её задача заключается в создании и передаче матрицы SkyBox эффекту(функция Camera::getSkyBoxMatrix).
чтобы запустить эту белиберду
в приложении нужно в...
своём главном файле включить заголовки
#include "sky_model.h"
#include "camera.h"
определить класс камеры и скайбокса
Camera TheCamera(Camera::LANDOBJECT);
cSkyModel* _SkyModel;
далее где-нибудь настроить камеру и создать скайбокс (один раз
)
TheCamera.setProjParam( Device, D3DX_PI * 0.25f, (float)Width/(float)Height, 0, 0);
Width - ширина экрана
Height - высота
// create skymodel
_SkyModel = new cSkyModel(_device, TheCamera);
if ( !_SkyModel->CreateCube() )
{
::MessageBox(0, "_SkyModel->CreatePMesh - FAILED", 0, 0);
::PostQuitMessage(0);
}
Перед рендерингом
TheCamera.ReadInput(timeDelta);
// timeDelta - может быть любое число например 0.7f ("чувствительность" камеры)
// Update the view matrix representing the cameras new position/orientation.
TheCamera.useCamera( Device );
теперь в функции рендеринга
if(_SkyModel)
_SkyModel->render(false);
вот кажется и всё разжевал
... а да ещё надо при завершении приложения реализовать класс _SkyModel, но это уж как-нибудь сами)
файл эффекта во вложениях, а кубическую текстуру(models/skybox1.dds) , к сожалению не могу передать, слишком много весит
Мне кажется с матрицей, что передается в эффект(Camera::getSkyBoxMatrix) что-то не так