I am trying to draw a 3D Wireframe (just the lines that connect each vertex) Cube and a 10x10 grid with D3D11. So far, this is my code
//************************************************************
//************ INCLUDES & DEFINES ****************************
//************************************************************
#include <iostream>
#include <ctime>
#include "XTime.h"
using namespace std;
#include <d3d11.h>
#include <d3dx11.h>
#include <d3d10.h>
#include <DirectXMath.h>
#include <DirectXColors.h>
#include <DirectXCollision.h>
#include <DirectXPackedVector.h>
#include <D3dx9math.h>
#include "Trivial_VS.csh"
#include "Trivial_PS.csh"
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3d10.lib")
using namespace DirectX::Colors;
using namespace DirectX::Internal;
using namespace DirectX::PackedVector;
using namespace DirectX::TriangleTests;
#define BACKBUFFER_WIDTH 500
#define BACKBUFFER_HEIGHT 500
//************************************************************
//************ SIMPLE WINDOWS APP CLASS **********************
//************************************************************
class DEMO_APP
{
HINSTANCE application;
WNDPROC appWndProc;
HWND window;
ID3D11Device *device = 0;
ID3D11DeviceContext *deviceContext = 0;
ID3D11RenderTargetView *RTV = 0;
IDXGISwapChain *swapChain = 0;
ID3D11View *view = 0;
ID3D11Debug *debugger = 0;
ID3D11Texture2D *swapChainBuffer = 0;
D3D11_VIEWPORT viewport;
ID3D11InputLayout* inputLayout;
XTime timer;
int XDir = 1;
int YDir = 1;
ID3D11Buffer *cubeBuffer;
unsigned int numCubeVertices = 24;
ID3D11Buffer *gridBufferC;
unsigned int numGridVertices = 44;
ID3D11VertexShader *vertexShader;
ID3D11PixelShader *pixelShader;
ID3D11Buffer * constantViewBuffer;
struct SEND_TO_VRAM
{
DirectX::XMVECTORF32 constantColor;
DirectX::XMFLOAT2 constantOffset;
DirectX::XMFLOAT2 padding;
DirectX::XMMATRIX worldMatrix;
DirectX::XMMATRIX viewMatrix;
DirectX::XMMATRIX projectionMatrix;
};
SEND_TO_VRAM toShaderCube;
SEND_TO_VRAM toShaderGridC;
public:
struct SIMPLE_VERTEX
{
DirectX::XMFLOAT2 position2D;
};
struct ROBUST_VERTEX
{
DirectX::XMFLOAT4 position;
};
DEMO_APP(HINSTANCE hinst, WNDPROC proc);
bool Run();
bool ShutDown();
};
//************************************************************
//************ CREATION OF OBJECTS & RESOURCES ***************
//************************************************************
DEMO_APP::DEMO_APP(HINSTANCE hinst, WNDPROC proc)
{
application = hinst;
appWndProc = proc;
WNDCLASSEX wndClass;
ZeroMemory( &wndClass, sizeof( wndClass ) );
wndClass.cbSize = sizeof( WNDCLASSEX );
wndClass.lpfnWndProc = appWndProc;
wndClass.lpszClassName = L"DirectXApplication";
wndClass.hInstance = application;
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndClass.hbrBackground = ( HBRUSH )( COLOR_WINDOWFRAME );
RegisterClassEx( &wndClass );
RECT window_size = { 0, 0, BACKBUFFER_WIDTH, BACKBUFFER_HEIGHT };
AdjustWindowRect(&window_size, WS_OVERLAPPEDWINDOW, false);
window = CreateWindow( L"DirectXApplication", L"CGS Hardware Project", WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME|WS_MAXIMIZEBOX),
CW_USEDEFAULT, CW_USEDEFAULT, window_size.right-window_size.left, window_size.bottom-window_size.top,
NULL, NULL, application, this );
ShowWindow( window, SW_SHOW );
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.Height = BACKBUFFER_HEIGHT;
swapChainDesc.BufferDesc.Width = BACKBUFFER_WIDTH;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = window;
swapChainDesc.SampleDesc.Count = 4;
swapChainDesc.Windowed = true;
UINT flags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT;
if (_DEBUG)
{
flags |= D3D11_CREATE_DEVICE_DEBUG;
}
HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
flags,
NULL,
NULL,
D3D11_SDK_VERSION,
&swapChainDesc,
&swapChain,
&device,
NULL,
&deviceContext);
hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&swapChainBuffer);
hr = device->CreateRenderTargetView(swapChainBuffer, NULL, &RTV);
hr = device->QueryInterface(__uuidof(ID3D11Debug), (void**)&debugger);
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = swapChainDesc.BufferDesc.Width;
viewport.Height = swapChainDesc.BufferDesc.Height;
viewport.MinDepth = 0;
viewport.MaxDepth = 1;
ROBUST_VERTEX cube[24];
//Cube Init
{
for (unsigned int i = 0; i < numCubeVertices; ++i)
{
cube[i].position.w = 1;
}
//TOPLEFT
cube[0].position.x = -0.25f;
cube[0].position.y = 0.25f;
cube[0].position.z = -0.25f;
cube[1].position.x = -0.25f;
cube[1].position.y = 0.25f;
cube[1].position.z = 0.25f;
//TOPBACK
cube[2].position.x = -0.25f;
cube[2].position.y = 0.25f;
cube[2].position.z = 0.25f;
cube[3].position.x = 0.25f;
cube[3].position.y = 0.25f;
cube[3].position.z = 0.25f;
//TOPRIGHT
cube[4].position.x = 0.25f;
cube[4].position.y = 0.25f;
cube[4].position.z = 0.25f;
cube[5].position.x = 0.25f;
cube[5].position.y = 0.25f;
cube[5].position.z = -0.25f;
//TOPFRONT
cube[6].position.x = 0.25f;
cube[6].position.y = 0.25f;
cube[6].position.z = -0.25f;
cube[7].position.x = -0.25f;
cube[7].position.y = 0.25f;
cube[7].position.z = -0.25f;
//BOTTOMLEFT
cube[8].position.x = -0.25f;
cube[8].position.y = -0.25f;
cube[8].position.z = -0.25f;
cube[9].position.x = -0.25f;
cube[9].position.y = -0.25f;
cube[9].position.z = 0.25f;
//BOTTOMBACK
cube[10].position.x = -0.25f;
cube[10].position.y = -0.25f;
cube[10].position.z = 0.25f;
cube[11].position.x = 0.25f;
cube[11].position.y = -0.25f;
cube[11].position.z = 0.25f;
//BOTTOMRIGHT
cube[12].position.x = 0.25f;
cube[12].position.y = -0.25f;
cube[12].position.z = 0.25f;
cube[13].position.x = 0.25f;
cube[13].position.y = -0.25f;
cube[13].position.z = -0.25f;
//BOTTOMFRONT
cube[14].position.x = 0.25f;
cube[14].position.y = -0.25f;
cube[14].position.z = -0.25f;
cube[15].position.x = -0.25f;
cube[15].position.y = -0.25f;
cube[15].position.z = -0.25f;
//CORNER FRONTLEFT
cube[16].position.x = -0.25f;
cube[16].position.y = 0.25f;
cube[16].position.z = -0.25f;
cube[17].position.x = -0.25f;
cube[17].position.y = -0.25f;
cube[17].position.z = -0.25f;
//CORNER BACKLEFT
cube[18].position.x = -0.25f;
cube[18].position.y = 0.25f;
cube[18].position.z = 0.25f;
cube[19].position.x = -0.25f;
cube[19].position.y = -0.25f;
cube[19].position.z = 0.25f;
//CORNER BACKRIGHT
cube[20].position.x = 0.25f;
cube[20].position.y = 0.25f;
cube[20].position.z = 0.25f;
cube[21].position.x = 0.25f;
cube[21].position.y = -0.25f;
cube[21].position.z = 0.25f;
//CORNER FRONTRIGHT
cube[22].position.x = 0.25f;
cube[22].position.y = 0.25f;
cube[22].position.z = -0.25f;
cube[23].position.x = 0.25f;
cube[23].position.y = -0.25f;
cube[23].position.z = -0.25f;
}
ROBUST_VERTEX gridC[44];
//Grid Init
{
for (unsigned int i = 0; i < numGridVertices; ++i)
{
gridC[i].position.y = 0;
gridC[i].position.w = 1;
}
//Borders
{
gridC[0].position.x = -0.5;
gridC[0].position.z = -0.5;
gridC[1].position.x = -0.5;
gridC[1].position.z = 0.5;
gridC[2].position.x = -0.5;
gridC[2].position.z = 0.5;
gridC[3].position.x = 0.5;
gridC[3].position.z = 0.5;
gridC[4].position.x = 0.5;
gridC[4].position.z = 0.5;
gridC[5].position.x = 0.5;
gridC[5].position.z = -0.5;
gridC[6].position.x = 0.5;
gridC[6].position.z = -0.5;
gridC[7].position.x = -0.5;
gridC[7].position.z = -0.5;
}
//CrossSections
{
float counter = -0.4;
for (unsigned int i = 8; i < 26;)
{
gridC[i].position.x = -0.5;
gridC[i].position.z = counter;
++i;
gridC[i].position.x = 0.5;
gridC[i].position.z = counter;
++i;
if (counter >= -0.15 && counter <= -0.05)
{
counter = 0;
}
else
{
counter += 0.1;
}
}
counter = -0.4;
for (unsigned int i = 26; i < 44;)
{
gridC[i].position.z = -0.5;
gridC[i].position.x = counter;
++i;
gridC[i].position.z = 0.5;
gridC[i].position.x = counter;
++i;
if (counter >=-0.15 && counter<=-0.05)
{
counter = 0;
}
else
{
counter += 0.1;
}
}
}
}
D3D11_BUFFER_DESC cubeBufferDesc;
ZeroMemory(&cubeBufferDesc, sizeof(D3D11_BUFFER_DESC));
cubeBufferDesc.Usage = D3D11_USAGE_DEFAULT;
cubeBufferDesc.ByteWidth = sizeof(ROBUST_VERTEX)*numCubeVertices;
cubeBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
cubeBufferDesc.MiscFlags = 0;
cubeBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA subResDataCube;
ZeroMemory(&subResDataCube, sizeof(D3D11_SUBRESOURCE_DATA));
subResDataCube.pSysMem = cube;
subResDataCube.SysMemPitch = 0;
subResDataCube.SysMemSlicePitch = 0;
device->CreateBuffer(&cubeBufferDesc, &subResDataCube, &cubeBuffer);
D3D11_BUFFER_DESC gridBufferDesc;
ZeroMemory(&gridBufferDesc, sizeof(D3D11_BUFFER_DESC));
gridBufferDesc.Usage = D3D11_USAGE_DEFAULT;
gridBufferDesc.ByteWidth = sizeof(ROBUST_VERTEX)*numGridVertices;
gridBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
gridBufferDesc.MiscFlags = 0;
gridBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA subResDataGrid;
ZeroMemory(&subResDataGrid, sizeof(D3D11_SUBRESOURCE_DATA));
subResDataGrid.pSysMem = gridC;
subResDataGrid.SysMemPitch = 0;
subResDataGrid.SysMemSlicePitch = 0;
device->CreateBuffer(&gridBufferDesc, &subResDataGrid, &gridBufferC);
device->CreateVertexShader(Trivial_VS, sizeof(Trivial_VS), NULL, &vertexShader);
device->CreatePixelShader(Trivial_PS, sizeof(Trivial_PS), NULL, &pixelShader);
D3D11_INPUT_ELEMENT_DESC inputElementDesc[] =
{
{"POSITION",0,DXGI_FORMAT_R32G32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0}
};
device->CreateInputLayout(inputElementDesc, 1, &Trivial_VS, sizeof(Trivial_VS), &inputLayout);
D3D11_BUFFER_DESC constantBufferDesc;
ZeroMemory(&constantBufferDesc, sizeof(D3D11_BUFFER_DESC));
constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
constantBufferDesc.ByteWidth = sizeof(SEND_TO_VRAM);
constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
constantBufferDesc.MiscFlags = 0;
constantBufferDesc.StructureByteStride = 0;
device->CreateBuffer(&constantBufferDesc, NULL, &constantViewBuffer);
toShaderCube.constantOffset.x = 0;
toShaderCube.constantOffset.y = 0;
toShaderCube.constantColor = DirectX::Colors::Green;
toShaderCube.worldMatrix = DirectX::XMMatrixIdentity();
toShaderGridC.constantOffset.x = 0;
toShaderGridC.constantOffset.y = 0;
toShaderGridC.constantColor = DirectX::Colors::White;
toShaderGridC.worldMatrix = DirectX::XMMatrixIdentity();
}
//************************************************************
//************ EXECUTION *************************************
//************************************************************
bool DEMO_APP::Run()
{
float Yscale = 1.0f / (tan(DirectX::XMConvertToRadians(0.5*60)));
float aspectRatio = viewport.Width / viewport.Height;
float Xscale = Yscale*aspectRatio;
float zNear = 0.1f;
float zFar = 10.0f;
DirectX::XMMATRIX viewMatrix;
DirectX::XMMATRIX projectionMatrix(Xscale, 0, 0, 0,
0, Yscale, 0, 0,
0, 0, (zFar / (zFar - zNear)), 1,
0, 0, -1.0f*(zFar*zNear) / (zFar - zNear), 0);
projectionMatrix = DirectX::XMMatrixTranspose(projectionMatrix);
toShaderCube.projectionMatrix = projectionMatrix;
toShaderGridC.projectionMatrix = projectionMatrix;
float cameraAngle = DirectX::XMConvertToRadians(18);
viewMatrix = DirectX::XMMatrixRotationX(cameraAngle);
viewMatrix = DirectX::XMMatrixMultiply(DirectX::XMMatrixTranslation(0, 0, -1.5), viewMatrix);
viewMatrix = DirectX::XMMatrixInverse(NULL,viewMatrix);
viewMatrix = DirectX::XMMatrixTranspose(viewMatrix);
toShaderCube.viewMatrix = viewMatrix;
toShaderGridC.viewMatrix = viewMatrix;
//timer.TotalTime() just returns the amount of time since the program started
toShaderCube.worldMatrix = DirectX::XMMatrixIdentity();
toShaderCube.worldMatrix = DirectX::XMMatrixTranslation(0, 0.25, 0);
toShaderCube.worldMatrix = DirectX::XMMatrixMultiply(DirectX::XMMatrixRotationY(DirectX::XMConvertToRadians(timer.TotalTime()*50)),
toShaderCube.worldMatrix);
toShaderCube.worldMatrix = DirectX::XMMatrixTranspose(toShaderCube.worldMatrix);
deviceContext->OMSetRenderTargets(1, &RTV, 0);
deviceContext->RSSetViewports(1, &viewport);
deviceContext->ClearRenderTargetView(RTV, DirectX::Colors::Black);
D3D11_MAPPED_SUBRESOURCE mappedSubRes;
ZeroMemory(&mappedSubRes, sizeof(mappedSubRes));
deviceContext->Map(constantViewBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &mappedSubRes);
memcpy(mappedSubRes.pData, &toShaderGridC, sizeof(SEND_TO_VRAM));
deviceContext->Unmap(constantViewBuffer, NULL);
deviceContext->VSSetConstantBuffers(0, 1, &constantViewBuffer);
UINT stride = sizeof(ROBUST_VERTEX);
UINT offset = 0;
deviceContext->IASetVertexBuffers(0, 1, &gridBufferC, &stride, &offset);
deviceContext->IASetInputLayout(inputLayout);
deviceContext->VSSetShader(vertexShader, 0, 0);
deviceContext->PSSetShader(pixelShader, 0, 0);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
deviceContext->Draw(numGridVertices, 0);
ZeroMemory(&mappedSubRes, sizeof(mappedSubRes));
deviceContext->Map(constantViewBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &mappedSubRes);
memcpy(mappedSubRes.pData, &toShaderCube, sizeof(SEND_TO_VRAM));
deviceContext->Unmap(constantViewBuffer, NULL);
stride = sizeof(ROBUST_VERTEX);
offset = 0;
deviceContext->IASetVertexBuffers(0, 1, &cubeBuffer, &stride, &offset);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
deviceContext->Draw(numCubeVertices, 0);
swapChain->Present(0, 0);
return true;
}
//************************************************************
//************ DESTRUCTION ***********************************
//************************************************************
bool DEMO_APP::ShutDown()
{
deviceContext->ClearState();
deviceContext->Release();
deviceContext = NULL;
swapChain->Release();
swapChain = NULL;
device->Release();
device = NULL;
RTV->Release();
RTV = NULL;
debugger->Release();
debugger = NULL;
swapChainBuffer->Release();
swapChainBuffer = NULL;
inputLayout->Release();
inputLayout = NULL;
cubeBuffer->Release();
cubeBuffer = NULL;
gridBufferC->Release();
gridBufferC = NULL;
vertexShader->Release();
vertexShader = NULL;
pixelShader->Release();
pixelShader = NULL;
constantViewBuffer->Release();
constantViewBuffer = NULL;
//view->Release();
//view = NULL;
UnregisterClass( L"DirectXApplication", application );
return true;
}
//************************************************************
//************ WINDOWS RELATED *******************************
//************************************************************
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow );
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam );
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR, int )
{
srand(unsigned int(time(0)));
DEMO_APP myApp(hInstance,(WNDPROC)WndProc);
MSG msg; ZeroMemory( &msg, sizeof( msg ) );
while ( msg.message != WM_QUIT && myApp.Run() )
{
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
myApp.ShutDown();
return 0;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
if(GetAsyncKeyState(VK_ESCAPE))
message = WM_DESTROY;
switch ( message )
{
case ( WM_DESTROY ): { PostQuitMessage( 0 ); }
break;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}
Here's the Trivial_VS hlsl shader file. The trivial_Ps doesn't do anything currently
struct INPUT_VERTEX
{
float2 coordinate : POSITION;
};
struct OUTPUT_VERTEX
{
float4 colorOut : COLOR;
float4 projectedCoordinate : SV_POSITION;
};
cbuffer THIS_IS_VRAM : register( b0 )
{
float4 constantColor;
float2 constantOffset;
float2 padding;
float4x4 worldMatrix;
float4x4 viewMatrix;
float4x4 projectionMatrix;
};
OUTPUT_VERTEX main( INPUT_VERTEX fromVertexBuffer )
{
OUTPUT_VERTEX sendToRasterizer = (OUTPUT_VERTEX)0;
sendToRasterizer.projectedCoordinate.w = 1;
sendToRasterizer.projectedCoordinate.xy = fromVertexBuffer.coordinate.xy;
sendToRasterizer.projectedCoordinate.xy += constantOffset;
sendToRasterizer.projectedCoordinate = mul(sendToRasterizer.projectedCoordinate, worldMatrix);
sendToRasterizer.projectedCoordinate = mul(sendToRasterizer.projectedCoordinate, viewMatrix);
sendToRasterizer.projectedCoordinate = mul(sendToRasterizer.projectedCoordinate, projectionMatrix);
sendToRasterizer.projectedCoordinate.x /= sendToRasterizer.projectedCoordinate.w;
sendToRasterizer.projectedCoordinate.y /= sendToRasterizer.projectedCoordinate.w;
sendToRasterizer.projectedCoordinate.z /= sendToRasterizer.projectedCoordinate.w;
sendToRasterizer.colorOut = constantColor;
return sendToRasterizer;
}
Right now, the only thing that is being drawn is a green square that rotates the way the cube should and a white line where the grid should be.
Ideally, I'd like to have the 10x10 white grid and the 3D Wireframe cube sitting on top of the grid and rotating. I don't want to fill in any of the faces with a texture and I don't want to have two triangles representing each face with a diagonal cutting through the face. I feel like I'm missing some aspect of working specifically in 3D.
Also, if you know how to debug what the values in the shader are changing to as I multiply them by each matrix, that would definitely be a help as well but really I just want to get my objects drawn.
Thanks for anything you can help out with!