Weird pop-in of individual triangles with distance

Started by
6 comments, last by deadc0deh 4 years, 10 months ago

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?

 

 

You didn't come into this world. You came out of it, like a wave from the ocean. You are not a stranger here. -Alan Watts

Advertisement

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.

 

You didn't come into this world. You came out of it, like a wave from the ocean. You are not a stranger here. -Alan Watts

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.

 

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. 

 

 

You didn't come into this world. You came out of it, like a wave from the ocean. You are not a stranger here. -Alan Watts

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

 

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.

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.

This topic is closed to new replies.

Advertisement