我想使用directx11显示.obj文件,所以我写了一些代码,当我尝试构建时,他们没有说任何特殊错误,但没有银色上下文没有显示。我找不到什么是错的。 这是我的整个代码。请给我一些建议。
这些代码基于“Frank Luna使用directx 11进行3D游戏编程简介”。 d3dApp.h只是创建窗口代码。
或许,你会觉得这段代码太长了,我知道。我为此感到遗憾,但我试图减少绘图中的无关代码。所以,请耐心等待并给我一些建议。请。这是我的主要代码
class Read_Pawn : public D3DApp
{
public:
Read_Pawn(HINSTANCE hInstance);
bool Init();
void DrawScene();
private:
XMFLOAT4X4 mView;
XMFLOAT4X4 mProj;
float mTheta;
float mPhi;
float mRadius;
POINT mLastMousePos;
Object Pawn;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
Read_Pawn Pawn(hInstance);
if (!Pawn.Init())
return 0;
return Pawn.Run();
}
Read_Pawn::Read_Pawn(HINSTANCE hInstance)
: D3DApp(hInstance), mTheta(1.5f*MathHelper::Pi), mPhi(0.25f*MathHelper::Pi), mRadius(5.0f), Pawn("Pawn")
{
mMainWndCaption = L"Pawn Read";
mLastMousePos.x = 0;
mLastMousePos.y = 0;
XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&mView, I);
XMStoreFloat4x4(&mProj, I);
}
bool Read_Pawn::Init()
{
if (!D3DApp::Init())
return false;
Effects::InitAll(md3dDevice);
Pawn.Init(md3dDevice);
Pawn.Create(md3dDevice, "pawn.obj");
return true;
}
void Read_Pawn::DrawScene()
{
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::Silver));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
Pawn.Draw(md3dImmediateContext, &mView, &mProj);
HR(mSwapChain->Present(0, 0));
}
这是我的.fx代码
cbuffer cbPerObject
{
float4x4 gWorldViewProj;
};
struct VertexIn
{
float3 PosL : POSITION;
float3 Normal : NORMAL;
float2 Texcoord : TEXCOORD0;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
float4 Color : COLOR;
};
VertexOut VS(VertexIn vin)
{
VertexOut vout;
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
vout.Color = float4(1.0f, 0.0f, 0.0f, 0.0f);
return vout;
}
float4 PS(VertexOut pin) : SV_Target
{
return pin.Color;
}
technique11 LoadVertex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
};
这是我的效果代码 头
class Effect
{
public:
Effect(ID3D11Device* pdevice, const std::wstring& filename);
private:
Effect(const Effect& rhs);
protected:
ID3DX11Effect* mFX;
};
class BasicEffect : public Effect
{
public:
BasicEffect(ID3D11Device* pdevice, const std::wstring& filename);
void SetWorldViewProj(CXMMATRIX M) { WorldViewProj->SetMatrix(reinterpret_cast<const float*>(&M)); };
public:
ID3DX11EffectTechnique* pLoadVertex;
ID3DX11EffectMatrixVariable* WorldViewProj;
};
class Effects
{
public:
static void InitAll(ID3D11Device* pdevice);
public:
static BasicEffect* BasicFX;
};
体
Effect::Effect(ID3D11Device* pdevice, const std::wstring& Filename) : mFX(0)
{
std::ifstream fin(Filename, std::ios::binary);
fin.seekg(0, std::ios_base::end);
int size = (int)fin.tellg();
fin.seekg(0, std::ios_base::beg);
std::vector<char> CompiledShader(size);
fin.read(&CompiledShader[0], size);
fin.close();
HR(D3DX11CreateEffectFromMemory(&CompiledShader[0], size, 0, pdevice, &mFX));
}
BasicEffect::BasicEffect(ID3D11Device* pdevice, const std::wstring& Filename) : Effect(pdevice, Filename)
{
pLoadVertex = mFX->GetTechniqueByName("LoadVertex");
WorldViewProj = mFX->GetVariableByName("gWorldViewProj")->AsMatrix();
}
BasicEffect* Effects::BasicFX = 0;
void Effects::InitAll(ID3D11Device* pdevice)
{
_chdir("FX");
BasicFX = new BasicEffect(pdevice, L"Basic.fxo");
_chdir("..");
}
这是我的顶点代码 头
namespace VERTEX
{
struct objVertex
{
XMFLOAT3 position;
XMFLOAT3 normal;
XMFLOAT2 texcoord;
};
}
class InputLayoutDesc
{
public:
static const D3D11_INPUT_ELEMENT_DESC objVertex[3];
};
class InputLayouts
{
public:
static void Init(ID3D11Device* device);
static ID3D11InputLayout* Get_objVertex() { return objVertex; };
private:
static ID3D11InputLayout* objVertex;
};
CPP
const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::objVertex[3] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
ID3D11InputLayout* InputLayouts::objVertex = 0;
void InputLayouts::Init(ID3D11Device* device)
{
D3DX11_PASS_DESC passDesc;
//objVertex
Effects::BasicFX->pLoadVertex->GetPassByIndex(0)->GetDesc(&passDesc);
HR(device->CreateInputLayout(InputLayoutDesc::objVertex, 3, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &objVertex));
}
对象头
class Object
{
void Init(ID3D11Device* pDevice);
HRESULT Create(ID3D11Device* pDevice, const char* Filename);
void Draw(ID3D11DeviceContext* DeviceContext, XMFLOAT4X4* View, XMFLOAT4X4* Proj);
private:
ID3D11Buffer* pmVB;
ID3D11Buffer* pmIB;
UINT mVCount;
UINT mTCount;
UINT mNCount;
UINT mICount;
XMFLOAT4X4 mWorld;
typedef std::unordered_multimap<UINT, UINT> VertexCache;
VertexCache vertexCache;
std::vector<VERTEX::objVertex> vertices;
private:
HRESULT LoadGeometryFromOBJ(const WCHAR* strFilename, vector<UINT>* vindices);
HRESULT CreateBuffer(ID3D11Device* Device, vector<UINT>* vindices);
DWORD AddVertex(UINT hash, VERTEX::objVertex* pVertex, VertexCache& cache);
};
体
//this code read only vertex without meterial.
void Object::Init(ID3D11Device* pDevice)
{
InputLayouts::Init(pDevice);
}
HRESULT Object::Create(ID3D11Device* pDevice, const char* Filename)
{
vector<UINT> Indices;
wchar_t* strFilename = new wchar_t[MAX_PATH];
mbstowcs(strFilename, Filename, strlen(Filename) + 1);
HR(LoadGeometryFromOBJ(strFilename, &Indices));
HR(CreateBuffer(pDevice, &Indices));
return S_OK;
}
HRESULT Object::LoadGeometryFromOBJ(const WCHAR* strFilename, vector<UINT>* Indices)
{
vector<XMFLOAT3> Positions;
vector<XMFLOAT2> TexCoords;
vector<XMFLOAT3> Normals;
//change directory
_chdir("Models");
std::ifstream InFile;
InFile.open(strFilename);
char strCommand[256] = { 0 };
for (;;)
{
InFile >> strCommand;
if (!InFile)
break;
if (0 == strcmp(strCommand, "#"))
{
// Comment
}
else if (0 == strcmp(strCommand, "v"))
{
// Vertex Position
float x = 0, y = 0, z = 0;
InFile >> x >> y >> z;
Positions.push_back(XMFLOAT3(x, y, z));
mVCount++;
}
else if (0 == strcmp(strCommand, "vt"))
{
// Vertex TexCoord
float u, v;
InFile >> u >> v;
TexCoords.push_back(XMFLOAT2(u, v));
mTCount++;
}
else if (0 == strcmp(strCommand, "vn"))
{
// Vertex Normal
float x, y, z;
InFile >> x >> y >> z;
Normals.push_back(XMFLOAT3(x, y, z));
mNCount++;
}
else if (0 == strcmp(strCommand, "f"))
{
// Face
UINT iPosition, iTexCoord, iNormal;
VERTEX::objVertex vertex;
for (UINT iFace = 0; iFace < 3; iFace++)
{
ZeroMemory(&vertex, sizeof(VERTEX::objVertex));
// OBJ format uses 1-based arrays
InFile >> iPosition;
vertex.position = (Positions)[iPosition - 1];
if ('/' == InFile.peek())
{
InFile.ignore();
if ('/' != InFile.peek())
{
// Optional texture coordinate
InFile >> iTexCoord;
vertex.texcoord = (TexCoords)[iTexCoord - 1];
}
if ('/' == InFile.peek())
{
InFile.ignore();
// Optional vertex normal
InFile >> iNormal;
vertex.normal = (Normals)[iNormal - 1];
}
}
/////////////////////////////////////////////////////////////
DWORD index = AddVertex(iPosition, &vertex, vertexCache);
Indices->push_back((UINT)index);
mICount++;
/////////////////////////////////////////////////////////////
}
}
}
InFile.close();
_chdir("..");
return S_OK;
}
HRESULT Object::CreateBuffer(ID3D11Device* Device, vector<UINT>* indices)
{
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(VERTEX::objVertex) * mVCount;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &(vertices[0]);
HR(Device->CreateBuffer(&vbd, &vinitData, &pmVB));
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT)* mICount;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &((*indices)[0]);
HR(Device->CreateBuffer(&ibd, &iinitData, &pmIB));
return S_OK;
}
void Object::Draw(ID3D11DeviceContext* Dc, XMFLOAT4X4* View, XMFLOAT4X4* Proj)
{
Dc->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
Dc->IASetInputLayout(InputLayouts::Get_objVertex());
UINT stride = sizeof(VERTEX::objVertex);
UINT offset = 0;
Dc->IASetVertexBuffers(0, 1, &pmVB, &stride, &offset);
Dc->IASetIndexBuffer(pmIB, DXGI_FORMAT_R32_UINT, offset);
XMMATRIX view = XMLoadFloat4x4(View);
XMMATRIX proj = XMLoadFloat4x4(Proj);
XMMATRIX world = XMLoadFloat4x4(&mWorld);
XMMATRIX WorldViewProj = view * proj * world;
Effects::BasicFX->SetWorldViewProj(reinterpret_cast<float*>(&WorldViewProj));
ID3DX11EffectTechnique* tech = Effects::BasicFX->pLoadVertex;
D3DX11_TECHNIQUE_DESC techDesc;
tech->GetDesc(&techDesc);
for (UINT i = 0; i < techDesc.Passes; i++)
{
tech->GetPassByIndex(i)->Apply(0, Dc);
Dc->DrawIndexed(mICount, 0, 0);
}
}
DWORD Object::AddVertex(UINT hash, VERTEX::objVertex* pVertex, VertexCache& cache)
{
auto f = cache.equal_range(hash);
for (auto it = f.first; it != f.second; ++it)
{
auto& tv = vertices[it->second];
if (0 == memcmp(pVertex, &tv, sizeof(VERTEX::objVertex)))
{
return it->second;
}
}
DWORD index = static_cast<UINT>(vertices.size());
vertices.push_back(*pVertex);
VertexCache::value_type entry(hash, index);
cache.insert(entry);
return index;
}
答案 0 :(得分:0)
很难弄清楚代码中到底出了什么问题。您可以尝试采取一些步骤来调试导致问题的部分。 我会做的是:
首先删除所有复杂功能。只需使用默认着色器绘制一个普通三角形。如果您没有看到设置错误或相机没有看到您正在绘制三角形的位置。
如果您看到三角形,请尝试启用着色器。如果三角形消失,那么着色器代码中出现问题。
如果您仍然看到三角形,请尝试加载对象。像边界框一样转储一些关于它的数据(最小值X,Y,Z)。可能是比例关闭,或者原点没有居中。
如果您设法找出问题所在,您可以更新问题并获得更好的答案(或提出其他问题)。