3 replies to this topic

Posted 25 June 2012 - 07:03 AM

I'm learning DirectX 11 and I'm having trouble with the perspective divide. Specifically, the perspective transform is resulting in all my vertices getting clipped before rasterisation.

I'm testing with a 200x200 cube centered at the origin. You can see an image of the problem in PIX below

After the the w-divide my vertices lie wholly outside of clip space, but I can't see anything wrong with the matrices I'm passing to my shaders.

Setting up the viewport

[source lang="cpp"]const int windowWidth = 800, windowHeight = 600;D3D11_VIEWPORT vp;ZeroMemory(&vp, sizeof(vp));vp.TopLeftX = D3D11_VIEWPORT_BOUNDS_MIN;vp.TopLeftY = D3D11_VIEWPORT_BOUNDS_MIN;vp.Width = (float)windowWidth;vp.Height = (float)windowHeight;vp.MinDepth = 0.0f;vp.MaxDepth = 1.0f;g_pImmediateDeviceContext->RSSetViewports(1, &vp);[/source]

Building the matrices

[source lang="cpp"]VSConstants VSConstData;D3DXMatrixIdentity(&VSConstData.world);D3DXMatrixLookAtLH(&VSConstData.view, &eye, &lookAt, &up);D3DXMatrixPerspectiveFovLH(&VSConstData.projection, toRadians(90.0f), (float)windowWidth / (float)windowHeight, 0.01f, 1000.0f);VSConstData.worldViewProjection = VSConstData.world * VSConstData.view * VSConstData.projection;D3DXMatrixInverse(&VSConstData.invWorldViewProjection, 0, &VSConstData.worldViewProjection);g_pImmediateDeviceContext->UpdateSubresource(g_pVSConstants, 0, 0, &VSConstData, 0, 0);[/source]

and here is the contents of the constants buffer as reported by PIX

Vertex & pixel shaders

