DirectX不绘制任何内容

DirectX does not draw anything

本文关键字:任何内 绘制 DirectX      更新时间:2023-10-16

你好,我最近试着学习DirectX 11,但我的程序什么都画不出来
我唯一得到的是我选择的背景颜色的窗口
我把我的程序分成了一个库(引擎)和一个常规项目
该库包含一个模型类、着色器类和一个Directx init函数。

S3DData只是一个包含所有相关类的结构,例如交换链等

static bool initDX(logfile* errorlog, S3DData *data){
D3D_FEATURE_LEVEL featureLevels[] = {
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0
};
UINT numFeatureLevels = 3;
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
HRESULT result = ERROR_SUCCESS;
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
//swapchain and device
bufferDesc.Height = data->WindowHeight;
bufferDesc.Width = data->WindowWidth;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.OutputWindow = data->Handle;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Windowed = data->Windowed;
swapChainDesc.BufferCount = 1;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.SampleDesc.Count = 1;
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
D3D11_SDK_VERSION, &swapChainDesc, &data->SwapChain, &data->Device, NULL,  &data->DeviceContext);
if(FAILED(result)){
std::string error;
errorlog->write("failed to create swapchain or device:");
if(result == E_INVALIDARG)
error = "invalid argument";
else if(result == E_OUTOFMEMORY)
error = " no memory";
else if(result == DXGI_ERROR_MORE_DATA)
error = " more data needed for buffer";
else if(result == E_NOTIMPL)
error = " not implemented";
else if(result == DXGI_ERROR_INVALID_CALL)
error = " invalid call";
else
error = std::to_string((unsigned int)result);
errorlog->write(error);
return false;
}
//back buffer and rendertargetview
ID3D11Texture2D *backbuffer;
result = data->SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backbuffer);
if(FAILED(result)){
errorlog->write("failed to get backbuffer");
return false;
}

result = data->Device->CreateRenderTargetView(backbuffer, NULL, &data->RenderTargetView);
if(FAILED(result)){
errorlog->write("failed to create render target view");
return false;
}
data->DeviceContext->OMSetRenderTargets(1, &data->RenderTargetView, nullptr);
backbuffer->Release();
ZeroMemory(&data->viewport, sizeof(D3D11_VIEWPORT));
data->viewport.Height = data->WindowHeight;
data->viewport.Width = data->WindowWidth;
data->viewport.TopLeftX = 0;
data->viewport.TopLeftY = 0;
data->DeviceContext->RSSetViewports(1, &data->viewport);
errorlog->write("directx success");
return true;

该函数基本上创建:设备、交换链和设备上下文
并设置:渲染目标和视口

第二个函数是着色器初始化函数:

