Advertisement Jump to content
Sign in to follow this  
XNobodyX

Basic Rendering

This topic is 1827 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have found a couple tutorials on how to use DirectX11 and I have gotten a working example that renders one triangle. However when I try and enter 3 more points in to render(6 in total) it only shows the first triangle. I set the topology(using IASetPrimitiveTopology) to D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST which to the best of my understanding should draw a new triangle every 3 points.


How do I render more than one object/set of points?
Am I missing something critical about the way the rendering process works in DirectX?


Here is the code:

//********** Setup **********//
//Compile Vertex Shader
HR(D3DCompileFromFile(	
    shaderPath,	
    nullptr,	
    nullptr,	
    "VShader",	
    "vs_5_0",	
    shaderFlags,	
    0,	
    &VS,	
    nullptr	));

//Compile Pixel Shader
HR(D3DCompileFromFile(	
    shaderPath,	
    nullptr,	
    nullptr,	
    "PShader",	
    "ps_5_0",	
    shaderFlags,	
    0,	
    &PS,	
    nullptr	));	

//Encapsulate both shaders in shader objects
HR(m_pDevice->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS));
m_pDevice->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

//Set the shader objects
m_pImmediateContext->VSSetShader(pVS, 0, 0);
m_pImmediateContext->PSSetShader(pPS, 0, 0);

//For playing around
VERTEX OurVertices[] ={	
    { 0.0f, 0.5f, 0.0f, { 0.0f, 1.0f, 0.0f, 1.0f } },	
    { 0.45f, -0.5, 0.0f, { 0.0f, 1.0f, 1.0f, 0.0f } },	
    { -0.45f, -0.5f, 0.0f, { 0.0f, 0.0f, 1.0f, 1.0f } },	
    { 0.0f, 0.5f, 0.0f, { 0.0f, 1.0f, 0.0f, 1.0f } },	
    { 0.45f, -0.5, 0.0f, { 0.0f, 1.0f, 1.0f, 0.0f } },	
    { -0.45f, -0.5f, 0.0f, { 0.0f, 0.0f, 1.0f, 1.0f } }
};

//Vertex buffer description
ZeroMemory(&bd, sizeof(bd));//Reserve memory for Vertex buffer description
bd.Usage = D3D11_USAGE_DYNAMIC;//Write access, access by CPU and GPU
bd.ByteWidth = sizeof(VERTEX) * 3;//Size of vertex struct * 3(x3 b/c x,y,z)
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;//Use as a vertex buffer
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;//Allow CPU to write buffer
m_pDevice->CreateBuffer(&bd, NULL, &pVBuffer);//Create vertex buffer

//Working with vertex buffer
m_pImmediateContext->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);//Map the buffer, pVBuffer is the buffer and ms is where we will put the buffer
memcpy(ms.pData, OurVertices, sizeof(OurVertices));//Copy data to mapped buffer
m_pImmediateContext->Unmap(pVBuffer, NULL);//Unmap buffer, allowing GPU to use buffer	

D3D11_INPUT_ELEMENT_DESC ied[] =//Describe to CPU how data is stored	
{
	{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};

m_pDevice->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
m_pImmediateContext->IASetInputLayout(pLayout);//Set layout, aply

//********************//

//********** Actual rendering **********//
m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, DirectX::Colors::CornflowerBlue);//Clear background to blue
    stride = sizeof(VERTEX);//Size of VERTEX
    offset = 0;//Offset in which we start reading VERTEX bytes
    m_pImmediateContext->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);//Tells GPU which vertices to read
    m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);//Tells the GPU what type of geomitry to render(Points, Line segments, line, triangle, triangle strip).
    m_pImmediateContext->Draw(3, 0);//Draw 3 vertices  and start at vertice 0
HR(m_pSwapChain->Present(0, 0));//Display background(From buffer)
//********************//

EDIT:
I figured out that I need to run lines 57-59 which copy the vertexes to GPU memory and then run lines 79-81 which do the actual rendering for each object I want to render. For some reason I can't put for than 3 vertexes in OurVertices and to render another triangle you have to create a new array of vertexes and run the lines mentioned above.

Questions that remain:
Why can't I put more than 3 vertexes in OurVertices? Isn't the D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST setting supposed to let me do that? This is very critical because without this functioning how I think it should I can only draw 2d triangles.

Edited by XNobodyX

Share this post


Link to post
Share on other sites
Advertisement

Looks like the formatting got screwed up on your code but from what I can see your doing:

m_pImmediateContext->Draw(3, 0)

