Jump to content
  • Advertisement
Sign in to follow this  
Lee_Hillvith

DX11 D3D11DepthStencil doesn't work properly

This topic is 2106 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Greetings
Hello, guys, recently I 've got my hand on D3D11, so my question maybe a little Idiotic,but I am going to ask anyway :P
This program renders two cubes, one of them rotates around the central one, you know, basic stuff.
It's works fine except a depth problem which is when the rotating cube should not be rendered when it is "behind" the central cube, however, it was rendered.
I've double checked the depthstencil buffer code, but haven't seen where is gone wrong.
So maybe some nice person can help me out?

Any answer would be greatly appreciated. And here is my code
[source lang="cpp"] #include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <xnamath.h>

// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define PI 3.14f

struct VERTEX{
FLOAT X, Y, Z;
D3DXCOLOR Color;
};

//new type, updating constant buffer in shader in runtime
struct cbPerObject
{
XMMATRIX WVP;
};
cbPerObject cbPerObj;

// global declarations
IDXGISwapChain *swapchain; // the pointer to the swap chain interface
ID3D11Device *dev; // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon; // the pointer to our Direct3D device context

ID3D11RenderTargetView *backbuffer; //globel declaration *2
// function prototypes
void InitD3D(HWND hWnd); // sets up and initializes Direct3D
void CleanD3D(void); // closes Direct3D and releases memory
void RenderFrame(void);
void InitPipeline(void); // Initialize the rendering pipeline
void InitGraphics(void);//Initialize the graphic stuff
void InitDepthStencil(void);//Initialize the depth stencil buffer
void InitCamera(void);// Initialize camera
void Update(void);// The scene update function

//Using Shader
ID3D11VertexShader *pVS;
ID3D11PixelShader *pPS;

//Shader buffer
ID3D11Buffer *pVertexBuffer;
//Indices buffer
ID3D11Buffer *pIndexBuffer;

//Input Layout
ID3D11InputLayout *pLayout;

//Depthstencilbuffer
ID3D11DepthStencilView* pDepthStencilView;
ID3D11Texture2D* pDepthStencilBuffer;

//Camera stuff
ID3D11Buffer* cbPerObjectBuffer;

XMMATRIX WVP;
XMMATRIX World;
XMMATRIX View;
XMMATRIX Projection;

XMVECTOR CameraPosition;
XMVECTOR CameraTarget;
XMVECTOR CameraUp;

//Transformation stuff
XMMATRIX CubeOne;
XMMATRIX CubeTwo;

XMMATRIX Translate;
XMMATRIX Rotate;
XMMATRIX Scale;

float rot = 0.01f;


// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;

ZeroMemory(&wc, sizeof(WNDCLASSEX));

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
//wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass";

RegisterClassEx(&wc);

RECT wr = {0, 0,800, 600};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

hWnd = CreateWindowEx(NULL,
L"WindowClass",
L"D3DBasicWindow",
WS_OVERLAPPEDWINDOW,
SCREEN_HEIGHT,
SCREEN_WIDTH,
wr.right - wr.left,
wr.bottom - wr.top,
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hWnd, nCmdShow);

// set up and initialize Direct3D

InitD3D(hWnd);

// enter the main loop:

MSG msg;

while(TRUE)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);

if(msg.message == WM_QUIT)
break;
}
else
{
// Run game code here
Update();
RenderFrame();
// ...
// ...
}
}

// clean up DirectX and COM
CleanD3D();

return msg.wParam;
}


// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}

return DefWindowProc (hWnd, message, wParam, lParam);
}


// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;

// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
//Tell dx the screen resolution
scd.BufferDesc.Width = SCREEN_WIDTH; // set the back buffer width
scd.BufferDesc.Height = SCREEN_HEIGHT; // set the back buffer height
//Set DirectX to automatically switch when Alt-Enter is used.
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // allow full-screen switching

scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE; // windowed/full-screen mode

// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);

//get the address of backbuffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0,_uuidof(ID3D11Texture2D),(LPVOID*)&pBackBuffer);

//use the backbuffer to create the render target
dev->CreateRenderTargetView(pBackBuffer,NULL,&backbuffer);
pBackBuffer->Release();
devcon->OMSetRenderTargets(1,&backbuffer,pDepthStencilView);

//--Set the Viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport,sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.Height = SCREEN_HEIGHT;
viewport.Width = SCREEN_WIDTH;

devcon->RSSetViewports(1,&viewport);

InitDepthStencil();
InitPipeline();
InitGraphics();
InitCamera();

}

void InitPipeline(void)
{
//Load and compile shaders from file
ID3D10Blob *VS, *PS;
D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
D3DX11CompileFromFile(L"shaders.hlsl", 0, 0,"PShader","ps_5_0", 0 , 0, 0, &PS, 0, 0);
//Encapsulate shader into shader objects
dev->CreateVertexShader(VS->GetBufferPointer(),VS->GetBufferSize(), NULL, &pVS);
dev->CreatePixelShader(PS->GetBufferPointer(),PS->GetBufferSize(), NULL, &pPS);

//Set shader to be active
devcon->VSSetShader(pVS, 0, 0);
devcon->PSSetShader(pPS, 0, 0);

//Create the inputlayout
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},
};

