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:
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 trying to render a model in OBJ file format with DirectX. I'm using simple cube model, but I get some really strange results(picture below)
I've tried to render a cube by filling vertecies array manually and it worked pretty good. After studing OBJ file format I've thougth that I should do the similar thing, but I don't understand why this is not working.
Sending two functions and structs descriptions:
initGeometry
In this function I set up my geometry, shaders and read information from file. I think that I do something wrong at the end of this function, because I didn't change shaders part and initializations part, only added new way to fill up a vertex array
render
This function didn't changed at all from my first version, where I filled up a vertecies array mannualy.
Structs
Just some structs descriptions.
HRESULT RenderDevice::initGeometry() {
///////READING INFO FROM FILE//////////
ifstream *inp = new ifstream("test.obj");
ofstream *out = new ofstream("result.txt");
char str[256];
while (!inp->eof()) {
inp->getline(str, 256);
meshInfo.coord.push_back(new std::string(str));
}
HRESULT hr = S_OK;
ID3DBlob *pVSBlob = NULL;
hr = compileShaderFromFile(L"texture.fx", "VS", "vs_4_0", &pVSBlob);
if (FAILED(hr)) {
MessageBox(NULL, L"Can't compile Vertex Shader", L"Error", MB_OK);
return hr;
}
hr = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader);
if (FAILED(hr)) {
pVSBlob->Release();
return hr;
}
D3D11_INPUT_ELEMENT_DESC layout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
UINT numElemenets = ARRAYSIZE(layout);
hr = g_pd3dDevice->CreateInputLayout(layout, numElemenets, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &g_pVertexLayout);
pVSBlob->Release();
if (FAILED(hr)) {
return hr;
}
g_pImmediateContext->IASetInputLayout(g_pVertexLayout);
ID3DBlob *pPSBlob = NULL;
hr = compileShaderFromFile(L"texture.fx", "PS", "ps_4_0", &pPSBlob);
if (FAILED(hr)) {
MessageBox(NULL, L"Can't compile Pixel Shader", L"Error", MB_OK);
return hr;
}
hr = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader);
pPSBlob->Release();
if (FAILED(hr)) {
return hr;
}
pPSBlob = NULL;
hr = compileShaderFromFile(L"texture.fx", "PSSolid", "ps_4_0", &pPSBlob);
if (FAILED(hr)) {
MessageBox(NULL, L"Can't compile Solid Pixel Shader", L"Error", MB_OK);
return hr;
}
hr = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShaderSolid);
pPSBlob->Release();
if (FAILED(hr)) {
return hr;
}
/////////SPLITING INFO INTO DIFFERENT VECTORS/////////////////
for (int i = 0; i < meshInfo.coord.size(); i++) {
if (meshInfo.coord[i]->c_str()[0] == 'v' && meshInfo.coord[i]->c_str()[1] != 'n') {
float tmpx, tmpy, tmpz;
sscanf_s(meshInfo.coord[i]->c_str(), "v %f %f %f", &tmpx, &tmpy, &tmpz);
meshInfo.positions.push_back(XMFLOAT3(tmpx, tmpy, tmpz));
} else if (meshInfo.coord[i]->c_str()[0] == 'v' && meshInfo.coord[i]->c_str()[1] == 'n') {
float tmpx, tmpy, tmpz;
sscanf_s(meshInfo.coord[i]->c_str(), "vn %f %f %f", &tmpx, &tmpy, &tmpz);
meshInfo.normals.push_back(XMFLOAT3(tmpx, tmpy, tmpz));
} else if (meshInfo.coord[i]->c_str()[0] == 'f') {
int iX, iY, iZ, nX, nY, nZ;
sscanf_s(meshInfo.coord[i]->c_str(), "f %d//%d %d//%d %d//%d", &iX, &nX, &iY, &nY, &iZ, &nZ);
meshInfo.indexiesPoints.push_back(iX);
meshInfo.indexiesPoints.push_back(iY);
meshInfo.indexiesPoints.push_back(iZ);
meshInfo.indexiesNormals.push_back(nX);
meshInfo.indexiesNormals.push_back(nY);
meshInfo.indexiesNormals.push_back(nZ);
}
}
meshInfo.indexiesAmount = meshInfo.indexiesPoints.size();
meshInfo.vertexAmount = meshInfo.positions.size();
meshInfo.normalsAmount = meshInfo.normals.size();
Vertex *vertices = new Vertex[meshInfo.indexiesAmount];
//////////////FILLING VERTECIES ARRAY///////////////
for (int i = 0; i < meshInfo.indexiesAmount; i++) {
vertices[i].normal.x = meshInfo.normals[meshInfo.indexiesNormals[i] - 1].x;
vertices[i].normal.y = meshInfo.normals[meshInfo.indexiesNormals[i] - 1].y;
vertices[i].normal.z = meshInfo.normals[meshInfo.indexiesNormals[i] - 1].z;
vertices[i].pos.x = meshInfo.positions[meshInfo.indexiesPoints[i] - 1].x;
vertices[i].pos.y = meshInfo.positions[meshInfo.indexiesPoints[i] - 1].y;
vertices[i].pos.z = meshInfo.positions[meshInfo.indexiesPoints[i] - 1].z;
}
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(Vertex) * meshInfo.indexiesAmount;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA initData;
ZeroMemory(&initData, sizeof(initData));
initData.pSysMem = vertices;
hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBuffer);
if (FAILED(hr)) {
return hr;
}
///////////////////FILLING INIXIES ARRAY///////////////////
WORD *indixies = new WORD[meshInfo.indexiesAmount];
for (int i = 0; i < meshInfo.indexiesAmount; i++) {
indixies[i] = meshInfo.indexiesPoints[i];
}
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(int) * meshInfo.indexiesAmount;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
initData.pSysMem = indixies;
hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pIndexBuffer);
if (FAILED(hr)) {
return hr;
}
UINT stride = sizeof(Vertex);
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);
g_pImmediateContext->IASetIndexBuffer(g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(ConstantBuffer);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
hr = g_pd3dDevice->CreateBuffer(&bd, NULL, &g_pCBMatrixes);
if (FAILED(hr)) {
return hr;
}
return S_OK;
}
void RenderDevice::render() {
float clearColor[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, clearColor);
g_pImmediateContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
updateLigth();
for (int i = 0; i < 6; i++) {
updateMatrix(MX_SETWORLD, i * (XM_PI * 2) / 6);
g_pImmediateContext->VSSetShader(g_pVertexShader, NULL, 0);
g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pCBMatrixes);
g_pImmediateContext->VSSetConstantBuffers(1, 1, &g_pCBLigth);
g_pImmediateContext->PSSetConstantBuffers(0, 1, &g_pCBMatrixes);
g_pImmediateContext->PSSetConstantBuffers(1, 1, &g_pCBLigth);
g_pImmediateContext->PSSetShader(g_pPixelShader, NULL, 0);
g_pImmediateContext->DrawIndexed(meshInfo.indexiesAmount, 0, 0);
}
g_pImmediateContext->PSSetShader(g_pPixelShaderSolid, NULL, 0);
for (int m = 0; m < 2; m++) {
updateMatrix(m, 0);
g_pImmediateContext->DrawIndexed(meshInfo.indexiesAmount, 0, 0);
}
g_pSwapChain->Present(0, 0);
}
typedef struct Vertex {
XMFLOAT3 pos;
XMFLOAT3 normal;
}Vertex;
typedef struct MeshInfo {
int vertexAmount;
int normalsAmount;
vector<XMFLOAT3> positions;
vector<XMFLOAT3> normals;
vector<string*> coord;
vector<int> indexiesPoints;
vector<int> indexiesNormals;
int indexiesAmount;
}MeshInfo;
typedef struct ConstantBuffer {
XMMATRIX mWorld;
XMMATRIX mView;
XMMATRIX mProjection;
XMFLOAT4 vLigthDir[2];
XMFLOAT4 vLigthColor[2];
XMFLOAT4 vOutputColor;
}ConstantBuffer;
I expect to see 6 cubes in my program's window,
but I get this thing
OBJ file format stores indices using one-based numbering (first vertex index is 1) Wavefron Obg file format. DirectX uses zero-based numbering (first vertex index is 0, same as C, C++).
So you should convert indices values to use them. You can do it like this:
for (int i = 0; i < meshInfo.indexiesAmount; i++) {
indixies[i] = meshInfo.indexiesPoints[i] - 1;
}
I've actually found a solution to my problem. The main problem was to make a correct order for vertecies to draw. But in .OBJ files only UNIQUE vertices, normals and texture coordinates are written. Also they are separated from each other (for example it can be 8 UNIQUE vertex coordinates and 6 UNIQUE normals coordinates). The main thing is happening in part, where are faces are described. Each face is pointing to a specific index of position, normal and texture coordinate, meaning that we can use same normals, positions and texture coordinates different times(I know it's obviously). And I realised that in my realisation I don't need indexies array at all, because Vertecies array, that I've filled up was already a model! And I ended up using method Draw instead of DrawIndexed in ID3D11DeviceContext.
I've been debugging this for about a day now and everything seems okay. Im trying to get a simple tringle to render, but nothing is showing up. I have a Pixel Shader and a Vertex Shader which is compiling okay.
I will supply all of the code, any help would be greatly appreciated.
Main C++ File:
#include <windows.h>
#include <D3D11_1.h>
static int ScreenWidth = 1280;
static int ScreenHeight = 720;
static bool GlobalRunning;
static ID3D11Device *Device;
static ID3D11DeviceContext *DeviceContext;
static IDXGISwapChain1 *SwapChain;
static ID3D11RenderTargetView *RenderTargetView;
#define Assert(Expression) if(!(Expression)) { *(int *)0 = 0;}
struct vec3
{
float X;
float Y;
float Z;
};
struct vec4
{
float X;
float Y;
float Z;
float W;
};
struct vertex
{
vec3 Position;
vec4 Color;
};
static int
SafeTruncateUInt64(LONG Value)
{
Assert(Value <= 0xFFFFFFFF);
int Result = (int)Value;
return(Result);
}
struct read_file_result
{
void *Contents;
int ContentsSize;
};
static read_file_result
Win32LoadEntireFile(char *Filename)
{
read_file_result Result = {};
HANDLE File = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(File != INVALID_HANDLE_VALUE)
{
LARGE_INTEGER FileSize;
if(GetFileSizeEx(File, &FileSize))
{
int FileSize32 = SafeTruncateUInt64(FileSize.QuadPart);
Result.Contents = VirtualAlloc(0, FileSize32, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
if(Result.Contents)
{
DWORD BytesRead;
if(ReadFile(File, Result.Contents, FileSize32, &BytesRead, 0) && BytesRead == FileSize32)
{
Result.ContentsSize = FileSize32;
}
else
{
// TODO(zak): Logging
}
}
else
{
// TODO(zak): Logging
}
}
else
{
// TODO(zak): Logging
}
}
else
{
// TODO(zak): Logging
}
return(Result);
}
static LRESULT CALLBACK
Win32MainWindowCallback(HWND Window,
UINT Message,
WPARAM WParam,
LPARAM LParam)
{
LRESULT Result = 0;
switch(Message)
{
case WM_ACTIVATEAPP:
{
// TODO(zak): Handle this
} break;
case WM_SIZE:
{
ScreenWidth = LOWORD(LParam);
ScreenHeight = HIWORD(LParam);
RenderTargetView->Release();
SwapChain->ResizeBuffers(0, ScreenWidth, ScreenHeight, DXGI_FORMAT_UNKNOWN, 0);
ID3D11Texture2D *BackBuffer;
if(SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&BackBuffer) == S_OK)
{
Device->CreateRenderTargetView(BackBuffer, 0, &RenderTargetView);
BackBuffer->Release();
}
} break;
case WM_QUIT:
{
GlobalRunning = false;
} break;
case WM_DESTROY:
{
GlobalRunning = false;
} break;
default:
{
Result = DefWindowProcA(Window, Message, WParam, LParam);
}
}
return(Result);
}
int CALLBACK
WinMain(HINSTANCE Instance,
HINSTANCE PrevInstance,
LPSTR CommandLine,
int ShowCode)
{
WNDCLASSA WindowClass = {};
WindowClass.style = CS_HREDRAW|CS_VREDRAW;
WindowClass.lpfnWndProc = Win32MainWindowCallback;
WindowClass.hInstance = Instance;
WindowClass.lpszClassName = "DXPlaygroundWindowClass";
if(RegisterClassA(&WindowClass))
{
RECT WindowRect;
WindowRect.top = 0;
WindowRect.bottom = ScreenHeight;
WindowRect.left = 0;
WindowRect.right = ScreenWidth;
AdjustWindowRect(&WindowRect, WS_OVERLAPPEDWINDOW, 0);
HWND Window =
CreateWindowExA(0,
WindowClass.lpszClassName,
"D3D Playground",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
0, 0, Instance, 0);
if(Window)
{
D3D_FEATURE_LEVEL FeatureLevelsRequested[3]
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
D3D_FEATURE_LEVEL FeatureLevelReturned;
if(D3D11CreateDevice(0,
D3D_DRIVER_TYPE_HARDWARE,
0,
0,
FeatureLevelsRequested,
3,
D3D11_SDK_VERSION,
&Device,
&FeatureLevelReturned,
&DeviceContext) == S_OK)
{
IDXGIFactory2 *Factory;
if(CreateDXGIFactory(__uuidof(IDXGIFactory2), (void **)&Factory) == S_OK)
{
DXGI_SWAP_CHAIN_DESC1 SwapChainDescription = {};
SwapChainDescription.Width = ScreenWidth;
SwapChainDescription.Height = ScreenHeight;
SwapChainDescription.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
DXGI_SAMPLE_DESC SampleDescription = {};
SampleDescription.Count = 1;
SampleDescription.Quality = 0;
SwapChainDescription.SampleDesc = SampleDescription;
SwapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDescription.BufferCount = 2;
SwapChainDescription.Scaling = DXGI_SCALING_STRETCH;
SwapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
if(Factory->CreateSwapChainForHwnd(Device, Window,
&SwapChainDescription,
0, 0, &SwapChain) == S_OK)
{
ID3D11Texture2D *BackBuffer;
if(SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
(void **)&BackBuffer) == S_OK)
{
Device->CreateRenderTargetView(BackBuffer, 0, &RenderTargetView);
BackBuffer->Release();
}
ShowWindow(Window, SW_SHOWNORMAL);
read_file_result VertexShaderFile = Win32LoadEntireFile("shaders/testvertex.fxo");
read_file_result PixelShaderFile = Win32LoadEntireFile("shaders/testpixel.fxo");
ID3D11VertexShader *VertexShader;
ID3D11PixelShader *PixelShader;
Device->CreateVertexShader(VertexShaderFile.Contents,
VertexShaderFile.ContentsSize, 0, &VertexShader);
Device->CreatePixelShader(PixelShaderFile.Contents,
PixelShaderFile.ContentsSize, 0, &PixelShader);
DeviceContext->VSSetShader(VertexShader, 0, 0);
DeviceContext->PSSetShader(PixelShader, 0, 0);
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
ID3D11InputLayout *Layout;
Device->CreateInputLayout(ied, 2, VertexShaderFile.Contents, VertexShaderFile.ContentsSize, &Layout);
DeviceContext->IASetInputLayout(Layout);
vertex OurVerticies[3] = {};
OurVerticies[0].Position.Y = 0.5f;
OurVerticies[0].Color.X = 1.0f;
OurVerticies[0].Color.W = 1.0f;
OurVerticies[1].Position.X = 0.45f;
OurVerticies[1].Position.Y = -0.5f;
OurVerticies[1].Color.Y = 1.0f;
OurVerticies[1].Color.W = 1.0f;
OurVerticies[2].Position.X = -0.45f;
OurVerticies[2].Position.Y = -0.5f;
OurVerticies[2].Color.Z = 1.0f;
OurVerticies[2].Color.W = 1.0f;
ID3D11Buffer *VertexBuffer = 0;
D3D11_BUFFER_DESC BufferDescription = {};
BufferDescription.Usage = D3D11_USAGE_DYNAMIC;
BufferDescription.ByteWidth = sizeof(vertex) * 3;
BufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;
BufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
Device->CreateBuffer(&BufferDescription, 0, &VertexBuffer);
D3D11_MAPPED_SUBRESOURCE MappedSubresource;
DeviceContext->Map(VertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedSubresource);
CopyMemory(MappedSubresource.pData, OurVerticies, sizeof(OurVerticies));
DeviceContext->Unmap(VertexBuffer, 0);
GlobalRunning = true;
while(GlobalRunning)
{
MSG Message;
while(PeekMessageA(&Message, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessageA(&Message);
}
FLOAT ClearColor[] = {0.0f, 0.0f, 1.0f, 1.0f};
DeviceContext->ClearRenderTargetView(RenderTargetView, ClearColor);
DeviceContext->OMSetRenderTargets(1, &RenderTargetView, 0);
UINT Stride = sizeof(vertex);
UINT Offset = 0;
DeviceContext->IASetVertexBuffers(0, 1, &VertexBuffer, &Stride, &Offset);
DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
DeviceContext->Draw(3, 0);
SwapChain->Present(1, 0);
}
}
else
{
// TODO(zak): Logging
}
}
else
{
// TODO(zak): Logging
}
}
else
{
// TODO(zak): Logging
}
}
else
{
// TODO(zak): Logging
}
}
else
{
// TODO(zak): Logging
}
return(0);
}
Pixel Shader
float4 main(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}
Vertex Shader
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VOut main(float4 position : POSITION, float4 color : COLOR)
{
VOut output;
output.position = position;
output.color = color;
return output;
}
The code you've posted is missing error checking of the HRESULT on most of the Direct3D calls. If a COM call returns a void you don't have to handle the error, otherwise you do. You can do this with the SUCCEEDED macro, the FAILED macro, or with the ThrowIfFailed helper. I'd bet at least one of your calls is failing and you don't notice because you aren't checking for a failure result.
Second, you should enable the Debug device by passing D3D11_CREATE_DEVICE_DEBUG as the 4th parameter. Then look for ERROR or CORRUPTION messages in your debug output. See this post.
Not sure where you got your original "hello world" tutorial, but you should take a look at the Direct3D Game VS Templates and the DirectX Tool Kit.
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 found this tutorial, i follow it and i create the class DirectX
class DirectX
{
private:
D3D_DRIVER_TYPE DriverType;
D3D_FEATURE_LEVEL FeatureLevel;
public:
int InitDirectX(HWND &hwnd, WinDesc &wd)
{
HRESULT result;
RECT dimensions;
GetClientRect( hwnd, &dimensions );
int width=dimensions.right-dimensions.left;
int height=dimensions.bottom-dimensions.top;
D3D_DRIVER_TYPE driverTypes[]=
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_SOFTWARE
};
unsigned int totalDriverTypes=ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels[]=
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0
};
unsigned int totalFeatureLevels = ARRAYSIZE( featureLevels );
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc,sizeof(swapChainDesc));
swapChainDesc.BufferCount=1;
swapChainDesc.BufferDesc.Width=width;
swapChainDesc.BufferDesc.Height=height;
swapChainDesc.BufferDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator=60;
swapChainDesc.BufferDesc.RefreshRate.Denominator=1;
swapChainDesc.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow=hwnd;
swapChainDesc.Windowed=1;
swapChainDesc.SampleDesc.Count=1;
swapChainDesc.SampleDesc.Quality=0;
for(int driver=0;driver<totalDriverTypes;++driver)
{
result = D3D11CreateDeviceAndSwapChain( 0, driverTypes[driver], 0,
0, featureLevels, totalFeatureLevels,
D3D11_SDK_VERSION, &swapChainDesc, &SwapChain,
&Device, &FeatureLevel, &Context );
if( SUCCEEDED( result ) )
{
D3D_DRIVER_TYPE driverType_ = driverTypes[driver];
break;
}
}
}
D3D11_TEXTURE2D_DESC textureDesc;
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
result=Device->CreateTexture2D(&textureDesc, NULL, &backBuffer);
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
result=Device->CreateRenderTargetView(backBuffer, &renderTargetViewDesc, &RenderTargetView);
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
result=Device->CreateShaderResourceView(backBuffer, &shaderResourceViewDesc, &shaderResourceView);
float color[4]={1,1,0,0};
Context->ClearRenderTargetView(RenderTargetView,color);
Context->OMSetRenderTargets(1,&RenderTargetView,0);
}
};
When i run it it get no error put when i call SwapChain->Present(0,0) nothing is displayed althought the renderTargetView should to be yellow.
Why?? I cannot found the error.
PS if i create a renderTargetView with this code:
ID3D11Texture2D* backBufferTexture;
result = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ),
( LPVOID* )&backBufferTexture );
result = Device->CreateRenderTargetView( backBufferTexture, 0,
&RenderTargetView );
all works;
and in my code i check all the "result" values;
2°
this is code of the sprite i want render:
Init()//init vertex buffer, index buffer, texture, matrix....
the render functioon is this:
C->OMSetRenderTargets(1,&RT1,0);
C->Update(...)// matrix to sent vertex shader, set texture, vertex, buffer....
C->Draw(6,0)//draw the sprite;
It should render a sprite(ex. a ball) on RT1 then :
C->OMSetRenderTargets(1,&RT,0);
RT1->Update() //like the texture;
RT1->Draw(6,0)
...
Swapchain->present(1,0);
The RT1 is displayed(ex. if i have clear it with blue there is a blue shape on the screen i can translate, scale and rotate) but not the ball(i have render on RT1);
but if i render the ball without set RT1 as renderTargetView the ball is correct displayed