Related
I made a texting program with Direct3D11 which allow me both 2D and 3D drawing. I used rastertek.com sample to get 3D scene faster. Then I added my D2D class and passed it trough DXGI without creating 2D device. That was working properly. However, I realized that my PC has no NVIDIA driver so that is why I was using INTEL IGraphics by default. I installed NVIDIA drivers. Reset, switched my preferred video processor to NVIDIA from control panel. Then, debug and I got a black screen. I am not an experienced person. That looks like solving it will be impossible for me. What can I do to fix it ?
I ADDED FULL PROJECT FILE:
https://easyupload.io/3fc087
THIS IS WHAT IT LOOKS LIKE ON INTEL GRAPHICS:
d3dclass.cpp if needed
////////////////////////////////////////////////////////////////////////////////
// Filename: d3dclass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "d3dclass.h"
#include <Windows.h>
D3DClass::D3DClass()
{
m_swapChain = 0;
m_device = 0;
m_deviceContext = 0;
m_renderTargetView = 0;
m_depthStencilBuffer = 0;
m_depthStencilState = 0;
m_depthStencilView = 0;
m_rasterState = 0;
}
D3DClass::D3DClass(const D3DClass& other)
{
}
D3DClass::~D3DClass()
{
}
bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen,
float screenDepth, float screenNear)
{
HRESULT result;
IDXGIFactory* factory;
IDXGIAdapter* adapter;
IDXGIOutput* adapterOutput;
unsigned int numModes, i, numerator, denominator;
size_t stringLength;
DXGI_MODE_DESC* displayModeList;
DXGI_ADAPTER_DESC adapterDesc;
int error;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
D3D_FEATURE_LEVEL featureLevel;
ID3D11Texture2D* backBufferPtr;
D3D11_TEXTURE2D_DESC depthBufferDesc;
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
D3D11_RASTERIZER_DESC rasterDesc;
D3D11_VIEWPORT viewport;
float fieldOfView, screenAspect;
// Store the vsync setting.
m_vsync_enabled = vsync;
// Create a DirectX graphics interface factory.
result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
if (FAILED(result))
{
return false;
}
// Use the factory to create an adapter for the primary graphics interface (video card).
result = factory->EnumAdapters(0, &adapter);
if (FAILED(result))
{
return false;
}
// Enumerate the primary adapter output (monitor).
result = adapter->EnumOutputs(0, &adapterOutput);
if (FAILED(result))
{
return false;
}
// Get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM display format for the adapter output (monitor).
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
if (FAILED(result))
{
return false;
}
// Create a list to hold all the possible display modes for this monitor/video card combination.
displayModeList = new DXGI_MODE_DESC[numModes];
if (!displayModeList)
{
return false;
}
// Now fill the display mode list structures.
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);
if (FAILED(result))
{
return false;
}
// Now go through all the display modes and find the one that matches the screen width and height.
// When a match is found store the numerator and denominator of the refresh rate for that monitor.
for (i = 0; i<numModes; i++)
{
if (displayModeList[i].Width == (unsigned int)screenWidth)
{
if (displayModeList[i].Height == (unsigned int)screenHeight)
{
numerator = displayModeList[i].RefreshRate.Numerator;
denominator = displayModeList[i].RefreshRate.Denominator;
}
}
}
// Get the adapter (video card) description.
result = adapter->GetDesc(&adapterDesc);
if (FAILED(result))
{
return false;
}
// Store the dedicated video card memory in megabytes.
m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024);
// Convert the name of the video card to a character array and store it.
error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);
error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);
if (error != 0)
{
return false;
}
// Release the display mode list.
delete[] displayModeList;
displayModeList = 0;
// Release the adapter output.
adapterOutput->Release();
adapterOutput = 0;
// Release the adapter.
adapter->Release();
adapter = 0;
// Release the factory.
factory->Release();
factory = 0;
// Initialize the swap chain description.
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
// Set to a single back buffer.
swapChainDesc.BufferCount = 1;
// Set the width and height of the back buffer.
swapChainDesc.BufferDesc.Width = screenWidth;
swapChainDesc.BufferDesc.Height = screenHeight;
// Set regular 32-bit surface for the back buffer.
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
// Set the refresh rate of the back buffer.
if (m_vsync_enabled)
{
swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;
}
else
{
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
}
// Set the usage of the back buffer.
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
// Set the handle for the window to render to.
swapChainDesc.OutputWindow = hwnd;
// Turn multisampling off.
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
// Set to full screen or windowed mode.
if (fullscreen)
{
swapChainDesc.Windowed = false;
}
else
{
swapChainDesc.Windowed = true;
}
// Set the scan line ordering and scaling to unspecified.
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// Discard the back buffer contents after presenting.
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
// Don't set the advanced flags.
swapChainDesc.Flags = 0;
// Set the feature level to DirectX 11.
featureLevel = D3D_FEATURE_LEVEL_11_0;
// Create the swap chain, Direct3D device, and Direct3D device context.
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT, &featureLevel, 1,
D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext);
if (FAILED(result))
{
return false;
}
// Get the pointer to the back buffer.
result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
if (FAILED(result))
{
return false;
}
// Create the render target view with the back buffer pointer.
result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
if (FAILED(result))
{
return false;
}
// Release pointer to the back buffer as we no longer need it.
backBufferPtr->Release();
backBufferPtr = 0;
// Initialize the description of the depth buffer.
ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
// Set up the description of the depth buffer.
depthBufferDesc.Width = screenWidth;
depthBufferDesc.Height = screenHeight;
depthBufferDesc.MipLevels = 1;
depthBufferDesc.ArraySize = 1;
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDesc.SampleDesc.Count = 1;
depthBufferDesc.SampleDesc.Quality = 0;
depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDesc.CPUAccessFlags = 0;
depthBufferDesc.MiscFlags = 0;
// Create the texture for the depth buffer using the filled out description.
result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
if (FAILED(result))
{
return false;
}
// Initialize the description of the stencil state.
ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
// Set up the description of the stencil state.
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing.
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing.
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Create the depth stencil state.
result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
if (FAILED(result))
{
return false;
}
// Set the depth stencil state.
m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);
// Initialize the depth stencil view.
ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
// Set up the depth stencil view description.
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
// Create the depth stencil view.
result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
if (FAILED(result))
{
return false;
}
// Bind the render target view and depth stencil buffer to the output render pipeline.
m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);
// create the D2D factory
// Setup the raster description which will determine how and what polygons will be drawn.
rasterDesc.AntialiasedLineEnable = true;
rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = true;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.FrontCounterClockwise = false;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;
// Create the rasterizer state from the description we just filled out.
result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
if (FAILED(result))
{
return false;
}
// Now set the rasterizer state.
m_deviceContext->RSSetState(m_rasterState);
// Setup the viewport for rendering.
viewport.Width = (float)screenWidth;
viewport.Height = (float)screenHeight;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
// Create the viewport.
m_deviceContext->RSSetViewports(1, &viewport);
// Setup the projection matrix.
fieldOfView = 3.141592654f / 4.0f;
screenAspect = (float)screenWidth / (float)screenHeight;
// Create the projection matrix for 3D rendering.
m_projectionMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth);
// Initialize the world matrix to the identity matrix.
m_worldMatrix = XMMatrixIdentity();
// Create an orthographic projection matrix for 2D rendering.
m_orthoMatrix = XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth);
return true;
}
void D3DClass::Shutdown()
{
// Before shutting down set to windowed mode or when you release the swap chain it will throw an exception.
if (m_swapChain)
{
m_swapChain->SetFullscreenState(false, NULL);
}
if (m_rasterState)
{
m_rasterState->Release();
m_rasterState = 0;
}
if (m_depthStencilView)
{
m_depthStencilView->Release();
m_depthStencilView = 0;
}
if (m_depthStencilState)
{
m_depthStencilState->Release();
m_depthStencilState = 0;
}
if (m_depthStencilBuffer)
{
m_depthStencilBuffer->Release();
m_depthStencilBuffer = 0;
}
if (m_renderTargetView)
{
m_renderTargetView->Release();
m_renderTargetView = 0;
}
if (m_deviceContext)
{
m_deviceContext->Release();
m_deviceContext = 0;
}
if (m_device)
{
m_device->Release();
m_device = 0;
}
if (m_swapChain)
{
m_swapChain->Release();
m_swapChain = 0;
}
return;
}
void D3DClass::BeginScene(float red, float green, float blue, float alpha)
{
float color[4];
// Setup the color to clear the buffer to.
color[0] = red;
color[1] = green;
color[2] = blue;
color[3] = alpha;
// Clear the back buffer.
m_deviceContext->ClearRenderTargetView(m_renderTargetView, color);
// Clear the depth buffer.
m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
return;
}
void D3DClass::ClearDepthStencilView() {
m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
}
void D3DClass::EndScene()
{
// Present the back buffer to the screen since rendering is complete.
if (m_vsync_enabled)
{
// Lock to screen refresh rate.
m_swapChain->Present(1, 0);
}
else
{
// Present as fast as possible.
m_swapChain->Present(0, 0);
}
return;
}
ID3D11Device* D3DClass::GetDevice()
{
return m_device;
}
ID3D11DeviceContext* D3DClass::GetDeviceContext()
{
return m_deviceContext;
}
void D3DClass::GetProjectionMatrix(XMMATRIX& projectionMatrix)
{
projectionMatrix = m_projectionMatrix;
return;
}
void D3DClass::GetWorldMatrix(XMMATRIX& worldMatrix)
{
worldMatrix = m_worldMatrix;
return;
}
void D3DClass::GetOrthoMatrix(XMMATRIX& orthoMatrix)
{
orthoMatrix = m_orthoMatrix;
return;
}
void D3DClass::GetVideoCardInfo(char* cardName, int& memory)
{
strcpy_s(cardName, 128, m_videoCardDescription);
memory = m_videoCardMemory;
return;
}
graphicsclass.cpp
////////////////////////////////////////////////////////////////////////////////
// Filename: graphicsclass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "graphicsclass.h"
#include <d3d11_4.h>
#include <string>
GraphicsClass::GraphicsClass()
{
m_Direct2D = 0;
m_Direct3D = 0;
m_Camera = 0;
m_Model = 0;
m_TextureShader = 0;
user_textData=L"testtest";
delta = 0;
}
clock_t begin_time = clock();
float framesPerSecond = 0;
int finalFrame = 0;
GraphicsClass::GraphicsClass(const GraphicsClass& other)
{
}
GraphicsClass::~GraphicsClass()
{
}
bool GraphicsClass::Initialize(int screenWidth, int screenHeight, HWND hwnd)
{
bool result;
// Create the Direct3D object.
m_Direct3D = new D3DClass;
if (!m_Direct3D)
{
return false;
}
// Initialize the Direct3D object.
result = m_Direct3D->Initialize(screenWidth, screenHeight, VSYNC_ENABLED, hwnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR);
if (!result)
{
MessageBox(hwnd, L"Could not initialize Direct3D.", L"Error", MB_OK);
return false;
}
m_Direct2D = new D2DClass;
if (!m_Direct2D)
{
return false;
}
result = m_Direct2D->Initialize(screenWidth, screenHeight, VSYNC_ENABLED, hwnd, m_Direct3D->m_swapChain);
if (!result)
{
MessageBox(hwnd, L"Could not initialize the color shader object.", L"Error", MB_OK);
return false;
}
// Create the camera object.
m_Camera = new CameraClass;
if (!m_Camera)
{
return false;
}
// Set the initial position of the camera.
m_Camera->SetPosition(0.0f, 0.0f, -5.0f);
// Create the model object.
m_Model = new ModelClass;
if (!m_Model)
{
return false;
}
//PIXEL FORMAT SHOULD BE A8...
char img[] = "xxxxx.tga";
char img2[] = "stone01.tga";
// Initialize the model object.
result = m_Model->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), img);
if (!result)
{
MessageBox(hwnd, L"Could not initialize the model object.", L"Error", MB_OK);
return false;
}
// Create the texture shader object.
m_TextureShader = new TextureShaderClass;
if (!m_TextureShader)
{
return false;
}
// Initialize the color shader object.
result = m_TextureShader->Initialize(m_Direct3D->GetDevice(), hwnd);
if (!result)
{
MessageBox(hwnd, L"Could not initialize the color shader object.", L"Error", MB_OK);
return false;
}
return true;
}
void GraphicsClass::Shutdown()
{
// Release the texture shader object.
if (m_TextureShader)
{
m_TextureShader->Shutdown();
delete m_TextureShader;
m_TextureShader = 0;
}
// Release the model object.
if (m_Model)
{
m_Model->Shutdown();
delete m_Model;
m_Model = 0;
}
// Release the camera object.
if (m_Camera)
{
delete m_Camera;
m_Camera = 0;
}
// Release the D3D object.
if (m_Direct3D)
{
m_Direct3D->Shutdown();
delete m_Direct3D;
m_Direct3D = 0;
}
// Release the D2D object.
if (m_Direct2D)
{
m_Direct2D->Shutdown();
delete m_Direct2D;
m_Direct2D = 0;
}
return;
}
ColorF cf[]{ ColorF::White,ColorF::Red,ColorF::Green,ColorF::Blue,ColorF::Yellow,ColorF::Orange,ColorF::Black,ColorF::Brown,ColorF::DarkRed,ColorF::DarkBlue,ColorF::DarkGreen,ColorF::Azure,ColorF::Aqua,ColorF::Purple,ColorF::DarkRed,ColorF::Cyan,ColorF::DarkCyan };
int arrayMax = (sizeof(cf[0])-1);
int RandIndex = 0;
bool GraphicsClass::Frame()
{
framesPerSecond++;
if (delta >= 1.0f) {
finalFrame = framesPerSecond;
framesPerSecond = delta = 0; begin_time = clock();
RandIndex = rand() % arrayMax;
}
else {
delta = float(clock() - begin_time) / CLOCKS_PER_SEC;
}
bool result;
// Render the graphics scene.
result = Render();
if (!result)
{
return false;
}
return true;
}
bool GraphicsClass::Render()
{
XMMATRIX worldMatrix, viewMatrix, projectionMatrix;
bool result;
// Clear the buffers to begin the scene.
m_Direct3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);
// Generate the view matrix based on the camera's position.
m_Camera->Render();
// Get the world, view, and projection matrices from the camera and d3d objects.
m_Direct3D->GetWorldMatrix(worldMatrix);
m_Camera->GetViewMatrix(viewMatrix);
m_Direct3D->GetProjectionMatrix(projectionMatrix);
// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_Model->Render(m_Direct3D->GetDeviceContext());
// Render the model using the texture shader.
result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture());
if (!result)
{
return false;
}
// draw the text
wstring FPS_STRING = to_wstring(finalFrame).append(L"Frames Per Second !");
const wchar_t *test[] = { FPS_STRING.c_str() };
m_Direct2D->RenderText(*test, L"Windows Command Prompt", 0, 0,cf[RandIndex]);
const wchar_t *usr_txt[] = { user_textData.c_str() };
m_Direct2D->RenderText(*usr_txt, L"Windows Command Prompt", 0, 70, ColorF::Red);
// render stroked rounded Rectangle
//m_Direct2D->RenderRectangle(XMFLOAT2(70, 30), XMFLOAT2(100, 100), XMFLOAT2(6, 6), 3.0f, ColorF::Red, true, false, true);
// Present the rendered scene to the screen.
m_Direct3D->EndScene();
/*m_Direct2D->m_D2DMultithread->Leave();*/
return true;
}
Resolution should be set correctly:
screenWidth = 1366; //MY PC HAS THIS RESOLUTION, MANUALLY SET IT.
screenHeight = 768; //
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
0, 0, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
I HAD A SECONDARY OWNER WINDOW THAT IS WHY I MISLEADED. STILL, I DO NOT KNOW THE REASON WHY INTEL RENDERS IT DESIRED SIZE example "199, 132" and NVIDIA DO NOT. NVIDIA WANTS TO RENDER SPECIFIC RESOLUTIONS LIKE 1024x768,1366x768 (tested them).
I'm taking my first steps in programming with Direct3D. I have a very basic pipeline setup, and all I want to get from it is an antialiased smooth image. But I get this:
First, I can't get rid of stair effect though I have 4x MSAA enabled already in my pipeline (DXGI_SAMPLE_DESC::Count is 4 and Quality is 0):
And second, I get this noisy texturing though I have mipmaps generated and LINEAR filtering set in the sampler state.
Am I missing something or doing wrong?
Here is my code:
1) Renderer class:
#include "Scene.h" // Custom class that contains vertex and index buffer contents for every rendered mesh.
#include "Camera.h" // Custom class that contains camera position and fov.
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
#include <DirectXMath.h>
using namespace DirectX;
#include <map>
#include "generated\VertexShader.h"
#include "generated\PixelShader.h"
class Renderer
{
public:
Renderer(HWND hWnd, int wndWidth, int wndHeight, const Scene& scene, const Camera& camera);
void Render();
void SwitchToWireframe();
void SwitchToSolid();
protected:
void CreateDeviceAndSwapChain();
void CreateDepthStencil();
void CreateInputLayout();
void CreateVertexShader();
void CreatePixelShader();
void CreateRasterizerStates();
void CreateBlendState();
void CreateSamplerState();
void CreateBuffer(ID3D11Buffer** buffer,
D3D11_USAGE usage, D3D11_BIND_FLAG bindFlags,
UINT cpuAccessFlags, UINT miscFlags,
UINT sizeOfBuffer, UINT sizeOfBufferElement, const void* initialData);
void CreateTexture2DAndSRV(const Scene::Texture& texture, ID3D11ShaderResourceView** view);
void CreateTexturesAndViews();
void GenerateMips();
protected:
const Scene& m_scene;
const Camera& m_camera;
DWORD m_cameraLastUpdateTickCount;
HWND m_windowHandle;
int m_windowWidth;
int m_windowHeight;
DXGI_SAMPLE_DESC m_sampleDesc;
ComPtr<IDXGISwapChain> m_swapChain;
ComPtr<ID3D11Texture2D> m_swapChainBuffer;
ComPtr<ID3D11RenderTargetView> m_swapChainBufferRTV;
ComPtr<ID3D11Device> m_device;
ComPtr<ID3D11DeviceContext> m_deviceContext;
ComPtr<ID3D11Debug> m_debugger;
ComPtr<ID3D11Texture2D> m_depthStencilTexture;
ComPtr<ID3D11DepthStencilState> m_depthStencilState;
ComPtr<ID3D11DepthStencilView> m_depthStencilView;
ComPtr<ID3D11InputLayout> m_inputLayout;
ComPtr<ID3D11VertexShader> m_vertexShader;
ComPtr<ID3D11PixelShader> m_pixelShader;
ComPtr<ID3D11RasterizerState> m_solidRasterizerState;
ComPtr<ID3D11RasterizerState> m_wireframeRasterizerState;
ComPtr<ID3D11BlendState> m_blendState;
ComPtr<ID3D11SamplerState> m_linearSamplerState;
std::map<std::string, ComPtr<ID3D11ShaderResourceView>> m_diffuseMapViews;
std::map<std::string, ComPtr<ID3D11ShaderResourceView>> m_normalMapViews;
XMMATRIX m_worldViewMatrix;
ID3D11RasterizerState* m_currentRasterizerState;
};
void Renderer::CreateDeviceAndSwapChain()
{
HRESULT hr;
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
swapChainDesc.BufferDesc.Width = m_windowWidth;
swapChainDesc.BufferDesc.Height = m_windowHeight;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 1;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 60;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
swapChainDesc.SampleDesc = m_sampleDesc;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = m_windowHandle;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
D3D_FEATURE_LEVEL desiredFeatureLevels[] = { D3D_FEATURE_LEVEL_10_1 };
D3D_FEATURE_LEVEL featureLevel;
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
desiredFeatureLevels, 1, D3D11_SDK_VERSION, &swapChainDesc,
m_swapChain.GetAddressOf(), m_device.GetAddressOf(), &featureLevel,
m_deviceContext.GetAddressOf());
if (FAILED(hr))
{
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL,
D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
desiredFeatureLevels, 1, D3D11_SDK_VERSION, &swapChainDesc,
m_swapChain.GetAddressOf(), m_device.GetAddressOf(), &featureLevel,
m_deviceContext.GetAddressOf());
}
if (FAILED(hr))
throw std::exception("Failed to create device or swap chain");
hr = m_device->QueryInterface(m_debugger.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to get debugger interface");
hr = m_swapChain->GetBuffer(0, __uuidof(m_swapChainBuffer),
(void**)m_swapChainBuffer.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to get swap chain buffer");
hr = m_device->CreateRenderTargetView(m_swapChainBuffer.Get(), NULL,
m_swapChainBufferRTV.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create RTV for swap chain buffer");
}
void Renderer::CreateDepthStencil()
{
HRESULT hr;
D3D11_TEXTURE2D_DESC tdesc;
tdesc.Width = m_windowWidth;
tdesc.Height = m_windowHeight;
tdesc.MipLevels = 1;
tdesc.ArraySize = 1;
tdesc.Format = DXGI_FORMAT_D16_UNORM;
tdesc.SampleDesc = m_sampleDesc;
tdesc.Usage = D3D11_USAGE_DEFAULT;
tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
tdesc.CPUAccessFlags = 0;
tdesc.MiscFlags = 0;
hr = m_device->CreateTexture2D(&tdesc, NULL, m_depthStencilTexture.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create depth stencil texture");
D3D11_DEPTH_STENCIL_VIEW_DESC dsvdesc;
dsvdesc.Format = DXGI_FORMAT_D16_UNORM;
dsvdesc.ViewDimension = m_sampleDesc.Count > 1
? D3D11_DSV_DIMENSION_TEXTURE2DMS
: D3D11_DSV_DIMENSION_TEXTURE2D;
dsvdesc.Flags = 0;
dsvdesc.Texture2D.MipSlice = 0;
hr = m_device->CreateDepthStencilView(m_depthStencilTexture.Get(), &dsvdesc,
m_depthStencilView.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create depth stencil view");
D3D11_DEPTH_STENCIL_DESC dsdesc;
dsdesc.DepthEnable = TRUE;
dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsdesc.DepthFunc = D3D11_COMPARISON_LESS;
dsdesc.StencilEnable = FALSE;
dsdesc.StencilReadMask = 0;
dsdesc.StencilWriteMask = 0;
dsdesc.FrontFace = {};
dsdesc.BackFace = {};
hr = m_device->CreateDepthStencilState(&dsdesc, m_depthStencilState.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create depth stencil state");
}
void Renderer::CreateInputLayout()
{
HRESULT hr;
D3D11_INPUT_ELEMENT_DESC iedescs[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = m_device->CreateInputLayout(iedescs, 3,
g_vertexShader, sizeof(g_vertexShader),
m_inputLayout.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create input layout");
}
void Renderer::CreateVertexShader()
{
HRESULT hr;
hr = m_device->CreateVertexShader(g_vertexShader, sizeof(g_vertexShader),
NULL, m_vertexShader.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create vertex shader");
}
void Renderer::CreatePixelShader()
{
HRESULT hr;
hr = m_device->CreatePixelShader(g_pixelShader, sizeof(g_pixelShader),
NULL, m_pixelShader.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create pixel shader");
}
void Renderer::CreateRasterizerStates()
{
HRESULT hr;
D3D11_RASTERIZER_DESC rdesc;
rdesc.FillMode = D3D11_FILL_SOLID;
rdesc.CullMode = D3D11_CULL_FRONT;
rdesc.FrontCounterClockwise = FALSE;
rdesc.DepthBias = 0;
rdesc.DepthBiasClamp = 0.0f;
rdesc.SlopeScaledDepthBias = 0.0f;
rdesc.DepthClipEnable = TRUE;
rdesc.ScissorEnable = FALSE;
rdesc.MultisampleEnable = m_sampleDesc.Count > 1 ? TRUE : FALSE;
rdesc.AntialiasedLineEnable = m_sampleDesc.Count > 1 ? TRUE : FALSE;
hr = m_device->CreateRasterizerState(&rdesc, m_solidRasterizerState.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create rasterizer state");
rdesc.FillMode = D3D11_FILL_WIREFRAME;
hr = m_device->CreateRasterizerState(&rdesc, m_wireframeRasterizerState.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create rasterizer state");
m_currentRasterizerState = m_solidRasterizerState.Get();
}
void Renderer::CreateSamplerState()
{
HRESULT hr;
D3D11_SAMPLER_DESC smdesc;
smdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
smdesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
smdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
smdesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
smdesc.MipLODBias = 0.0f;
smdesc.MaxAnisotropy = 0;
smdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
smdesc.BorderColor[4] = {};
FLOAT MinLOD = 0.0;
FLOAT MaxLOD = 0.0;
hr = m_device->CreateSamplerState(&smdesc, m_linearSamplerState.GetAddressOf());
if (FAILED(hr))
throw new std::exception("Failed to create sampler state");
}
void Renderer::CreateBlendState()
{
HRESULT hr;
D3D11_BLEND_DESC bdesc;
bdesc.AlphaToCoverageEnable = FALSE;
bdesc.IndependentBlendEnable = FALSE;
bdesc.RenderTarget[0].BlendEnable = FALSE;
bdesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
bdesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
bdesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
bdesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
bdesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
bdesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
bdesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
hr = m_device->CreateBlendState(&bdesc, m_blendState.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create blend state");
}
void Renderer::CreateBuffer(ID3D11Buffer** buffer,
D3D11_USAGE usage, D3D11_BIND_FLAG bindFlags,
UINT cpuAccessFlags, UINT miscFlags,
UINT sizeOfBuffer, UINT sizeOfBufferElement, const void* initialData)
{
HRESULT hr;
D3D11_BUFFER_DESC bdesc;
bdesc.ByteWidth = sizeOfBuffer;
bdesc.Usage = usage;
bdesc.BindFlags = bindFlags;
bdesc.CPUAccessFlags = cpuAccessFlags;
bdesc.MiscFlags = miscFlags;
bdesc.StructureByteStride = sizeOfBufferElement;
D3D11_SUBRESOURCE_DATA bdata;
bdata.pSysMem = initialData;
bdata.SysMemPitch = 0;
bdata.SysMemSlicePitch = 0;
hr = m_device->CreateBuffer(&bdesc, &bdata, buffer);
if (FAILED(hr))
throw std::exception("Failed to create buffer");
}
void Renderer::CreateTexture2DAndSRV(const Scene::Texture& sceneTexture, ID3D11ShaderResourceView** view)
{
HRESULT hr;
constexpr DXGI_FORMAT texformat = DXGI_FORMAT_R32G32B32A32_FLOAT;
D3D11_TEXTURE2D_DESC tdesc;
tdesc.Width = sceneTexture.width;
tdesc.Height = sceneTexture.height;
tdesc.MipLevels = 0;
tdesc.ArraySize = 1;
tdesc.Format = texformat;
tdesc.SampleDesc.Count = 1;
tdesc.SampleDesc.Quality = 0;
tdesc.Usage = D3D11_USAGE_DEFAULT;
tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
tdesc.CPUAccessFlags = 0;
tdesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
ComPtr<ID3D11Texture2D> texture2d;
hr = m_device->CreateTexture2D(&tdesc, NULL, texture2d.GetAddressOf());
if (FAILED(hr))
throw std::exception("Failed to create texture");
D3D11_SUBRESOURCE_DATA srdata;
srdata.pSysMem = sceneTexture.data;
srdata.SysMemPitch = sceneTexture.width * sizeof(float) * 4;
srdata.SysMemSlicePitch = 0;
m_deviceContext->UpdateSubresource(texture2d.Get(), 0, NULL,
srdata.pSysMem, srdata.SysMemPitch, srdata.SysMemSlicePitch);
D3D11_SHADER_RESOURCE_VIEW_DESC srvdesc;
srvdesc.Format = texformat;
srvdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvdesc.Texture2D.MostDetailedMip = 0;
srvdesc.Texture2D.MipLevels = -1;
ComPtr<ID3D11ShaderResourceView> shaderResourceView;
hr = m_device->CreateShaderResourceView(texture2d.Get(), &srvdesc, view);
if (FAILED(hr))
throw std::exception("Failed to create shader resource view");
}
void Renderer::CreateTexturesAndViews()
{
for (auto it = m_scene.materials.cbegin(); it != m_scene.materials.cend(); it++)
{
//don't know what's the problem but if I don't place initialized ComPtr<...> instance into a map
//then further .GetAddessOf() fails.
m_diffuseMapViews.emplace(it->first, ComPtr<ID3D11ShaderResourceView>());
m_normalMapViews.emplace(it->first, ComPtr<ID3D11ShaderResourceView>());
CreateTexture2DAndSRV(it->second.diffuseMap, m_diffuseMapViews[it->first].GetAddressOf());
CreateTexture2DAndSRV(it->second.normalMap, m_normalMapViews[it->first].GetAddressOf());
}
}
void Renderer::GenerateMips()
{
for (auto it = m_diffuseMapViews.begin(); it != m_diffuseMapViews.end(); it++)
m_deviceContext->GenerateMips(it->second.Get());
for (auto it = m_normalMapViews.begin(); it != m_normalMapViews.end(); it++)
m_deviceContext->GenerateMips(it->second.Get());
}
Renderer::Renderer(HWND hWnd, int windowWidth, int windowHeight,
const Scene& scene, const Camera& camera)
: m_scene(scene)
, m_camera(camera)
, m_cameraLastUpdateTickCount(0)
, m_windowHandle(hWnd)
, m_windowWidth(windowWidth)
, m_windowHeight(windowHeight)
{
m_sampleDesc.Count = 4;
m_sampleDesc.Quality = 0;
CreateDeviceAndSwapChain();
CreateDepthStencil();
CreateInputLayout();
CreateVertexShader();
CreatePixelShader();
CreateRasterizerStates();
CreateBlendState();
CreateSamplerState();
CreateTexturesAndViews();
GenerateMips();
// Setting up IA stage
m_deviceContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_deviceContext->IASetInputLayout(m_inputLayout.Get());
// Setting up VS stage
m_deviceContext->VSSetShader(m_vertexShader.Get(), 0, 0);
// Setting up RS stage
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast<FLOAT>(m_windowWidth);
viewport.Height = static_cast<FLOAT>(m_windowHeight);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
m_deviceContext->RSSetViewports(1, &viewport);
// Setting up PS stage
m_deviceContext->PSSetSamplers(0, 1, m_linearSamplerState.GetAddressOf());
m_deviceContext->PSSetShader(m_pixelShader.Get(), 0, 0);
// Setting up OM stage
m_deviceContext->OMSetBlendState(m_blendState.Get(), NULL, 0xffffffff);
m_deviceContext->OMSetDepthStencilState(m_depthStencilState.Get(), 0);
m_deviceContext->OMSetRenderTargets(1, m_swapChainBufferRTV.GetAddressOf(), m_depthStencilView.Get());
}
void Renderer::Render()
{
constexpr float background[4] = { 0.047f, 0.0487f, 0.066f, 1.0f };
// Setting up view matix
if (m_cameraLastUpdateTickCount
!= m_camera.GetLastUpdateTickCount())
{
const Float3& camFrom = m_camera.GetFrom();
const Float3& camAt = m_camera.GetAt();
const Float3& camUp = m_camera.GetUp();
m_cameraLastUpdateTickCount = m_camera.GetLastUpdateTickCount();
FXMVECTOR from = XMVectorSet(camFrom.x, camFrom.y, camFrom.z, 1.0f);
FXMVECTOR at = XMVectorSet(camAt.x, camAt.y, camAt.z, 1.0f);
FXMVECTOR up = XMVectorSet(camUp.x, camUp.y, camUp.z, 0.0f);
FXMVECTOR dir = XMVectorSubtract(at, from);
FXMVECTOR x = XMVector3Cross(dir, up);
FXMVECTOR up2 = XMVector3Cross(x, dir);
XMMATRIX lookTo = XMMatrixLookToRH(from, dir, up2);
float scalef = 1.0f / XMVectorGetByIndex(XMVector3Length(dir), 0);
XMMATRIX scale = XMMatrixScaling(scalef, scalef, scalef);
float aspect = float(m_windowWidth) / m_windowHeight;
float fov = m_camera.GetFov() / 180.0f * 3.14f;
XMMATRIX persp = XMMatrixPerspectiveFovRH(fov, aspect, 0.1f, 1000.0f);
m_worldViewMatrix = XMMatrixMultiply(XMMatrixMultiply(lookTo, scale), persp);
}
else
{
return;
}
m_deviceContext->ClearDepthStencilView(m_depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
m_deviceContext->ClearRenderTargetView(m_swapChainBufferRTV.Get(), background);
for (auto imesh = m_scene.meshes.cbegin(); imesh != m_scene.meshes.cend(); imesh++)
{
// Creating vertex buffer
ComPtr<ID3D11Buffer> vertexBuffer;
CreateBuffer(vertexBuffer.GetAddressOf(),
D3D11_USAGE_DEFAULT, D3D11_BIND_VERTEX_BUFFER, 0, 0,
sizeof(Scene::Vertex) * imesh->vertices.size(), sizeof(Scene::Vertex),
imesh->vertices.data());
// Creating index buffer
ComPtr<ID3D11Buffer> indexBuffer;
CreateBuffer(indexBuffer.GetAddressOf(),
D3D11_USAGE_DEFAULT, D3D11_BIND_INDEX_BUFFER, 0, 0,
sizeof(unsigned int) * imesh->indices.size(), sizeof(unsigned int),
imesh->indices.data());
// Creating constant buffer
ComPtr<ID3D11Buffer> constantBuffer;
CreateBuffer(constantBuffer.GetAddressOf(),
D3D11_USAGE_IMMUTABLE, D3D11_BIND_CONSTANT_BUFFER, 0, 0,
sizeof(XMMATRIX), sizeof(XMMATRIX),
&m_worldViewMatrix);
// Setting up IA stage
ID3D11Buffer* vertexBuffers[8] = { vertexBuffer.Get() };
unsigned int vertexBufferStrides[8] = { sizeof(Scene::Vertex) };
unsigned int vertexBufferOffsets[8] = { 0 };
m_deviceContext->IASetVertexBuffers(0, 8,
vertexBuffers, vertexBufferStrides, vertexBufferOffsets);
m_deviceContext->IASetIndexBuffer(indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
// Setting up VS stage
m_deviceContext->VSSetConstantBuffers(0, 1, constantBuffer.GetAddressOf());
// Setting up RS stage
m_deviceContext->RSSetState(m_currentRasterizerState);
// Setting up PS stage
ID3D11ShaderResourceView* srvs[2] = { };
srvs[0] = m_diffuseMapViews.at(imesh->material).Get();
srvs[1] = m_normalMapViews.at(imesh->material).Get();
m_deviceContext->PSSetShaderResources(0, 2, srvs);
// Drawing
m_deviceContext->DrawIndexed(imesh->indices.size(), 0, 0);
}
m_swapChain->Present(0, 0);
}
void Renderer::SwitchToWireframe()
{
m_currentRasterizerState = m_wireframeRasterizerState.Get();
m_camera.UpdateLastUpdateTickCount();
}
void Renderer::SwitchToSolid()
{
m_currentRasterizerState = m_solidRasterizerState.Get();
m_camera.UpdateLastUpdateTickCount();
}
2) Vertex shader
struct VS_INPUT
{
float3 position : POSITION;
float3 normal : NORMAL;
float2 texcoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : SV_POSITION;
float3 normal : NORMAL;
float2 texcoord : TEXCOORD;
};
cbuffer Matrices
{
matrix worldViewMatrix;
}
VS_OUTPUT main(VS_INPUT input)
{
VS_OUTPUT output;
output.position = mul(worldViewMatrix, float4(input.position.xyz, 1.0));
output.normal = input.normal;
output.texcoord = input.texcoord;
return output;
}
3) Pixel shader
Texture2D DiffuseMap : register(t0);
Texture2D NormalMap: register(t1);
SamplerState LinearSampler : register(s0);
float4 main(VS_OUTPUT input) : SV_TARGET
{
float3 light = normalize(float3(2.87, -0.36, 1.68));
float3 diffuseColor = DiffuseMap.Sample(LinearSampler, input.texcoord);
float3 normalDisplace = float3(0.0, 0.0, 1.0) - NormalMap.Sample(LinearSampler, input.texcoord);
float illumination = clamp(dot(light, input.normal + normalDisplace), 0.2, 1.0);
return float4(mul(diffuseColor, illumination), 1.0);
}
Okay, I've just figured out the reason of this stairs effect:
The reason is that I passed the same width and height values for CreateWindow WinApi function, and for DXGI_SWAP_CHAIN_DESC::BufferDesc. Meanwhile, these should be different because CreateWindow takes outer width and height of a window to create (window rectangle), while BufferDesc should receive inner values (window client area rectangle). Because of that actual area on screen was smaller than swap chain buffer and the result of rendering was presumably resampled to fit the rectangle, which was introducing the aliasing after MSAA was already applied.
Fixing the issue gave a much cleaner result (4x MSAA is applied here):
But the question with texture aliasing is still open:
I am developing a game engine using DX11. I am following a tutorial at http://www.rastertek.com/. I have done tutorial 2. The problem is that, when I try to change the color values, the window remains black. The relevant code is:
Graphics.cpp
bool Graphics::Initialize(int screenWidth, int screenHeight, HWND hwnd)
{
bool result;
m_D3D = new D3DClass;
if (!m_D3D)
return false;
result = m_D3D->Initialize(screenWidth, screenHeight, hwnd, VSYNC_ENABLED, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR);
if (!result)
{
MessageBox(hwnd, "Could not initialize Direct3D", "Error", MB_OK);
return false;
}
return true;
}
bool Graphics::Render()
{
m_D3D->BeginScene(0.0f, 0.0f, 0.0f, 0.0f);
m_D3D->EndScene();
return true;
}
D3DClass.cpp
bool D3DClass::Initialize(int screenWidth, int screenHeight, HWND hwnd, bool vsync, bool fullscreen, float screenDepth, float screenNear)
{
HRESULT result;
IDXGIFactory* factory;
IDXGIAdapter* adapter;
IDXGIOutput* adapterOutput;
unsigned int numModes, i, numerator, denominator, stringLength;
DXGI_MODE_DESC* displayModeList;
DXGI_ADAPTER_DESC adapterDesc;
int error;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
D3D_FEATURE_LEVEL featureLevel;
ID3D11Texture2D* backBufferPtr;
D3D11_TEXTURE2D_DESC depthBufferDesc;
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
D3D11_RASTERIZER_DESC rasterDesc;
D3D11_VIEWPORT viewport;
float fieldOfView, screenAspect;
m_vsync_enabled = vsync;
result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
if (FAILED(result))
return false;
result = factory->EnumAdapters(0, &adapter);
if (FAILED(result))
return false;
result = adapter->EnumOutputs(0, &adapterOutput);
if (FAILED(result))
return false;
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
if (FAILED(result))
return false;
displayModeList = new DXGI_MODE_DESC[numModes];
if (!displayModeList)
return false;
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);
if(FAILED(result))
return false;
for (int i = 0; i < numModes; i++)
{
if (displayModeList[i].Height == (unsigned int)screenHeight && displayModeList[i].Width == (unsigned int)screenWidth)
{
numerator = displayModeList[i].RefreshRate.Numerator;
denominator = displayModeList[i].RefreshRate.Denominator;
break;
}
}
result = adapter->GetDesc(&adapterDesc);
if (FAILED(result))
return false;
m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1048576); //MB
error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);
if (error != 0)
return false;
delete[] displayModeList;
displayModeList = 0;
adapterOutput->Release();
adapterOutput = 0;
adapter->Release();
adapter = 0;
factory->Release();
factory = 0;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = screenWidth;
swapChainDesc.BufferDesc.Height = screenHeight;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
if (m_vsync_enabled)
{
swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;
}
else
{
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
}
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hwnd;
//MultiSampling Off
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = !fullscreen;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = 0;
featureLevel = D3D_FEATURE_LEVEL_11_0;
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext);
if (FAILED(result))
return false;
result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
if (FAILED(result))
return false;
backBufferPtr->Release();
backBufferPtr = 0;
ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
depthBufferDesc.Width = screenWidth;
depthBufferDesc.Height = screenHeight;
depthBufferDesc.MipLevels = 1;
depthBufferDesc.ArraySize = 1;
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
//Multisampling off
depthBufferDesc.SampleDesc.Count = 1;
depthBufferDesc.SampleDesc.Quality = 0;
depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDesc.CPUAccessFlags = 0;
depthBufferDesc.MiscFlags = 0;
result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
if (FAILED(result))
return false;
ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
if (FAILED(result))
return false;
m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);
ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
if (FAILED(result))
return false;
m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);
//TODO::CUSTOMIZE USER PRESETS
rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = true;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.FrontCounterClockwise = false;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;
result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
if (FAILED(result))
return false;
m_deviceContext->RSSetState(m_rasterState);
viewport.Width = (float)screenWidth;
viewport.Height = (float)screenHeight;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
m_deviceContext->RSSetViewports(1, &viewport);
//TODO:: FOV SETTINGS
fieldOfView = (float)D3DX_PI / 4.0f;
screenAspect = (float)screenWidth / (float)screenHeight;
D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth);
D3DXMatrixIdentity(&m_worldMatrix);
D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, screenNear, screenDepth);
return true;
}
void D3DClass::BeginScene(float red, float green, float blue, float alpha)
{
m_deviceContext->ClearRenderTargetView(m_renderTargetView, D3DXCOLOR(red, green, blue, alpha));
m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
return;
}
void D3DClass::EndScene()
{
if (m_vsync_enabled)
m_swapChain->Present(1, 0);
else
m_swapChain->Present(0, 0);
return;
}
Framework.cpp
void Framework::InitializeWindows(int& screenWidth, int& screenHeight)
{
WNDCLASSEX wc;
DEVMODE dmScreenSettings;
int posX, posY;
m_application = this;
m_hinstance = GetModuleHandle(NULL);
m_applicationName = "Racing Game";
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = m_hinstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = wc.hIcon;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = m_applicationName;
wc.cbSize = sizeof(WNDCLASSEX);
RegisterClassEx(&wc);
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
if (FULL_SCREEN)
{
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
posX = posY = 0;
}
else
{
screenWidth = 800;
screenHeight = 600;
posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
}
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
ShowWindow(m_hwnd, SW_SHOW);
SetForegroundWindow(m_hwnd);
SetFocus(m_hwnd);
ShowCursor(false);
return;
}
Each time I change the parameters in theBeginScene() call, no matter what those are (i tried values ranging from 1.0f to 256.0f on the red), the window is always black and there isn't the windows top three buttons (close, minimize, expand). What am I doing wrong? Any help appreciated.
I am following the same tutorials,
It's floating point value between 0 and 1.
so in your case for red color it's
bool Graphics::Render()
{
m_D3D->BeginScene(1.0f, 0.0f, 0.0f, 1.0f);
m_D3D->EndScene();
return true;
}
Don't forget to set opacity to 1.0 the last value.
Good luck for the next ones.
Fist things first - Full error:
Error 3 error C2664: 'errno_t wcstombs_s(size_t *,char *,size_t,const wchar_t *,size_t)' : cannot convert argument 1 from 'unsigned int *' to 'size_t *' C:\Users\Adam\Desktop\DirectxTEST\Win32Project4\D3dclass.cpp 88 1 Win32Project4
I know whats causing this error(I think), I'm just stuck on what is "size_t*", because I've checked and my statment that I use wcstombs_s goes: unsigned int, char[128], int, WCHAR, int. This is the function with said line in, the header file that goes with the class it's in(incase somehow this is a #include error), and then the entire class, it's really long and 90% of it is irrelevent, but just to provide context incase it's nessicery.
Main code:
error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);
if (error != 0){
return false;
}
.h
#ifndef _D3DCLASS_H_
#define _D3DCLASS_H_
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
//#pragma comment(lib, "d3dx11.lib")
//#pragma comment(lib, "d3dx10.lib")
#include <dxgi.h>
#include <D3DCommon.h>
#include <d3d11.h>
#include <d3dx10math.h>
class D3DClass{
public:
D3DClass();
D3DClass(const D3DClass&);
~D3DClass();
bool Initialize(int, int, bool, HWND, bool, float, float);
void Shutdown();
void BeginScene(float, float, float, float);
void EndScene();
ID3D11Device* GetDevice();
ID3D11DeviceContext* GetDeviceContext();
void GetProjectionMatrix(D3DXMATRIX&);
void GetWorldMatrix(D3DXMATRIX&);
void GetOrthoMatrix(D3DXMATRIX&);
void GetVideoCardInfo(char*, int&);
private:
bool m_vsync_enabled;
int m_videoCardMemory;
char m_videoCardDescription[128];
IDXGISwapChain* m_swapChain;
ID3D11Device* m_device;
ID3D11DeviceContext* m_deviceContext;
ID3D11RenderTargetView* m_renderTargetView;
ID3D11Texture2D* m_depthStencilBuffer;
ID3D11DepthStencilState* m_depthStencilState;
ID3D11DepthStencilView* m_depthStencilView;
ID3D11RasterizerState* m_rasterState;
D3DXMATRIX m_projectionMatrix;
D3DXMATRIX m_worldMatrix;
D3DXMATRIX m_orthoMatrix;
};
#endif
Full Class
#include "D3Dclass.h"
D3DClass::D3DClass(){
m_swapChain = 0;
m_device = 0;
m_deviceContext = 0;
m_renderTargetView = 0;
m_depthStencilBuffer = 0;
m_depthStencilState = 0;
m_depthStencilView = 0;
m_rasterState = 0;
}
D3DClass::D3DClass(const D3DClass& other){
}
D3DClass::~D3DClass(){
}
bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen, float screenDepth, float screenNear){
HRESULT result;
IDXGIFactory* factory;
IDXGIAdapter* adapter;
IDXGIOutput* adapterOutput;
unsigned int numModes, i, numerator, denominator, stringLength;
DXGI_MODE_DESC* displayModeList;
DXGI_ADAPTER_DESC adapterDesc;
int error;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
D3D_FEATURE_LEVEL featureLevel;
ID3D11Texture2D* backBufferPtr;
D3D11_TEXTURE2D_DESC depthBufferDesc;
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
D3D11_RASTERIZER_DESC rasterDesc;
D3D11_VIEWPORT viewport;
float fieldOfView, screenAspect;
m_vsync_enabled = vsync;
//Create a DirectX Graphics Interface Library
result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
if (FAILED(result)){
return false;
}
//Create apapter for video card
result = factory->EnumAdapters(0, &adapter);
if (FAILED(result)){
return false;
}
//Enemerate the moniter/screen
result = adapter->EnumOutputs(0, &adapterOutput);
if (FAILED(result)){
return false;
}
//Get the number of nodes that fit in the DXGI below for moniter
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
if (FAILED(result)){
return false;
}
//Create list to hold possible display modes for moniter
displayModeList = new DXGI_MODE_DESC[numModes];
if (!displayModeList){
return false;
}
//Fill display mode structure
result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);
if (FAILED(result)){
return false;
}
//Find display mode that matches screen width and height
//Then store numerator and denominator of refresh rate
for (i = 0; i < numModes; i++){
if (displayModeList[i].Width == (unsigned int)screenWidth){
if (displayModeList[i].Height == (unsigned int)screenHeight){
numerator = displayModeList[i].RefreshRate.Numerator;
denominator = displayModeList[i].RefreshRate.Denominator;
}
}
}
//Get video card desc
result = adapter->GetDesc(&adapterDesc);
if (FAILED(result)){
return false;
}
//Store dedicated video card memory in megabytes
m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024);
//Convert video card name to char and store it
error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);
if (error != 0){
return false;
}
//Release display mode list
delete[] displayModeList;
displayModeList = 0;
//Release adapter output
adapterOutput->Release();
adapterOutput = 0;
//Release the adapter
adapter->Release();
adapter = 0;
//Release the Factory
factory->Release();
factory = 0;
//Initialize swap chain description
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
//Set to a single back buffer
swapChainDesc.BufferCount = 1;
//Set sizes of back buffer
swapChainDesc.BufferDesc.Width = screenWidth;
swapChainDesc.BufferDesc.Height = screenHeight;
//Set regular 32bit surface for back buffer
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
//Set refresh rate for back buffer
if (m_vsync_enabled){
swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;
}
else{
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
}
//Set usage of back buffer
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
//Set handle for the window to render into
swapChainDesc.OutputWindow = hwnd;
//Turn multisampling off
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
//Set to full screen/windowed
if (fullscreen){
swapChainDesc.Windowed = false;
}
else{
swapChainDesc.Windowed = true;
}
//Thing?
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
//Discard buffer contents after presenting
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
//Don't set advanced flags
swapChainDesc.Flags = 0;
//Set feature level to DirectX-11
featureLevel = D3D_FEATURE_LEVEL_11_0;
//Create the Swap Chain, Direct3D device and Direct3D device context
//Turn D3D_DRIVER_TYPE_HARDWARE to D3D_DRIVER_TYPE_REFERENCE to support directx10 or lower
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext);
if (FAILED(result)){
return false;
}
//Get pointer to back buffer
result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
if (FAILED(result)){
return false;
}
//Create render target view with back buffer pointer
result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
if (FAILED(result)){
return false;
}
//Release pointer to back buffer
backBufferPtr->Release();
backBufferPtr = 0;
//Initialize depth buffer desc
ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
//Depth Buffer Description
depthBufferDesc.Width = screenWidth;
depthBufferDesc.Height = screenHeight;
depthBufferDesc.MipLevels = 1;
depthBufferDesc.ArraySize = 1;
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDesc.SampleDesc.Count = 1;
depthBufferDesc.SampleDesc.Quality = 0;
depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDesc.CPUAccessFlags = 0;
depthBufferDesc.MiscFlags = 0;
//Create texture for depth buffer
result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
if (FAILED(result)){
return false;
}
//Initialize stencil state desc
ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
//Setup desc
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
//Create depth stencil state
result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
if (FAILED(result)){
return false;
}
//Set depth stencil state
m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);
//Initialize depth stencil view
ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
//Setup depth stencil view
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
//Create depth stencil view
result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
if (FAILED(result)){
return false;
}
//Bind render target view and depth stencil buffer to output render pipeline
m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);
//Setup raster desc(determines how polygons are rendered)
rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = true;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.FrontCounterClockwise = false;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;
//Create raster state
result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
if (FAILED(result)){
return false;
}
//Set raster state
m_deviceContext->RSSetState(m_rasterState);
//Setup viewport for rendering
viewport.Width = (float)screenWidth;
viewport.Height = (float)screenHeight;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
//Create viewport
m_deviceContext->RSSetViewports(1, &viewport);
//Setup projection matrix
fieldOfView = (float)D3DX_PI / 4.0f;
screenAspect = (float)screenWidth / (float)screenHeight;
//Create projecttion matrix for 3d rendering
D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth);
//Initialize world matrix to identity matrix
D3DXMatrixIdentity(&m_worldMatrix);
//Create Orthographic projection matrix for 2D rendering
D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, screenNear, screenDepth);
return true;
}
void D3DClass::Shutdown(){
//Set to windowed
if (m_swapChain){
m_swapChain->GetFullscreenState(false, NULL);
}
if (m_rasterState){
m_rasterState->Release();
m_rasterState = 0;
}
if (m_depthStencilBuffer){
m_depthStencilBuffer->Release();
m_depthStencilBuffer = 0;
}
if (m_depthStencilState){
m_depthStencilState->Release();
m_depthStencilState = 0;
}
if (m_depthStencilView){
m_depthStencilView->Release();
m_depthStencilView = 0;
}
if (m_deviceContext){
m_deviceContext->Release();
m_deviceContext = 0;
}
if (m_swapChain){
m_swapChain->Release();
m_swapChain = 0;
}
return;
}
void D3DClass::BeginScene(float red, float blue, float green, float alpha){
float color[4];
//Setup colors
color[0] = red;
color[1] = green;
color[2] = blue;
color[3] = alpha;
//Clear back buffer
m_deviceContext->ClearRenderTargetView(m_renderTargetView, color);
//Clear depth buffer
m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_STENCIL, 1.0f, 0);
return;
}
void D3DClass::EndScene(){
//Present back buffer to screen
if (m_vsync_enabled){
//Lock to screen refresh rate
m_swapChain->Present(1, 0);
}
else{
//Present as fast as possible
m_swapChain->Present(0, 0);
}
return;
}
//Helper functions
ID3D11Device* D3DClass::GetDevice(){
return m_device;
}
ID3D11DeviceContext* D3DClass::GetDeviceContext(){
return m_deviceContext;
}
void D3DClass::GetProjectionMatrix(D3DXMATRIX& projectionMatrix){
m_projectionMatrix = projectionMatrix;
return;
}
void D3DClass::GetWorldMatrix(D3DXMATRIX& worldMatrix){
m_worldMatrix = worldMatrix;
return;
}
void D3DClass::GetOrthoMatrix(D3DXMATRIX& orthoMatrix){
m_orthoMatrix = orthoMatrix;
return;
}
void D3DClass::GetVideoCardInfo(char* cardName, int& memory){
strcpy_s(cardName, 128, m_videoCardDescription);
memory = m_videoCardMemory;
return;
}
Either change the type of stringLength to size_t or pass NULL as as the first argument to wcstombs_s instead.
I cannot get my program to correctly choose which models to place in front. I have followed the MSDN code exactly. My code appears to correctly draw all polygons in a particular call of DrawIndexed, but each subsequent call seems to cause models to be drawn in the order they are drawn, not based on whether they are closer to the screen.
Here is my code for initializing Direct3d:
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory( &sd, sizeof( sd ) );
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 4;
sd.SampleDesc.Quality = 0;
sd.Windowed = !fullScreen;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
D3D_FEATURE_LEVEL FeatureLevelsRequested = D3D_FEATURE_LEVEL_11_0;
UINT numFeatureLevelsRequested = 1;
D3D_FEATURE_LEVEL FeatureLevelsSupported;
HRESULT hr;
if( FAILED (hr = D3D11CreateDeviceAndSwapChain( adapters[0],
D3D_DRIVER_TYPE_UNKNOWN,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&sd,
&swapchain,
&dev,
&FeatureLevelsSupported,
&devcon )))
{
//return;
}
ID3D11Texture2D *pBack = NULL;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBack);
// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBack, NULL, &backbuffer);
pBack->Release();
// set the render target as the back buffer
// Create depth stencil texture
D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format =DXGI_FORMAT_D24_UNORM_S8_UINT;
descDepth.SampleDesc.Count = 4;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = dev->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil);
if(FAILED(hr))
exit(hr);
// Create the depth stencil view
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory(&descDSV, sizeof(descDSV));
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
descDSV.Texture2D.MipSlice = 0;;
//descDSV.Texture2DMS.UnusedField_NothingToDefine = 0;
hr = dev->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView);
if(FAILED(hr))
exit(hr);
devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = width;
viewport.Height = height;
devcon->RSSetViewports(1, &viewport);
This is my code for rendering:
void Direct3DRenderer::Render()
{
devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));
devcon->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0 );
camera.location = simulation->GetWorld()->GetCameraCoordinates();
camera.direction = simulation->GetWorld()->GetCameraLookAt();
//camera.up = simulation->GetWorld()->GetCameraOrientation();
Vec3d lookAt = camera.location + camera.direction;
XMVECTOR eye = XMVectorSet((float)camera.location[0], (float)camera.location[1], (float)camera.location[2], 0.f);
XMVECTOR look = XMVectorSet(lookAt[0], lookAt[1], lookAt[2], 0);
XMVECTOR up = XMVectorSet(camera.up[0], camera.up[1], camera.up[2], 0);
g_View = XMMatrixLookAtLH(eye, look, up);
ConstantBuffer oncePerFrame;
oncePerFrame.matrix = XMMatrixTranspose(g_View);
devcon->UpdateSubresource(oncePerFrameBuffer, 0, NULL, &oncePerFrame, 0, 0);
UINT stride = sizeof(VERTEX);
UINT offset = 0;
const std::vector<Graphical*> graphicalList = simulation->GetWorld()->GetGraphicalList();
for(int ind = 0; ind < graphicalList.size(); ++ind)
{
switch(graphicalList[ind]->GetModelType())
{
case 1: //Sphere
{
ConstantBuffer oncePerModel2;
oncePerModel2.matrix = XMMatrixTranspose(XMMatrixScalingFromVector(graphicalList[ind]->GetScaleX()) * XMMatrixTranslationFromVector(graphicalList[ind]->GetTranslationX()));
devcon->UpdateSubresource(oncePerModelBuffer, 0, NULL, &oncePerModel2, 0, 0);
devcon->IASetVertexBuffers(0, 1, &(sphereModel.vertexBuffer), &stride, &offset);
devcon->IASetIndexBuffer(sphereModel.indexBuffer, DXGI_FORMAT_R32_UINT, 0);
devcon->DrawIndexed(sphereModel.indexCount, 0, 0);
}
break;
}
}
ConstantBuffer oncePerModel;
oncePerModel.matrix = XMMatrixTranspose(g_World);
devcon->UpdateSubresource(oncePerModelBuffer, 0, NULL, &oncePerModel, 0, 0);
devcon->IASetVertexBuffers(0, 1, &terrainModel.vertexBuffer, &stride, &offset);
devcon->IASetIndexBuffer(terrainModel.indexBuffer, DXGI_FORMAT_R32_UINT, 0);
devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
devcon->DrawIndexed(terrainModel.indexCount, 0, 0);
swapchain->Present(0, 0);
}
I have tried searching extensively, and have followed every tutorial I could find. Nothing fixes it.
In the case of the spheres, depth appears to be correct if viewing from one side, but not the other.
Any help would be appreciated. Thanks.
From OP comment:
The problem ended up being much simpler. I did not set the minimum and
max depth for the viewport object. It worked once I did so.
I had the same problem, it works now:
D3D11_VIEWPORT screenViewport;
/* ... */
screenViewport.MinDepth = 0;
screenViewport.MaxDepth = 1;
/* ... */
context->RSSetViewports(1, &screenViewport);
There are three key steps to Z-Buffering.
Setting the Appropriate Presentation Parameters
Turning On Z-Buffering
Clearing the Z-Buffer
1) Setting the Appropriate Presentation Parameters
D3DPRESENT_PARAMETERS d3dpp;
//...
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
EnableAutoDepthStencil
In truth, z-buffering can be complex. Setting this value to TRUE tells Direct3D to automatically create the z-buffer and set it up in a way used most often. There are, of course, uses for the complex method, but we'll stick to simple for now. We'll cover ways the complex method can be useful later in the tutorial.
AutoDepthStencilFormat
This is the format for each pixel in the z-buffer. We don't use the regular pixel format defined in the Presentation Parameters. Instead, we use a special format for z-buffers. This format is D3DFMT_D16. This means that each pixel is 16-bit. There are other formats, but we will not need them for the extent of this tutorial.
2) Turning On Z-Buffering
// d3ddev is your Direct3D device - a variable of type LPDIRECT3DDEVICE9
d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
3) Clearing the Z-Buffer
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
By the way this works in DirectX 9.0c. Im not sure if it is compatible with DirectX 11.
Had a similar problem in DirectX10, seems it was initialisation code, I am not sure about the CreateDevice and SwapChain against UNKNOWN driver type, as I have not used that before.
There are a few differences I can see, the Stencil buffer does not specify the operations to perform depth stencil tests against. (Unless this has been specified in the HLSL which is not visible here)
eg:
// Stencil test parameters
dsDesc.StencilEnable = true;
dsDesc.StencilReadMask = 0xFF;
dsDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing
dsDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
dsDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing
dsDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
dsDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
In any event, here is a working DirectX10 example, I am pretty sure you can adapt it quickly for DirectX11.
logger->debug("initD3D: Calling D3D10CreateDeviceAndSwapChain.\n");
SYSTEMTIME sysTime;
GetSystemTime(&sysTime);
srand((unsigned int)sysTime.wMilliseconds);
logger->debug("in initD3D.\n");
shutdownXX = false;
count = 1;
quality = 0;
//Create the back buffer desc.
ZeroMemory(&swapDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapDesc.BufferCount = 1;
swapDesc.BufferDesc.Width = width;
swapDesc.BufferDesc.Height = height;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapDesc.BufferDesc.RefreshRate.Numerator = 60;
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapDesc.OutputWindow = hwnd;
swapDesc.SampleDesc.Count = count;
swapDesc.SampleDesc.Quality = quality;
swapDesc.Windowed = FALSE;
swapDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
//Create the device.
HRESULT hr = D3D10CreateDeviceAndSwapChain(
NULL,
D3D10_DRIVER_TYPE_HARDWARE,
NULL,
0,
D3D10_SDK_VERSION,
&swapDesc,
&swapChain,
&device);
if (!chk(hr, TEXT("Could not create D3D Device D3D10CreateDeviceAndSwapChain failed.")))
return false;
ID3D10Texture2D *buffer;
logger->debug("initD3D: Calling swapChain->GetBuffer.\n");
hr = swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*) &buffer);
if (!chk(hr, TEXT("Could not create D3D Device: swapChain->GetBuffer failed.")))
return false;
D3D10_TEXTURE2D_DESC BBDesc;
ZeroMemory(&BBDesc, sizeof(D3D10_TEXTURE2D_DESC));
buffer->GetDesc( &BBDesc );
D3D10_RENDER_TARGET_VIEW_DESC RTVDesc;
ZeroMemory(&RTVDesc, sizeof(D3D10_RENDER_TARGET_VIEW_DESC));
RTVDesc.Format = BBDesc.Format;
//RTVDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
RTVDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DMS;
RTVDesc.Texture2D.MipSlice = 0;
logger->debug("initD3D: Calling device->CreateRenderTargetView.\n");
hr = device->CreateRenderTargetView(buffer, &RTVDesc, &renderTView);
buffer->Release();
if (!chk(hr, TEXT("Could not create D3D Device: device->CreateRenderTargetView failed.")))
return false;
ZeroMemory(&descDepth, sizeof(D3D10_TEXTURE2D_DESC));
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
//descDepth.Format = DXGI_FORMAT_D32_FLOAT;
descDepth.SampleDesc.Count = count;
descDepth.SampleDesc.Quality = quality;
descDepth.Usage = D3D10_USAGE_DEFAULT;
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = device->CreateTexture2D(&descDepth, NULL, &stencil);
if (!chk(hr, TEXT("device->device->CreateTexture2D Failed\n")))
return false;
// Depth test parameters
dsDesc.DepthEnable = true;
dsDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc = D3D10_COMPARISON_LESS;
// Stencil test parameters
dsDesc.StencilEnable = true;
dsDesc.StencilReadMask = 0xFF;
dsDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing
dsDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
dsDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing
dsDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
dsDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
hr = device->CreateDepthStencilState(&dsDesc, &pDSState);
if (!chk(hr, TEXT("device->device->CreateDepthStencilState Failed\n")))
return false;
device->OMSetDepthStencilState(pDSState, 1);
ZeroMemory(&descDSV, sizeof(D3D10_DEPTH_STENCIL_VIEW_DESC));
descDSV.Format = descDepth.Format;
//descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2DMS;
descDSV.Texture2D.MipSlice = 0;
hr = device->CreateDepthStencilView(stencil, &descDSV, &depthStencil);
if (!chk(hr, TEXT("device->device->CreateDepthStencilView Failed\n")))
return false;
device->OMSetRenderTargets(1, &renderTView, depthStencil);
resizeD3D10Window(width, height);
return true;