Frank luna, introduction to 3d game programming with directx 11

Started by
8 comments, last by unbird 9 years ago

I'm on chapter 10 stenciling, question 8 dealing with Depth complexity.

Anyone read this book by Frank Luna?

Here is part of the question that im not understanding.

8. Depth complexity refers to the number of pixel fragments that compete, via the depth test, to be written to a particular entry in the back buffer. For example, a pixel we have drawn may be overwritten by a pixel that is closer to the camera (and this can happen several times before the closest pixel is actually figured out once the entire scene has been drawn). The pixel in Figure 10.12 has a depth complexity of 3 since three pixel fragments compete for the pixel. Potentially, the graphics card could fill a pixel several times each frame. This overdraw has performance implications, as the graphics card is wasting time processing pixels that eventually get overridden and are never seen. Consequently, it is useful to measure the depth complexity in a scene for performance analysis. We can measure the depth complexity as follows: Render the scene and use the stencil buffer as a counter; that is, each pixel in the stencil buffer is originally cleared to zero, and every time a pixel fragment is processed, we increment its count with D3D11_STENCIL_OP_INCR. The corresponding stencil buffer entry should always be incremented for every pixel fragment no matter what, so use the stencil comparison function D3D11_COMPARISON_ALWAYS. Then, for example, after the frame has been drawn, if the ijth pixel has a corresponding entry of five in the stencil buffer, then we know that those five pixel fragments were processed for that pixel during that frame (i.e., the pixel has a depth complexity of five). Note that when counting the depth complexity, technically you only need to render the scene to the stencil buffer. To visualize the depth complexity (stored in the stencil buffer), proceed as follows:

Associate a color ck for each level of depth complexity k. For example, blue for a depth complexity of one, green for a depth complexity of two, red for a depth complexity of three, and so on. (In very complex scenes where the depth complexity for a pixel could get very large, you probably do not want to associate a color for each level. Instead, you could associate a color for a range of disjoint levels. For example, pixels with depth complexity 1–5 are colored blue, pixels with depth complexity 6–10 are colored green, and so on.) (b) Set the stencil buffer operation to D3D11_STENCIL_OP_KEEP so that we do not modify it anymore. (We modify the stencil buffer with D3DSTENCILOP_INCR when we are counting the depth complexity as the scene is rendered, but when writing the code to visualize the stencil buffer, we only need to read from the stencil buffer and we should not write to it.) For each level of depth complexity k: (i) Set the stencil comparison function to D3D11_COMPARISON_EQUAL and set the stencil reference value to k.

(ii) Draw a quad of color ck that covers the entire projection window. Note that this will only color the pixels that have a depth complexity of k because of the preceding set stencil comparison function and reference value.
Figure 10.13. Sample screenshot of the solution to Exercise 8. With this setup, we have colored each pixel based on its depth complexity uniquely, and so we can easily study the depth complexity of the scene. For this exercise, render the depth complexity of the scene used in the “Blend” demo from Chapter 9. Figure 10.13 shows a sample screenshot.
The depth test occurs in the output merger stage of the pipeline, which occurs after the pixel shader stage. This means that a pixel fragment is processed through the pixel shader, even if it may ultimately be rejected by the depth test. However, modern hardware does an “early z-test” where the depth test is performed before the pixel shader. This way, a rejected pixel fragment will be discarded before being processed by a potentially expensive pixel shader. To take advantage of this optimization, you should try to render your non-blended game objects in front-to- back order with respect to the camera; in this way, the nearest objects will be drawn first, and objects behind them will fail the early z-test and not be processed further. This can be a significant performance benefit if your scene suffers from lots overdraw due to a high depth complexity. We are not able to control the early z-test through the Direct3D API; the graphics driver is the one that decides if it is possible to perform the early z-test. For example, if a pixel shader modifies the pixel fragment’s depth value, then the early z-test is not possible, as the pixel shader must be executed before the depth test since the pixel shader modifies depth values.
We mentioned the ability to modify the depth of a pixel in the pixel shader. How does that work? A pixel shader can actually output a structure, not just a single color vector as we have been doing thus far:


struct PixelOut 
{ 
float4 color : SV_Target;
 float depth : SV_Depth;
 };

 PixelOut PS(VertexOut pin)
 {
 PixelOut pout;
 // … usual pixel work
 pout.Color = float4(litColor, alpha); 
// set pixel depth in normalized [0, 1] range
 pout.depth = pin.PosH.z - 0.05f; return pout;
 }

Im suppose to get a picture like the one on the right.

Fig10_13.png

Can someone give me a idea on what I need to do here? Does this need to be done in the pixel shader?

Advertisement

Im suppose to get a picture like the one on the right. Can someone give me a idea on what I need to do here? Does this need to be done in the pixel shader?

Not "the" pixel shader, no. "Another" pixel shader.

Since you're that far along in the book, you should know how DO to the basics described in each step.

