I am totally noob to 3D drawing using DirectX so, I wanted to learn the very basics of it and so, I attempted to use a mix of every example I stumbled upon through the web.
My first objective is to simply draw a few lines on the screen but so far, the only thing I was able to realize is to clear the screen with some varying color...
In order to draw my 2D lines, I actually use HLSL vertex and pixel shaders compiled directly by the 2015 version of Visual Studio into cso files. (I initially had trouble with the pixel shader but managed to find that its properties have to be set )
When I use the Visual Studio Graphics Analyzer/Debugger, I can see the IA step which seems to be correct as the lines are drawn. But after this step, I can't see anything more although I can debug step by step in the vertex shader and I see the correct values in position and color parameters.
The main issues, here, are:
- In pixel history, I can't see any Draw() call issued on the deviceContext. I can only see ClearRenderTarget()
- The pixel shader displays the message "Stage did not run. No ouput"
I don't know what is wrong in the process, are the world/view/projection matrices or the depthStencilView mandatory? Did I forgot to provide a specific buffer to the swapChain and pipeline? I tried to disable depth, scissor, and culling in the rasterState object but I can't be sure.
I use a structure for my vertices which is :
#define LINES_NB 1000
struct Point
{
float x, y, z, rhw;
float r, g, b, a;
} lineList[LINES_NB];
Finally, here is the code for the VERTEX SHADER:
struct VIn
{
float4 position : POSITION;
float4 color : COLOR;
};
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VOut main(VIn input)
{
VOut output;
output.position = input.position;
output.color = input.color;
return output;
}
Which I compile with the following line :
/Zi /E"main" /Od /Fo"E:\PATH\VertexShader.cso" /vs"_5_0" /nologo
And the code for the PIXEL SHADER is the following:
struct PIn
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
float4 main(PIn input) : SV_TARGET
{
return input.color;
}
Which I compile with the following line:
/Zi /E"main" /Od /Fo"E:\PATH\PixelShader.cso" /ps"_5_0" /nologo
This is the RASTERIZER STATE creation part:
D3D11_RASTERIZER_DESC rasterDesc;
rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_NONE;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = false;
rasterDesc.FillMode = D3D11_FILL_WIREFRAME;
rasterDesc.FrontCounterClockwise = true;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;
result = _device->CreateRasterizerState(&rasterDesc, &_rasterState);
if (FAILED(result))
{
OutputDebugString("FAILED TO CREATE RASTERIZER STATE.\n");
HR(result);
return -1;
}
_immediateContext->RSSetState(_rasterState);
And this is the INPUT LAYOUT registration part (_vertexShaderCode->code contains the contents of vertexShader.cso and _vertexShaderCode->size, the size of those contents):
// create the input layout object
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
HR(_device->CreateInputLayout(ied, sizeof(ied) / sizeof(D3D11_INPUT_ELEMENT_DESC), _vertexShaderCode->code, _vertexShaderCode->size, &_vertexInputLayout));
_immediateContext->IASetInputLayout(_vertexInputLayout);
Where variables are declared as:
struct Shader
{
BYTE *code;
UINT size;
};
ID3D11Device* _device;
ID3D11DeviceContext* _immediateContext;
ID3D11RasterizerState* _rasterState;
ID3D11InputLayout* _vertexInputLayout;
Shader* _vertexShaderCode;
Shader* _pixelShaderCode;
My VERTEX BUFFER is created by calling createLinesBuffer once, and then, calling renderVertice for mapping it at every drawcall:
void DxDraw::createLinesBuffer(ID3D11Device* device)
{
D3D11_BUFFER_DESC vertexBufferDesc;
ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vertexBufferDesc.ByteWidth = sizeof(Point) * LINES_NB;
std::cout << "buffer size : " << sizeof(Point) * LINES_NB << std::endl;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vertexBufferData;
ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
vertexBufferData.pSysMem = lineList;
std::cout << "lineList : " << lineList << std::endl;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
HR(device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &_vertexBuffer));
}
void DxDraw::renderVertice(ID3D11DeviceContext* ctx, UINT count, D3D11_PRIMITIVE_TOPOLOGY type)
{
D3D11_MAPPED_SUBRESOURCE ms;
ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE));
// map the buffer
HR(ctx->Map(_vertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms));
// copy the data to it
memcpy(ms.pData, lineList, sizeof(lineList));
// unmap it
ctx->Unmap(_vertexBuffer, NULL);
// select which vertex buffer to display
UINT stride = sizeof(Point);
UINT offset = 0;
ctx->IASetVertexBuffers(0, 1, &_vertexBuffer, &stride, &offset);
// select which primtive type we are using
ctx->IASetPrimitiveTopology(type);
// draw the vertex buffer to the back buffer
ctx->Draw(count, 0);
}