Which only draws the first 3 vertices. It should be:

m_pImmediateContext->Draw(6, 0)

Share this post


Link to post
Share on other sites

Looks like the formatting got screwed up on your code but from what I can see your doing:

 

I fixed that, seems like after the first edit it lost all carriage returns.

 

When I change it to 6 I get a DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL warning in the output window and it only shows 3. with this code 

//Actual rendering
m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, DirectX::Colors::CornflowerBlue);//Clear background to blue
	stride = sizeof(VERTEX);//Size of VERTEX
	offset = 0;//Offset in which we start reading VERTEX bytes

	VERTEX OurVertices[] =
	{
		{ 0.0f, 0.5f, 0.0f, { 0.0f, 1.0f, 0.0f, 1.0f } },
		{ 0.45f, -0.5, 0.0f, { 0.0f, 1.0f, 1.0f, 0.0f } },
		{ -0.45f, -0.5f, 0.0f, { 0.0f, 0.0f, 1.0f, 1.0f } },
		{ -0.5f, 0.5f, 0.0f, { 0.0f, 1.0f, 0.0f, 1.0f } },
		{ -0.1f, -0.5, 0.0f, { 0.0f, 1.0f, 1.0f, 0.0f } },
		{ -1.0f, -0.5f, 0.0f, { 0.0f, 0.0f, 1.0f, 1.0f } }
	};

	m_pImmediateContext->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);//Map the buffer, pVBuffer is the buffer and ms is where we will put the buffer
	memcpy(ms.pData, OurVertices, sizeof(OurVertices));//Copy data to mapped buffer
	m_pImmediateContext->Unmap(pVBuffer, NULL);//Unmap buffer, allowing GPU to use buffer

	m_pImmediateContext->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);//Tells GPU which vertices to read
	m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);//Tells the GPU what type of geomitry to render(Points, Line segments, line, triangle, triangle strip).
	m_pImmediateContext->Draw(6, 0);//Draw 3 vertices  and start at vertice 0
HR(m_pSwapChain->Present(0, 0));//Display background(From buffer)

I had tried doing that before because this is what logically makes sense, but it didn't work. But when I changed LN47, bd.ByteWidth = sizeof(VERTEX) * 3;//Size of vertex struct * 3(x3 b/c x,y,z) to times 6 it works out fine. If you could explain this whole process to me that would be cool.

Edited by XNobodyX

Share this post


Link to post
Share on other sites

ByteWidth is the whole size of your vertexbuffer. So you have 6 vertices defined in your OurVertices-array then you also have to allocate the vertexbuffer for same amount of space.

For explanation (simple):

Just imagine the OurVertices-array is a data-container on CPU-side. This can't directly be accessed by the GPU. To transfer the content you have to create a data-container on GPU-side and this is the vertexbuffer. The data is transfered through Map->memcpy->Unmap. Map opens a "pointer" to the allocated vertexbuffer and you can copy the data. Unmap closes the "pointer" and the gpu now knows it can access the containing data for rendering. The transfer is an expensive process and you should do it as few as possible. So for static geometry just once when creating the vertexbuffer and not on every frame. Dynamic buffers like particles should be updated when needed. You can also just update a part of the buffer. You can also delete the buffer on CPU-side, the vertexbuffer will still contain all data until it will be released.

Share this post


Link to post
Share on other sites

As said above you have:

 

  1. bd.ByteWidth = sizeof(VERTEX) * 3;

 

Which sets the size of the whole vertex buffer, with this you are only able to store a maximum of 3 vertices. The error you are getting now is literally as it says, the buffer is too small to accommodate 6 vertices.

Edited by Six222

Share this post


Link to post
Share on other sites

As said above you have:

 

  1. bd.ByteWidth = sizeof(VERTEX) * 3;

 

Which sets the size of the whole vertex buffer, with this you are only able to store a maximum of 3 vertices. The error you are getting now is literally as it says, the buffer is too small to accommodate 6 vertices.

How would I deal with a bunch of object(A bunch of diferent arrays)?

Share this post


Link to post
Share on other sites

Create the same amount of vertexbuffers, one for each object. The vertex-struct for each object can be different but you have to draw all objects with a single draw-call.

 

Alternative: One big vertexbuffer, copy all objects into this (one after another in memorylayout like an array). But the vertex-struct has to be the same for all objects. Advantage is, you can draw all objects with one single draw-call if you use the trianglelist-topology. If not do a drawcall for every object but with different starting indices obvioulsly.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!