After you have rendered the scene (but NOT Present'ed it) and filled the stencil buffer as described -

StartLoop:

In a loop "for size_t k=0; k < numColorsYouveChosen; ++k":


Set the stencil buffer operation to D3D11_STENCIL_OP_KEEP so that we do not modify it anymore.


Set the stencil comparison function to D3D11_COMPARISON_EQUAL and set the stencil reference value to k.

Hint: take a look at the docs for ID3D11DeviceContext::OMSetDepthStencilState.

Next: You should already know how to setup code to do the following:


Draw a quad of color ck that covers the entire projection window.

EndLoop;

swapChain->Present();

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

what _specifically_ don't you understand?

what output do you get?

can you post a screen shot?

can you post a code snippet? (if you've written one).

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

I think you got confused by that "pixel shader outputs depth". This was just additional information. The suggested shaders are a so-called full screen quad combined with a trivial pixel shader just outputting a color (provided through a constant buffer). For the former google or search the DX forum for drawing a quad (or triangle) without vertex buffers. But you can of course explicitly set up vertices for a quad or triangle. I also recommend using a graphics debugger, since working with stencil is usually a bit obscure.

It should be noted that one can sample the stencil buffer directly using a shader resource view with format DXGI_FORMAT_X24_TYPELESS_G8_UINT. In this case the full screen quad only needs to be called once. In the pixel shader you map the stencil value (0..255) to a color, e.g. through a 1D texture lookup. Try this only after you have successfully completed the above exercise :wink:

I'm not getting draw a quad over the projection window. A quad is a plane right? So when I draw the quad and disable depth, you will be able to see through the plane at other objects? am I right?

Well, sort of smile.png . A full screen quad is a quadrangle, a axis-aligned rectangle covering your whole rendertarget. I.e. just two triangles. The idea is to run your pixel shader once per pixel. What happens then exactly (e.g. seethrough) is determined by what your pixel shader does and what blending you use. Have a look at one of Luna's postprocessing (Blur.cpp) shaders and search for the function DrawScreenQuad().

For this stencil visualization you set blending to opaque. The pixel shader might just looks like this:


cbuffer Parameters
{
	float4 Color;
}

float4 PS(): SV_Target
{
	return Color;
}

Are there any good tutorials for directx 11 for creating a quad that is see through? Maybe with or without using vertex buffers.


creating a quad that is see through?

Just FYI - the picture on the right in your first post is not "see through."

However, to answer your question (which, with respect to your original question, is off-topic) - the construction of the quad has nothing to do with whether it's transparent or not. That's a matter of using a transparent texture and setting the rasterization blend state with the appropriate blending parameters.

Chapter 9 in Luna's book discusses blending.

EDIT: raster state --> blend state. Sorry. And.. read unbird's previous post with more care. wink.png

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This is what I got:

Untitled.jpg

I redrew everything, rendered the scene twice but in the loop as described above.

Like for the box I did this code


boxTech->GetDesc(&techDesc);
	for (UINT p = 0; p < techDesc.Passes; ++p)
	{
		for (UINT i = 0; i < 4; i++)
		{
			md3dImmediateContext->IASetVertexBuffers(0, 1, &mBoxVB, &stride, &offset);
			md3dImmediateContext->IASetIndexBuffer(mBoxIB, DXGI_FORMAT_R32_UINT, 0);

			// Set per object constants.
			XMMATRIX world = XMLoadFloat4x4(&mBoxWorld);
			XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world);
			XMMATRIX worldViewProj = world*view*proj;

			Effects::BasicFX->SetWorld(world);
			Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
			Effects::BasicFX->SetWorldViewProj(worldViewProj);
			Effects::BasicFX->SetTexTransform(XMMatrixIdentity());
			Effects::BasicFX->SetMaterial(mdc[i-1]);
			
		
			md3dImmediateContext->OMSetDepthStencilState(RenderStates::overdraw, i);
			md3dImmediateContext->RSSetState(RenderStates::NoCullRS);
			boxTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
			md3dImmediateContext->DrawIndexed(36, 0, 0);

			// Restore default render state.
			md3dImmediateContext->RSSetState(0);
		}
	}

This is my STENCIL SETTINGS


	D3D11_DEPTH_STENCIL_DESC drawDepth;
	drawDepth.DepthEnable = true;
	drawDepth.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	drawDepth.DepthFunc = D3D11_COMPARISON_LESS;
	drawDepth.StencilEnable = true;

	drawDepth.StencilReadMask = 0xff;
	drawDepth.StencilWriteMask = 0xff;


	drawDepth.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	drawDepth.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	drawDepth.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	drawDepth.FrontFace.StencilFunc = D3D11_COMPARISON_EQUAL;

	drawDepth.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	drawDepth.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	drawDepth.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	drawDepth.BackFace.StencilFunc = D3D11_COMPARISON_EQUAL;

	HR(device->CreateDepthStencilState(&drawDepth, &overdraw));

This is right?

Also, in the first post I made, the part where it says

"(ii) Draw a quad of color ck that covers the entire projection window. Note that this will only color the pixels that have a depth complexity of k because of the preceding set stencil comparison function and reference value."

Is this another way get depth? Or part of the I?

Oh yeah, I still working on getting the stencil ref to the shader...so that will be in the future

This is right?

laugh.png It looks like it's working, but it wasn't precisely what the exercise had in mind. Instead of drawing the whole scene again (and again) you just draw a full screen quad for each color/stencil ref. Congrats anyway. Here some links about buffer-less full screen quad/triangles:
http://www.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau (page 12, full screen triangle)
http://www.gamedev.net/topic/609917-full-screen-quad-without-vertex-buffer
http://www.reddit.com/r/gamedev/comments/2j17wk/a_slightly_faster_bufferless_vertex_shader_trick/

The trick here is that you don't need any vertex transformation, but provide vertex positions in normalized device coordinates already, so it will work for any render target (viewport has to match though).

Reading (sampling) depth or stencil more directly is possible but one has to use different formats for the texture, the depth stencil view and the shader resource view.

Texture format: DXGI_R24G8_TYPELESS
Depth Stencil View Format: DXGI_FORMAT_D24_UNORM_S8_UINT
Shader Resource View for depth: DXGI_FORMAT_R24_UNORM_X8_TYPELESS
Shader Resource View for stencil: DXGI_FORMAT_X24_TYPELESS_G8_UINT

Note that one cannot read depth AND stencil through the same SRV (at least as far as I know). One can bind both views though.

This topic is closed to new replies.

Advertisement