I am currently developing a Direct3D application where I'm facing a challenge in displaying a cube on the screen. Despite checking various aspects, the cube fails to appear. Here's what I've verified so far:
Defined and created buffers for both vertices and indices of the cube. Compiled shaders (VShader and PShader) without encountering any errors. Ensured correct setup of the viewport and render target view. Called the Present() function to render the frame on the screen. However, despite these efforts, the cube remains invisible when running the application.
I appreciate any insights or assistance you can provide on resolving this issue. Thank you for your attention!
Main.cpp
#include "ExtroEngine.h"
#include <Windows.h>
using namespace ExtroEngine;
ID3D11Device* gp_Device;
ID3D11DeviceContext* gp_DeviceContext;
IDXGIDevice* gp_DXGI_Device;
IDXGIAdapter* gp_DXGI_Adapter;
IDXGIFactory* gp_DXGI_Factory;
IDXGISwapChain* gp_DXGI_SwapChain;
ID3D11VertexShader* gp_VS;
ID3D11PixelShader* gp_PS;
ID3D11InputLayout* gp_InputLayout;
ID3D11Buffer* gp_VBuffer;
ID3D11RenderTargetView* gp_BackBuffer;
void InitD3D(HWND hwnd,RECT wr);
void InitPipeline();
void InitGraphics();
void Render();
void CleanD3D();
Vertex Triangle[] = {
{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
{ XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
{ XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
{ XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
// Back face
{ XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
{ XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
{ XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
{ XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) }
};
WORD CubeIndices[] = {
// Front face
0, 1, 2,
0, 2, 3,
// Back face
4, 5, 6,
4, 6, 7,
// Left face
4, 7, 1,
4, 1, 0,
// Right face
3, 2, 6,
3, 6, 5,
// Top face
1, 7, 6,
1, 6, 2,
// Bottom face
4, 0, 3,
4, 3, 5
};
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
WNDCLASSEXW Wnd = {};
Wnd.cbSize = sizeof(WNDCLASSEXW);
Wnd.cbClsExtra = 0;
Wnd.hInstance = hInstance;
Wnd.lpszClassName = L"Scene";
Wnd.lpfnWndProc = WinProc;
Wnd.style = CS_HREDRAW | CS_VREDRAW;
Wnd.hCursor = LoadCursorW(hInstance, IDC_ARROW);
RegisterClassExW(&Wnd);
RECT wr = { 0, 0, SCENE_WIDTH, SCENE_HEIGHT };
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
hwnd = CreateWindowExW(NULL, L"Scene", L"Scene", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
InitD3D(hwnd, wr);
MSG msg = { 0 };
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
Render();
}
CleanD3D();
return 0;
}
//-------------------KHỞI TẠO DIRECTX 3D-------------------//
void InitD3D(HWND hwnd, RECT wr)
{
HRESULT hr = 0;
GetClientRect(hwnd, &wr);
D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_10_1 };
D3D_DRIVER_TYPE DriveType[] = {D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE};
DXGI_SWAP_CHAIN_DESC swpDesc;
ZeroMemory(&swpDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swpDesc.BufferCount = 1;
swpDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swpDesc.BufferDesc.Width = SCENE_WIDTH_MAX_HD;
swpDesc.BufferDesc.Height = SCENE_HEIGHT_MAX_HD;
swpDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swpDesc.OutputWindow = hwnd;
swpDesc.SampleDesc.Count = 1;
swpDesc.SampleDesc.Quality = 0;
swpDesc.Windowed = TRUE;
for (auto DeviceSelect : DriveType)
{
hr = D3D11CreateDeviceAndSwapChain(NULL, DeviceSelect, NULL, NULL, NULL, NULL,
D3D11_SDK_VERSION, &swpDesc, &gp_DXGI_SwapChain, &gp_Device, featureLevels, &gp_DeviceContext);
if (SUCCEEDED(hr))
{
break;
}
}
if (FAILED(hr)){
MessageBox(NULL, L"Error Create Device And Swap Chain", L"Error", MB_OK);
CleanD3D();
return;
}
ID3D11Texture2D* pBackBuffer;
gp_DXGI_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
gp_Device->CreateRenderTargetView(pBackBuffer, NULL, &gp_BackBuffer);
pBackBuffer->Release();
gp_DeviceContext->OMSetRenderTargets(1, &gp_BackBuffer, NULL);
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = SCENE_WIDTH_MAX_HD;
viewport.Height = SCENE_HEIGHT_MAX_HD;
gp_DeviceContext->RSSetViewports(1, &viewport);
InitPipeline();
InitGraphics();
}
void InitPipeline()
{
HRESULT hr;
ID3DBlob* VS, * PS;
hr = D3DCompileFromFile(L"Material.hlsl", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
"VShader", "vs_5_0", 0, 0, &VS, NULL);
if (FAILED(hr)){
MessageBox(NULL, L"Compile From File {Material.hlsl} Error With {VShader}",
L"Error", MB_OK);
CleanD3D();
return;
}
hr = D3DCompileFromFile(L"Material.hlsl", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
"PShader", "ps_5_0", 0, 0, &PS, NULL);
if (FAILED(hr)) {
MessageBox(NULL, L"Compile From File {Material.hlsl} Error With {PShader}",
L"Error", MB_OK);
CleanD3D();
return;
}
hr = gp_Device->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &gp_VS);
if (FAILED(hr)) {
MessageBox(NULL, L"Create Vertex Shader Error With {VS}",
L"Error", MB_OK);
CleanD3D();
return;
}
hr = gp_Device->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &gp_PS);
if (FAILED(hr)) {
MessageBox(NULL, L"Create Pixel Shader Error With {PS}",
L"Error", MB_OK);
CleanD3D();
return;
}
gp_DeviceContext->VSSetShader(gp_VS, NULL, 0);
gp_DeviceContext->PSSetShader(gp_PS, NULL, 0);
D3D11_INPUT_ELEMENT_DESC InputShader[] =
{
{"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0},
{"COLOR",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0}
};
gp_Device->CreateInputLayout(InputShader, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &gp_InputLayout);
gp_DeviceContext->IASetInputLayout(gp_InputLayout);
}
void InitGraphics()
{
HRESULT hr;
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(Vertex) * ARRAYSIZE(Triangle);
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory(&InitData, sizeof(InitData));
InitData.pSysMem = Triangle;
hr = gp_Device->CreateBuffer(&bd, &InitData, &gp_VBuffer);
if (!SUCCEEDED(hr)){
MessageBox(NULL, L"Create Buffer Error",
L"Error", MB_OK);
CleanD3D();
return;
}
D3D11_MAPPED_SUBRESOURCE map;
gp_DeviceContext->Map(gp_VBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &map);
memcpy(map.pData, Triangle, sizeof(Triangle));
gp_DeviceContext->Unmap(gp_VBuffer, NULL);
}
//-------------------VẼ CỬA SỔ-------------------//
void Render()
{
float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
gp_DeviceContext->ClearRenderTargetView(gp_BackBuffer, clearColor);
UINT stride = sizeof(Vertex);
UINT offset = 0;
gp_DeviceContext->IASetVertexBuffers(0, 1, &gp_VBuffer, &stride, &offset);
gp_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
gp_DeviceContext->DrawIndexed(ARRAYSIZE(CubeIndices), 0, 0);
gp_DXGI_SwapChain->Present(0, 0);
}
//-------------------GIẢI PHÓNG BỘ NHỚ DIRECTX 3D-------------------//
void CleanD3D()
{
SafeRelease(gp_Device);
SafeRelease(gp_DeviceContext);
SafeRelease(gp_DXGI_Device);
SafeRelease(gp_DXGI_Adapter);
SafeRelease(gp_DXGI_Factory);
SafeRelease(gp_DXGI_SwapChain);
SafeRelease(gp_VS);
SafeRelease(gp_PS);
SafeRelease(gp_InputLayout);
SafeRelease(gp_BackBuffer);
}
//-------------------GỌI CỬA SỔ-------------------//
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
Render();
ValidateRect(hwnd, NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
ExtroEngine.h
#pragma once
#include <d3d11.h>
#include <directxmath.h>
#include <dxgi1_2.h>
#include <d3dcompiler.h>
#define SCENE_HEIGHT 600
#define SCENE_HEIGHT_MAX_HD 3300
#define SCENE_WIDTH_MAX_HD 2240
#define SCENE_WIDTH 600
using namespace DirectX;
namespace ExtroEngine
{
#pragma region Sharder
struct Vertex
{
XMFLOAT3 Position;
XMFLOAT4 Color;
};
#pragma endregion
#pragma region Utility
//Giúp giải phóng tài nguyên an toàn hơn
template<typename T>
inline void SafeRelease(T& ptr)
{
if (ptr != NULL)
{
ptr->Release();
ptr = NULL;
}
}
#pragma endregion
}
and Material.hlsl
cbuffer cbPerObject
{
float4x4 WVP;
};
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
VOut output;
output.position = position;
output.color = color;
return output;
}
float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}
I want to understand why I am getting this error and the cause
You're missing quite a number of things for the cube to display:
So for example you can add this to your code:
ID3D11Buffer* gp_IBuffer;
ID3D11RasterizerState* gp_rs;
// this goes in InitGraphics/Pipeline
// create an Index Buffer
D3D11_BUFFER_DESC ib{}
ib.Usage = D3D11_USAGE_IMMUTABLE;
ib.ByteWidth = sizeof(WORD) * ARRAYSIZE(CubeIndices);
ib.BindFlags = D3D11_BIND_INDEX_BUFFER;
D3D11_SUBRESOURCE_DATA data{};
data.pSysMem = CubeIndices;
gp_Device->CreateBuffer(&ib, &data, &gp_IBuffer);
// create a Rasterizer State
D3D11_RASTERIZER_DESC rasterizerDesc{};
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.CullMode = D3D11_CULL_NONE; // or something else
gp_Device->CreateRasterizerState(&rasterizerDesc, &gp_rs);
// this goes in Render()
gp_DeviceContext->IASetIndexBuffer(gp_IBuffer, DXGI_FORMAT_R16_UINT, 0);
gp_DeviceContext->RSSetState(gp_rs);
And you should see this:
PS: in general, you should set all pipeline actions (VSSetShader, PSSetShader, IASetInputLayout, OMSetRenderTargets, etc.) in the "render loop".