Jump to content
  • Advertisement
VanillaSnake21

DX11 Weird pop-in of individual triangles with distance

Recommended Posts

Posted (edited)

I'm getting a strange pop in issue after increasing the size of the terrain. This was not an issue before the size increase, so I'm thinking it's got something to do with either the depth buffer or the far planes.
I'm including a video of what it looks like and some code snippets from what I think are relevant places.

 

Depth buffer

	//create depth stencil texture
	D3D11_TEXTURE2D_DESC descDepth;

	descDepth.Width = mClientWidth;
	descDepth.Height = mClientHeight;
	descDepth.MipLevels = 1;
	descDepth.ArraySize = 1;
	descDepth.Format = DXGI_FORMAT_D32_FLOAT;
	descDepth.SampleDesc.Count = 1;
	descDepth.SampleDesc.Quality = 0;
	descDepth.Usage = D3D11_USAGE_DEFAULT;
	descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
	descDepth.CPUAccessFlags = 0;
	descDepth.MiscFlags = 0;

	if (FAILED(mD3DDevice->CreateTexture2D(&descDepth, NULL, &mD3D11DepthStencilTexture))) return;
	if (FAILED(mD3DDevice->CreateDepthStencilView(mD3D11DepthStencilTexture, 0, &mD3D11DepthStencilView))) return;

 

Viewport

//set view port ===================================================
	mD3D11Viewport.Width = swapChainDesc.BufferDesc.Width;
	mD3D11Viewport.Height = swapChainDesc.BufferDesc.Height;
	mD3D11Viewport.MinDepth = 0.0f;
	mD3D11Viewport.MaxDepth = 1.0f;
	mD3D11Viewport.TopLeftX = 0;
	mD3D11Viewport.TopLeftY = 0;

	mDeviceContext->RSSetViewports(1, &mD3D11Viewport);

 

Blend state

D3D11_BLEND_DESC BlendDesc;
	ZeroMemory(&BlendDesc, sizeof(D3D11_BLEND_DESC));

	

	BlendDesc.RenderTarget[0].BlendEnable = TRUE;
	BlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
	BlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
	BlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
	BlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
	BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
	BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

	mD3DDevice->CreateBlendState(&BlendDesc, &mD3D11BlendState);
	mDeviceContext->OMSetBlendState(mD3D11BlendState, 0, 0xffffffff);

 

 

Clearing the depth buffer

// Clear the back buffer 
	float clearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red,green,blue,alpha
	mDeviceContext->ClearRenderTargetView(mD3D11RenderTargetView, clearColor);
	mDeviceContext->ClearDepthStencilView(mD3D11DepthStencilView, D3D11_CLEAR_DEPTH, 1, 1);

 

 

Projection matrix calculation

	mProjectionMatrix = XMMatrixPerspectiveFovLH(3.14159265f / 4.0f, 4.0f/3.0f, 0.01f, 100000.0f);

 

 

Any ideas what this could be?

 

 

Edited by VanillaSnake21

Share this post


Link to post
Share on other sites
Advertisement
Posted (edited)

After doing some additional tests, I think the issue can be narrowed down even further. If I don't draw the skybox, the environement comes out looking better, I can see further, but there are still transparancy issues. I've tried disabling blending but it did not help.

Also when I view the outputs of pixel shaders and output merger states they both display the geometry properly, but I guess something after the output merger stage prevents it from being displayed?

 

You can see it throughout the video as little pop-ins but the effect becomes jarring at 0:40, at the end I show what the outputs of various stages look like.

 

Edited by VanillaSnake21

Share this post


Link to post
Share on other sites

Off the top of my head its either z-buffer, alpha blending or back face culling. It looks more like z-buffer.

In ClearDepthStencilView why do you set stencil to 1? Don't think it matters though.

Try narrowing the near far clip range to make sure its not a z-buffer fighting thing. 0.001 to 100000 is a pretty big range.

 

Share this post


Link to post
Share on other sites
Posted (edited)
29 minutes ago, TeaTreeTim said:

Off the top of my head its either z-buffer, alpha blending or back face culling. It looks more like z-buffer.

In ClearDepthStencilView why do you set stencil to 1? Don't think it matters though.

 Try narrowing the near far clip range to make sure its not a z-buffer fighting thing. 0.001 to 100000 is a pretty big range.

  

That was it! Thanks so much, I raised the low clip to 10 and it fixed the clipping issue. I had to increase the skybox radius as well and now it looks great. 

 

 

Edited by VanillaSnake21

Share this post


Link to post
Share on other sites
Posted (edited)

You guys probably know that better than i do, anyway :-): real world coordinates (double on the cpu) can be split into two floats ....

static inline void doubleToTwoFloats( const double &d, float &high, float &low ) {
	high = (float)d;
	low = (float)(d - high);
}

... and reassembled in the vertex shader (*).

	vec3 t1 = inPositionLow - g_cameraPositionLow;
	vec3 e = t1 - inPositionLow;
	vec3 t2 = ( ( -g_cameraPositionLow - e ) + ( inPositionLow - ( t1 - e ) ) ) +
			  inPositionHigh - g_cameraPositionHigh;
	vec3 highDifference = t1 + t2;
	vec3 lowDifference = t2 - ( highDifference - t1 );
	vec3 position = highDifference + lowDifference; // * mvp relative to eye

The modelviewprojectionmatrix used must be stripped of the translation to render the so transformed scene in view coordinates. I have an unsolved issue with model tranformations with this method ...

Skybox shouldn't interfere with the rest imo, if it is rendered last with depth comparison set to "less or equal" ?

 

But for a "real world" planet a depth buffer of 32bit is still pretty puny, coordinates alone won't help displaying a spaceship in hand's reach in front of the earth with the moon behind them. One solution for such scenes i haven't tackled yet is to divide the frustum into 3 "levels" (*) ...

-------

(*) from: "3D Engine Designs for Virtual Globes" by Cozzi/Ring

 

Edited by Green_Baron
Name spelling

Share this post


Link to post
Share on other sites

For a skybox, a trick you can use is to force its depth to the far clip plane. This will keep it from drawing on top of your scene geometry without having to use crazy long draw distances. The easiest way to do it is to set the viewport with MinDepth = MaxDepth = 1.0f, and use a rasterizer state with DepthClipEnable set to FALSE.

Share this post


Link to post
Share on other sites
Posted (edited)
Quote

But for a "real world" planet a depth buffer of 32bit is still pretty puny

This is partially true. In the "real world" for large scenes, everything gets transformed to around the camera on the CPU side first, this greatly decreases the required bit depth. A lot of special cases exist too... for example in FPS the gun/hands is usually using a different depth range than the rest of the scene as it requires a near plane really close, which destroys z precision at distance. Far away geometry (other than skybox) uses yet another, etc. Another example of relocating to camera is skeletal animation which usually suffers heavily from imprecision in the hierarchy of matrix multiplications in combination with compression, moving this to a camera local frame before multiplying the whole thing helps greatly.

Edited by deadc0deh

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!