bool shader::init(std::string vsFile, std::string psFile, S3DData * data){
std::ofstream output;
output.open("shaderErrorLog.txt", std::ios::binary);
_S3DData = data;
_pixelShader =  nullptr;
_vertexShader = nullptr;
_layout = nullptr;
HRESULT result;
ID3D10Blob *errorMsg, *pixelShader, *vertexShader;;
unsigned int numElements;
errorMsg = 0;
pixelShader = 0;
vertexShader = 0;
result = D3DX11CompileFromFile(vsFile.c_str(), 0, 0, "VS", "vs_5_0", 0, 0, 0, &vertexShader, &errorMsg, 0);
if(FAILED(result)){
if(errorMsg != nullptr){
char *compilerErrors = (char*)errorMsg->GetBufferPointer();
unsigned int size = errorMsg->GetBufferSize();
output.write(compilerErrors, size);
}
else
{
std::string error ="failed to find file";
output.write(error.c_str(), error.size());
}
return false;
}

result = D3DX11CompileFromFile(psFile.c_str(), 0, 0, "PS", "ps_5_0", 0, 0, 0, &pixelShader, &errorMsg, 0);
if(FAILED(result)){
if(errorMsg){
char *compilerErrors = (char*)errorMsg->GetBufferPointer();
unsigned int size = errorMsg->GetBufferSize();
output.write(compilerErrors, size);
}
else
{
std::string noFileMsg = "file " +psFile +"not found";
output.write(noFileMsg.c_str(), noFileMsg.size());
}
return false;
}
result = _S3DData->Device->CreateVertexShader(vertexShader->GetBufferPointer(), vertexShader->GetBufferSize(), nullptr, &_vertexShader);
if(FAILED(result)){
return false;
}
result = _S3DData->Device->CreatePixelShader(pixelShader->GetBufferPointer(), pixelShader->GetBufferSize(), nullptr, &_pixelShader);
if(FAILED(result)){
return false;
}
//layout of vertex
//in case of color.fx position and color
D3D11_INPUT_ELEMENT_DESC layout[] ={
{"POSITION",0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
//get num of elements
numElements = 2;

result = _S3DData->Device->CreateInputLayout(layout, numElements, vertexShader->GetBufferPointer(), vertexShader->GetBufferSize(), &_layout);
if(FAILED(result))
return false;
vertexShader->Release();
vertexShader = 0;
pixelShader->Release();
pixelShader = 0;
std::string success = "shader init : success";
output.write(success.c_str() , success.size());
_S3DData->DeviceContext->IASetInputLayout(_layout);
_S3DData->DeviceContext->VSSetShader(_vertexShader, 0, 0);
_S3DData->DeviceContext->PSSetShader(_pixelShader, 0, 0);
return true;

这些是着色器类的成员:

ID3D11VertexShader *_vertexShader;
ID3D11PixelShader *_pixelShader;
ID3D11InputLayout *_layout;
S3DData *_S3DData;

该函数创建着色器,由于我现在只有一个着色器,
它设置着色器和输入布局。

最后一个函数是模型初始化函数:

bool model::init(S3DData *data){
_S3DData = data;
HRESULT result;
vertex *vertexBuffer;
unsigned long* indexBuffer;
D3D11_BUFFER_DESC indexDesc, vertexDesc;
D3D11_SUBRESOURCE_DATA indexData, vertexData;
//create buffers
_vertexCount = 3;
_indexCount = 3;
vertexBuffer = new vertex[_vertexCount];
if(!vertexBuffer)return false;
indexBuffer = new unsigned long[_indexCount];
if(!indexBuffer)return false;
//fill buffers
vertexBuffer[0] = vertex( 0.0f, 1.0f, 1.0f);
vertexBuffer[0] = vertex( 1.0f, -1.0f, 1.0f);
vertexBuffer[0] = vertex( -1.0f, -1.0f, 1.0f);
indexBuffer[0] = 0;
indexBuffer[1] = 1;
indexBuffer[2] = 2;
//bufferDesc
vertexDesc.Usage = D3D11_USAGE_DEFAULT;
vertexDesc.ByteWidth = sizeof(vertex) * _vertexCount;
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexDesc.CPUAccessFlags = 0;
vertexDesc.MiscFlags = 0;
vertexDesc.StructureByteStride = 0;
//set subressource data
vertexData.pSysMem = vertexBuffer;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;
result = _S3DData->Device->CreateBuffer(&vertexDesc, &vertexData, &_vertex);
if(FAILED(result))return false;
indexDesc.ByteWidth = sizeof(unsigned long) * _indexCount;
indexDesc.Usage = D3D11_USAGE_DEFAULT;
indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexDesc.MiscFlags = 0;
indexDesc.CPUAccessFlags = 0;
indexDesc.StructureByteStride = 0;
//set subressource
indexData.pSysMem = indexBuffer;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
result = _S3DData->Device->CreateBuffer(&indexDesc, &indexData, &_index);
if(FAILED(result))return false;
delete []indexBuffer;
indexBuffer = nullptr;
delete []vertexBuffer;
vertexBuffer = nullptr;

顶点结构:

struct vertex{
XMFLOAT3 pos;
vertex(){}
vertex(float x, float y, float z):pos(x, y, z){
}

所以这个函数只创建缓冲区

在渲染函数中,设置了剩余的变量:

void model::render(shader *Shader){
unsigned int stride = sizeof(vertex);
unsigned int offset = 0;
_S3DData->DeviceContext->IASetVertexBuffers(0, 1, &_vertex, &stride, &offset);
_S3DData->DeviceContext->IASetIndexBuffer(_index, DXGI_FORMAT_R32_UINT, 0);
//set form of vertex: triangles
_S3DData->DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_S3DData->DeviceContext->DrawIndexed(_indexCount, 0, 0);

}

编辑:这些是您请求的着色器代码
顶点着色器:

struct VSout{
float4 position :SV_POSITION;
};

VSout VS(float4 position:POSITION){
VSout output;
output.position = position;
return output;
}

像素着色器:

float4 PS() :SV_TARGET{
float4 newColor = float4(1.0f, 1.0f, 0.0f, 1.0f);
return newColor;
}

这是调试器的屏幕截图,你有所有的draw调用等等。在中间你可以看到顶点缓冲区调试器

谢谢你事先的帮助。

查看您发布的调试器图像,第2个和第3个顶点都是0。这意味着您没有正确填充顶点缓冲区。

查看您的代码,当您填充顶点缓冲区时,您只在0索引中设置它。所以你的代码看起来像这样:

vertexBuffer[0] = vertex( 0.0f, 1.0f, 1.0f);
vertexBuffer[0] = vertex( 1.0f, -1.0f, 1.0f);
vertexBuffer[0] = vertex( -1.0f, -1.0f, 1.0f);

它应该是这样的:

vertexBuffer[0] = vertex( 0.0f, 1.0f, 1.0f);
vertexBuffer[1] = vertex( 1.0f, -1.0f, 1.0f);
vertexBuffer[2] = vertex( -1.0f, -1.0f, 1.0f);