dev->CreateInputLayout(ied,2,VS->GetBufferPointer(),VS->GetBufferSize(),&pLayout);
devcon->IASetInputLayout(pLayout);
}

void InitGraphics(void)
{
VERTEX CrossVertices[] =
{
{ -1.0f, -1.0f, -1.0f , D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},{ -1.0f, 1.0f, -1.0f, D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f) },{ 1.0f, 1.0f, -1.0f , D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},//ABC
{1.0f, -1.0f, -1.0f , D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)},{-1.0f, -1.0f, 1.0f , D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)}, { -1.0f, 1.0f, 1.0f, D3DXCOLOR(0.0f, 0.5f, 0.0f, 1.0f)},//DEF
{ 1.0f, 1.0f, 1.0f,D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f) },{+1.0f, -1.0f, 1.0f,D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)},//GH

};

// create the vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));

bd.Usage = D3D11_USAGE_DYNAMIC; // write access access by CPU and GPU
bd.ByteWidth = sizeof(VERTEX) * 36; // size is the VERTEX struct * 3
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // use as a vertex buffer
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // allow CPU to write in buffer

dev->CreateBuffer(&bd, NULL, &pVertexBuffer); // create the buffer


// copy the vertices into the buffer
D3D11_MAPPED_SUBRESOURCE ms;
devcon->Map(pVertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, CrossVertices, sizeof(CrossVertices)); // copy the data
devcon->Unmap(pVertexBuffer, NULL); // unmap the buffer

DWORD indices[ ] = {
// front face
0, 1, 2,
0, 2, 3,
// back face
4, 6, 5,
4, 7, 6,
// left face
4, 5, 1,
4, 1, 0,
// right face
3, 2, 6,
3, 6, 7,
// top face
1, 5, 6,
1, 6, 2,
// bottom face
4, 0, 3,
4, 3, 7
};
D3D11_BUFFER_DESC indexBufferDesc;
ZeroMemory( &indexBufferDesc, sizeof(indexBufferDesc) );

indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(DWORD) * 36;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA iinitData;

iinitData.pSysMem = indices;
dev->CreateBuffer(&indexBufferDesc, &iinitData, &pIndexBuffer);

devcon->IASetIndexBuffer( pIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

}

void InitDepthStencil(void)
{
D3D11_TEXTURE2D_DESC DepthStencilDesc;
DepthStencilDesc.Width = SCREEN_WIDTH;
DepthStencilDesc.Height = SCREEN_HEIGHT;
DepthStencilDesc.MipLevels = 1;
DepthStencilDesc.ArraySize = 1;
DepthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
DepthStencilDesc.SampleDesc.Count = 1;
DepthStencilDesc.SampleDesc.Quality = 0;
DepthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
DepthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
DepthStencilDesc.CPUAccessFlags = 0;
DepthStencilDesc.MiscFlags = 0;

//Create Depth Stencil View
dev->CreateTexture2D(&DepthStencilDesc,NULL,&pDepthStencilBuffer);
dev->CreateDepthStencilView(pDepthStencilBuffer, NULL, &pDepthStencilView);
devcon->OMSetRenderTargets(1,&backbuffer,pDepthStencilView);



}
void InitCamera(void)
{
D3D11_BUFFER_DESC cbbd;
ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC));
cbbd.Usage = D3D11_USAGE_DEFAULT;
cbbd.ByteWidth = sizeof(cbPerObject);
cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbbd.CPUAccessFlags = 0;
cbbd.MiscFlags = 0;

dev->CreateBuffer(&cbbd,NULL,&cbPerObjectBuffer);
CameraPosition = XMVectorSet(0.0f,0.0f,-5.0f,0.0f);
CameraTarget = XMVectorSet(0.0f,0.0f,0.0f,0.0f);
CameraUp = XMVectorSet(0.0f,1.0f,0.0f,0.0f);

View = XMMatrixLookAtLH(CameraPosition, CameraTarget,CameraUp);
//Set the Projection Matrix
Projection = XMMatrixPerspectiveFovLH(0.4f*PI, (float)SCREEN_WIDTH/SCREEN_HEIGHT,1.0f,1000.0f);

}

// this is the function that cleans up Direct3D and COM
void CleanD3D(void)
{
swapchain->SetFullscreenState(FALSE, NULL); // switch to windowed mode
// close and release all existing COM objects
swapchain->Release();
backbuffer->Release();
dev->Release();
devcon->Release();
//Release shader
pVS->Release();
pPS->Release();
//Release VertexBuffer
pVertexBuffer->Release();
pIndexBuffer->Release();
pLayout->Release();
//Release Depthstencil
pDepthStencilView->Release();
pDepthStencilBuffer->Release();
//Release contant buffer
cbPerObjectBuffer->Release();

}

void RenderFrame(void)
{
//clear the back buffer
devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f,0.2f,0.5f,1.0f));

