Hi all, I'm trying to cut down on some of the spaghetti in my code after running through a few lessons and tutorials. Currently, I have everything grouped in a "Renderer" class and I'm trying to break my larger functions down into more manageable bits.
I have three main functions that are initializing all my d3d and graphics:
void Renderer::InitD3D(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferDesc.Width = SCREEN_WIDTH; // set the back buffer width
scd.BufferDesc.Height = SCREEN_HEIGHT; // set the back buffer height
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE; // windowed/full-screen mode
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // allow full-screen switching
// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
// Set the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = SCREEN_WIDTH;
viewport.Height = SCREEN_HEIGHT;
devcon->RSSetViewports(1, &viewport);
}
void Renderer::InitPipeline(ID3D11Device * dev, ID3D11DeviceContext * devcon)
{
// load and compile the two shaders
ID3D10Blob *VS, *PS;
D3DX11CompileFromFile("Shaders.shader", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, 0, 0);
D3DX11CompileFromFile("Shaders.shader", 0, 0, "PShader", "ps_4_0", 0, 0, 0, &PS, 0, 0);
// encapsulate both shaders into shader objects
dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
// set the shader objects
devcon->VSSetShader(pVS, 0, 0);
devcon->PSSetShader(pPS, 0, 0);
// create the input layout object
createInputLayout(dev, devcon, VS);
}
void Renderer::InitGraphics(std::vector<Renderable_Object*> Game_Objects)
{
for (int i = 0; i < Game_Objects.size(); i++)
{
for (int j = 0; j < Game_Objects[i]->getVertices().size(); j++)
{
OurVertices.push_back(Game_Objects[i]->getVertices()[j]);
}
}
createVertexBuffer(dev);
createInstanceBuffer(dev);
createProjectionBuffer(dev);
createWorldBuffer(dev);
}
I have InitD3D, which creates my device, swapchain, and device context. This seems to make sense to me, its all of the "background" work. The comes InitPipeline, this function in my mind, should be in charge of preparing the pathway in which we will shove data into our shaders for rendering. Then, I have my InitGraphics, which really all I want it to do is setup the data to be shoved down previously mentioned pipeline, right now in my mind i think it is doing more than that. Am I right in thinking creating buffers is part of the pipeline setup, and then after the setup is done, updating those buffers is part of the graphics initiation I am thinking of.
Again, three Phases:
Initialize D3D window and device and crap -> initialize pipeline and way of sending data to it -> push data onto the pipeline for initial rendering
One more side question: do I need to use the same subresource that I used to initialize a buffer when I go to update it with map/unmap? Or do I set a new subresource_data? I'm starting to think I need the original subresource_data, or at least a pointer to it, because when I call CreateBuffer I pass it a reference to a subresource_data object...
Sorry all, I tend to ask before I invetigate, given that this code here works just fine for me, it would suggest that I do not need the original subresource, all I need is the data I'm going to update with.
if (createVertexBuffer(dev))
{
// copy the vertices into the buffer
D3D11_MAPPED_SUBRESOURCE ms;
devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, OurVertices.data(), sizeof(Vertex) * OurVertices.size()); // copy the data
devcon->Unmap(pVBuffer, NULL); // unmap the buffer
}
So, this means I can successfully separate my buffer creation, from my buffer initialization. I can create my buffers as the cars that will carry crap down the pipeline, in the init pipeline funciton, then I can put people in said cars in the initgraphics function.