dx sample의 tiger.x와 tiger.bmp를 소스 폴더에 넣어주어야 제대로 동작합니다.
#include <Windows.h>
using namespace System;
using namespace System::Windows::Forms;
using namespace System::Drawing;
using namespace SlimDX;
using namespace SlimDX::Direct3D9;
struct TextureVertex
{
Vector3 positon;
int color;
float tu, tv;
};
public ref class WndForm : public Form
{
Direct3D^ direct3D;
PresentParameters^ presentParams;
Device^ device;
Mesh^ mesh;
array<Material^>^ meshMaterials;
array<Texture^>^ meshTextures;
SlimDX::Direct3D9::Font^ font;
public:
String^ lastError;
String^ fps1;
String^ fps2;
Int32 staticFPS;
Int32 variableFPS;
WndForm(void)
{
this->ClientSize = System::Drawing::Size(400, 300);
this->StartPosition = FormStartPosition::CenterScreen;
this->Text = "D3D Tutorial 8";
}
~WndForm()
{
this->!WndForm();
}
!WndForm()
{
Release();
}
bool InitD3D()
{
try {
// 환경변수 세팅
direct3D = gcnew Direct3D();
presentParams = gcnew PresentParameters();
presentParams->Windowed = true;
presentParams->SwapEffect = SwapEffect::Discard;
presentParams->DeviceWindowHandle = this->Handle;
presentParams->EnableAutoDepthStencil = true;
presentParams->AutoDepthStencilFormat = Format::D16;
device = gcnew Device(direct3D, 0, DeviceType::Hardware, this->Handle, CreateFlags::SoftwareVertexProcessing, presentParams);
// render state
device->SetRenderState(RenderState::CullMode, Cull::None);
device->SetRenderState(RenderState::ZEnable, true);
device->SetRenderState(RenderState::Ambient, 0xffffff);
// model
mesh = Mesh::FromFile(device, "tiger.x", MeshFlags::SystemMemory);
array<ExtendedMaterial>^ materials = mesh->GetMaterials();
meshMaterials = gcnew array<Material^>(materials->Length);
meshTextures = gcnew array<Texture^>(materials->Length);
for (int i = 0; i < materials->Length; i++) {
meshMaterials[i] = materials[i].MaterialD3D;
meshMaterials[i]->Ambient = meshMaterials[i]->Diffuse;
meshTextures[i] = Texture::FromFile(device, materials[i].TextureFileName);
}
// font
System::Drawing::Font^ nfont = gcnew System::Drawing::Font("Arial", 15);;
font = gcnew SlimDX::Direct3D9::Font(device, nfont);
return true;
}
catch (Direct3D9Exception^ ex) {
lastError = ex->ToString();
return false;
}
}
void Release()
{
if (mesh)
delete mesh;
for (int i = 0; i < meshMaterials->Length; i++)
delete meshMaterials[i];
for (int i = 0; i < meshTextures->Length; i++)
delete meshTextures[i];
if (font)
delete font;
if (direct3D)
delete direct3D;
if (device)
delete device;
}
void SetupMatrix()
{
device->SetTransform(TransformState::World, Matrix::RotationY(Environment::TickCount / 1000.0f));
device->SetTransform(TransformState::View, Matrix::LookAtLH(Vector3(0.0f, 3.0f, -5.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 1.0f, 0.0f)));
device->SetTransform(TransformState::Projection, Matrix::PerspectiveFovLH((float)Math::PI / 4, 1.0f, 1.0f, 100.0f));
}
void Render()
{
if (!device)
return;
// 렌더링 시작
device->Clear(ClearFlags::Target | ClearFlags::ZBuffer, System::Drawing::Color::Black, 1.0f, 0);
device->BeginScene();
SetupMatrix();
// 렌더링
font->DrawString(nullptr, fps1, 20, 20, 0xffff0000);
font->DrawString(nullptr, fps2, 20, 40, 0xffff0000);
for (int i = 0; i < meshMaterials->Length; i++) {
device->Material = *meshMaterials[i];
device->SetTexture(0, meshTextures[i]);
mesh->DrawSubset(i);
}
// 렌더링 끝
device->EndScene();
device->Present();
}
void SetFPS(int sFPS, int vFPS)
{
staticFPS = sFPS;
variableFPS = vFPS;
fps1 = staticFPS.ToString();
fps2 = variableFPS.ToString();
}
};
ref class FrameControl
{
float timer;
float frameRate;
public:
FrameControl()
{
SetFrameRate(60.0f);
}
~FrameControl()
{
}
void SetFrameRate(float fps)
{
frameRate = 1.0f / fps;
}
bool Update(float dt)
{
timer += dt;
if (timer < 0)
return false;
timer -= frameRate;
return true;
}
bool FrameMove()
{
if (timer >= 0)
return true;
return false;
}
};
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
WndForm^ frm = gcnew WndForm();
FrameControl^ fc = gcnew FrameControl();
if (!frm->InitD3D()) {
MessageBox::Show(frm->lastError);
delete frm;
return 0;
}
frm->Show();
frm->fps1 = "";
frm->fps2 = "";
fc->SetFrameRate(60.0f);
int curTick = Environment::TickCount;
int lastTick = curTick;
int tickGap;
int staticFrame, variableFrame;
int lastStaticFrame = 0;
int lastVariableFrame = 0;
while (frm->Created) {
// ms단위의 delta time
tickGap = Environment::TickCount - curTick;
curTick = Environment::TickCount;
// 언제나 고정적으로 해야하는 작업 (intput, network etc..)
if (fc->Update((float)tickGap / 1000.0f))
staticFrame++;
// 상황에 따라 많이 할수도 적게 할수도 있는 작업 (rendering etc..)
if (!fc->FrameMove()) {
variableFrame++;
frm->Render();
Application::DoEvents();
// 작업의 부하를 테스트하기 위해 밑의 값을 변동해보면 어떻게 동작하는지 볼 수 있습니다. (10~50ms)
//Sleep(30);
}
// 초당 프레임율을 계산해서 문자열로 변환
if ((Environment::TickCount - lastTick) > 1000) {
staticFrame -= lastStaticFrame;
variableFrame -= lastVariableFrame;
frm->SetFPS(staticFrame, variableFrame);
lastTick = Environment::TickCount;
lastStaticFrame = staticFrame;
lastVariableFrame = variableFrame;
}
}
delete frm;
return 0;
}


0 개의 댓글:
댓글 쓰기