//Do other 3D rendering here
// select which vertex buffer to display
UINT stride = sizeof(VERTEX);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset);
devcon->ClearDepthStencilView(pDepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
// select which primtive type we are using
devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);



WVP = CubeTwo * View * Projection;
cbPerObj.WVP = XMMatrixTranspose(WVP);
devcon->UpdateSubresource(cbPerObjectBuffer,0,NULL,&cbPerObj,0,0);
devcon->VSSetConstantBuffers(0,1,&cbPerObjectBuffer);

devcon->DrawIndexed(36,0,0);
WVP = CubeOne * View * Projection;
cbPerObj.WVP = XMMatrixTranspose(WVP);
devcon->UpdateSubresource(cbPerObjectBuffer,0,NULL,&cbPerObj,0,0);
devcon->VSSetConstantBuffers(0,1,&cbPerObjectBuffer);
devcon->DrawIndexed(36,0,0);

//Switch thee backbuffer and the front buffer
swapchain->Present(0,0);
}

void Update()
{

//Only rotates 2PI
rot+=0.001f;
if(rot>2*PI)
rot = 0.0f;
//Reset the cube one world matrix
CubeOne = XMMatrixIdentity();
XMVECTOR rotaxis = XMVectorSet(0.0f,1.0f,0.0f,0.0f);
Rotate = XMMatrixRotationAxis(rotaxis,rot);
Translate = XMMatrixTranslation(0.0f,0.0f,8.0f);
Scale = XMMatrixScaling(0.2f,0.2f,0.2f);
CubeOne = Translate * Rotate * Scale;
//Reset Cube two world matrix
CubeTwo = XMMatrixIdentity();
Rotate = XMMatrixRotationAxis(rotaxis,-rot);
Scale = XMMatrixScaling(0.5f,0.5f,0.5f);
CubeTwo = Rotate * Scale;
}[/source]

HLSL
[source lang="cpp"]cbuffer cbPerObject
{
float4x4 WVP;
};
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
VOut output;

output.position = mul(position,WVP);
output.color = color;

return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}[/source]

Share this post


Link to post
Share on other sites
Advertisement
Progress: I initialised the d3device in a wrond order:

It should be: InitWindow-SwapChain->renderTargetView->DepthStencil->ViewPort->CompileShader->Vertex and Indices->Camera

my wrong order: InitWindow-SwapChain->renderTargetView->ViewPort->->DepthStencil->CompileShader->Vertex and Indices->Camera

So the renderTargetView doesn't have the Depthstencil info and...Change the place where InitDepthStencil() is called

Ok...this time my cubes are gone......

Share this post


Link to post
Share on other sites
After I change[source lang="cpp"]devcon->OMSetRenderTargets(1,&backbuffer,pDepthStencilView);[/source]
to [source lang="cpp"]devcon->OMSetRenderTargets(1,&backbuffer,NULL);[/source]

The cubes came back(ofc) which means there are something wrond with my pDepthStencilView.

I have checked my code and DXSampleTutorial5 code, Still can't find a difference in the stencil part.

The only Difference is I keep Depthstencil Init in a single function and Call it after I created the RenderTargetView
[source lang="cpp"]void InitDepthStencil(void)
{
D3D11_TEXTURE2D_DESC DepthStencilDesc;
ZeroMemory( &DepthStencilDesc, sizeof(DepthStencilDesc) );
DepthStencilDesc.Width = SCREEN_WIDTH;
DepthStencilDesc.Height = SCREEN_HEIGHT;
DepthStencilDesc.MipLevels = 1;
DepthStencilDesc.ArraySize = 1;
DepthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
DepthStencilDesc.SampleDesc.Count = 1;
DepthStencilDesc.SampleDesc.Quality = 0;
DepthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
DepthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
DepthStencilDesc.CPUAccessFlags = 0;
DepthStencilDesc.MiscFlags = 0;
//Create Depth Stencil View
dev->CreateTexture2D(&DepthStencilDesc,NULL,&pDepthStencilBuffer);


D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory( &descDSV, sizeof(descDSV) );
descDSV.Format = DepthStencilDesc.Format;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;

dev->CreateDepthStencilView(pDepthStencilBuffer, &descDSV, &pDepthStencilView);
devcon->OMSetRenderTargets(1,&backbuffer,NULL);
//devcon->OMSetRenderTargets(1,&backbuffer,pDepthStencilView);

}[/source]

and call it Here

[source lang="java"]Init3D()
{..................
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0,_uuidof(ID3D11Texture2D),(LPVOID*)&pBackBuffer);

//use the backbuffer to create the render target
dev->CreateRenderTargetView(pBackBuffer,NULL,&backbuffer);
pBackBuffer->Release();
InitDepthStencil();
...............
}[/source]

Share this post


Link to post
Share on other sites
I'd also advise checking the values of SCREEN_WIDTH and SCREEN_HEIGHT - they may not be correct. Generally I GetDesc on the swap chain then use the values returned from that for setting up these views, which helps ensure that everything is absolutely consistent.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!