0
votes

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 e.g. 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.

1
At a quick glance, I don't see anything stick out too much. You're checking HRESULTS too. I don't see any shader code, can you provide that? Also, are you developing in Visual Studio? There's a powerful graphics debugger included in all recent versions, including VS 2012. It can show you what the GPU calculated per-drawcall, and per-stage too (vertex shader output, pixel output, etc). It would help shed a lot of light, and personally it's integral to any type of graphics development.cehnehdeh
I'd might try setting the Z of each vertex to 0, not sure if 1 is outside of the clipping range. This depends on what happens in your vertex shader, however.cehnehdeh
Your input layout assumes you are using float4 for the position, but you actually only have float3. Try changing your second input layout element to {"COLOR",0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0} Also, what is your HLSL for the vertex/pixel shader?Chuck Walbourn
@cehnehdeh I tried to set the z to 0 but it stil does not draw anything. by the way I edited the question and added the shader code.jaklh
@ChuckWalbourn thanks for the tip. I changed the second input element. I missunderstod the variable I thought it would be the offset of the second variable, but apperently it is the space between both elements(if i understand it right)jaklh

1 Answers

1
votes

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