[source lang="cpp"]float4x4 world;float4x4 view;float4x4 projection;float4x4 worldViewProjection;float4x4 invWorldViewProjection;Texture2D g_texture;SamplerState defaultSampler{MipFilter = LINEAR;MinFilter = LINEAR;MagFilter = LINEAR;};struct VSInput{float4 position : POSITION;float3 normal : NORMAL;float2 texcoord : TEXCOORD0;};struct PSInput{float4 position : SV_POSITION;float3 normal : NORMAL;float2 texcoord : TEXCOORD0;};PSInput VSDefault(VSInput input){PSInput result;result.position = mul(input.position, world);result.position = mul(result.position, view);result.position = mul(result.position, projection);result.normal = input.normal;//mul(input.normal, invWorldViewProjection);result.texcoord = input.texcoord;return result;}float4 PSDefault(PSInput input) : SV_TARGET{return g_texture.Sample(defaultSampler, input.texcoord);}[/source]

I have a feeling the problem is to do with my viewport settings as the post-vs output looks fine. It is only after clipping that I lose everything. Unfortunately I can't find much information on the appropriate values for the D3D11_VIEWPORT structure and trial and error has proven unsuccessful. Any idea what I'm doing wrong?

I'm testing with a 200x200 cube centered at the origin. You can see an image of the problem in PIX below

After the the w-divide my vertices lie wholly outside of clip space, but I can't see anything wrong with the matrices I'm passing to my shaders.

Setting up the viewport

[source lang="cpp"]const int windowWidth = 800, windowHeight = 600;D3D11_VIEWPORT vp;ZeroMemory(&vp, sizeof(vp));vp.TopLeftX = D3D11_VIEWPORT_BOUNDS_MIN;vp.TopLeftY = D3D11_VIEWPORT_BOUNDS_MIN;vp.Width = (float)windowWidth;vp.Height = (float)windowHeight;vp.MinDepth = 0.0f;vp.MaxDepth = 1.0f;g_pImmediateDeviceContext->RSSetViewports(1, &vp);[/source]

Building the matrices

[source lang="cpp"]VSConstants VSConstData;D3DXMatrixIdentity(&VSConstData.world);D3DXMatrixLookAtLH(&VSConstData.view, &eye, &lookAt, &up);D3DXMatrixPerspectiveFovLH(&VSConstData.projection, toRadians(90.0f), (float)windowWidth / (float)windowHeight, 0.01f, 1000.0f);VSConstData.worldViewProjection = VSConstData.world * VSConstData.view * VSConstData.projection;D3DXMatrixInverse(&VSConstData.invWorldViewProjection, 0, &VSConstData.worldViewProjection);g_pImmediateDeviceContext->UpdateSubresource(g_pVSConstants, 0, 0, &VSConstData, 0, 0);[/source]

and here is the contents of the constants buffer as reported by PIX

Vertex & pixel shaders

[source lang="cpp"]float4x4 world;float4x4 view;float4x4 projection;float4x4 worldViewProjection;float4x4 invWorldViewProjection;Texture2D g_texture;SamplerState defaultSampler{MipFilter = LINEAR;MinFilter = LINEAR;MagFilter = LINEAR;};struct VSInput{float4 position : POSITION;float3 normal : NORMAL;float2 texcoord : TEXCOORD0;};struct PSInput{float4 position : SV_POSITION;float3 normal : NORMAL;float2 texcoord : TEXCOORD0;};PSInput VSDefault(VSInput input){PSInput result;result.position = mul(input.position, world);result.position = mul(result.position, view);result.position = mul(result.position, projection);result.normal = input.normal;//mul(input.normal, invWorldViewProjection);result.texcoord = input.texcoord;return result;}float4 PSDefault(PSInput input) : SV_TARGET{return g_texture.Sample(defaultSampler, input.texcoord);}[/source]

I have a feeling the problem is to do with my viewport settings as the post-vs output looks fine. It is only after clipping that I lose everything. Unfortunately I can't find much information on the appropriate values for the D3D11_VIEWPORT structure and trial and error has proven unsuccessful. Any idea what I'm doing wrong?

Posted 25 June 2012 - 07:16 AM

I held off for 4 days on creating this thread, exhausting every option I could think of, and not even 10 minutes after I posted did I find the solution.

[source lang="cpp"]const int windowWidth = 800, windowHeight = 600;D3D11_VIEWPORT vp;ZeroMemory(&vp, sizeof(vp));vp.TopLeftX = 0; //Change these two linesvp.TopLeftY = 0; //vp.Width = (float)windowWidth;vp.Height = (float)windowHeight;vp.MinDepth = 0.0f;vp.MaxDepth = 1.0f;g_pImmediateDeviceContext->RSSetViewports(1, &vp);[/source]

MSDN says what the possible values for the D3D11_VIEWPORT structure are but it doesn't clearly explain what those values mean. I wrongly assumed the top left corner would be the minimum possible value given the conventions used for texture addressing and window layouts.

Can anyone offer an in-depth explanation of the interpretation of these values?

[source lang="cpp"]const int windowWidth = 800, windowHeight = 600;D3D11_VIEWPORT vp;ZeroMemory(&vp, sizeof(vp));vp.TopLeftX = 0; //Change these two linesvp.TopLeftY = 0; //vp.Width = (float)windowWidth;vp.Height = (float)windowHeight;vp.MinDepth = 0.0f;vp.MaxDepth = 1.0f;g_pImmediateDeviceContext->RSSetViewports(1, &vp);[/source]

MSDN says what the possible values for the D3D11_VIEWPORT structure are but it doesn't clearly explain what those values mean. I wrongly assumed the top left corner would be the minimum possible value given the conventions used for texture addressing and window layouts.

Can anyone offer an in-depth explanation of the interpretation of these values?

**Edited by _Sauce_, 25 June 2012 - 07:18 AM.**

Posted 25 June 2012 - 12:15 PM

Your vertex shader outputs homogeneous coordinates in clip space. When you divide XYZ by W, you get "normalized device coordinates" where X = -1 is the left side of the viewport, x = 1 is the right side, Y = -1 is the bottom, Y = 1 is the top, Z = 0 is the near clip plane, and z = 1 is the far clip plane. Any coordinates outside of these bounds will be clipped.

After that comes the viewport transform, which looks like this:

At this point the Y-axis is flipped such that (0, 0) is the top left, and (Viewport.Width, Viewport.Height) is the bottom right.

After that comes the viewport transform, which looks like this:

X = (X + 1) * Viewport.Width * 0.5 + Viewport.TopLeftX Y = (1 - Y) * Viewport.Height * 0.5 + Viewport.TopLeftY Z = Viewport.MinDepth + Z * (Viewport.MaxDepth - Viewport.MinDepth)

At this point the Y-axis is flipped such that (0, 0) is the top left, and (Viewport.Width, Viewport.Height) is the bottom right.

Posted 26 June 2012 - 08:31 AM

Thanks MJP, that helps a lot.Your vertex shader outputs homogeneous coordinates in clip space. When you divide XYZ by W, you get "normalized device coordinates" where X = -1 is the left side of the viewport, x = 1 is the right side, Y = -1 is the bottom, Y = 1 is the top, Z = 0 is the near clip plane, and z = 1 is the far clip plane. Any coordinates outside of these bounds will be clipped.

After that comes the viewport transform, which looks like this:X = (X + 1) * Viewport.Width * 0.5 + Viewport.TopLeftX Y = (1 - Y) * Viewport.Height * 0.5 + Viewport.TopLeftY Z = Viewport.MinDepth + Z * (Viewport.MaxDepth - Viewport.MinDepth)

At this point the Y-axis is flipped such that (0, 0) is the top left, and (Viewport.Width, Viewport.Height) is the bottom right.