简体   繁体   中英

DirectX does not draw anything

Hello I recently tried to learn DirectX 11 but my program does not draw anything.
The only thing I get is the window with the background color i have chosen
I have divided my program into a library(engine) and a regular project.
The library contains a model class, shader class and a Directx init function.

the S3DData is just a struct containing all relevant classes eg swap chain etc.

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;

the function basically creates: the device, swapchain and devicecontext.
and sets: the render target and the viewport

the second funtion is the shader init function:

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;

and these are the members of the shader class:

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

this function creates the shaders and since i only have 1 shader for now,
it sets the shaders and the input layout.

the last function is the model init function:

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;

the vertex struct:

struct vertex{
XMFLOAT3 pos;

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

so this function only creates the buffers

in the render function the remaining variable are set:

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);

}

EDIT: these are the shader codes you requested
Vertex Shader:

    struct VSout{
    float4 position :SV_POSITION;
};


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

Pixel Shader:

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

this here is a screenshot of the debuger left you have all the draw calls etc. And in the middle you can see the vertex buffer debuger

thanks for your help in advance.

Looking at the debugger image you posted, the 2nd and 3rd vertices are all 0. This means you didn't fill your vertex buffer properly.

Looking at your code, when you fill your vertex buffer, you're only setting it in the 0 index. So you code looks like this:

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);

And it should look like this:

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM