Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: ZBuffer and matrix changes

  1. #1

    ZBuffer and matrix changes

    Hi PGD'ers.

    I have discovered something weird.

    The Z buffers isn't working properly when you change your projection matrix. I had this problem with my engine so i decided to test it using one of clooties tut's.
    My engine supports different view/projection matrices to be used in one scene. So it is possible to render with perspective/orthogonal/screen coordinates etc.
    But this requires changing the projection matrix, and that delivers a wierd result.
    I've used this code to test. (its from the Mesh tutorial in clooties SDK, just replace the render code with this code).

    [pascal]
    procedure Render;
    var
    i: DWORD;
    matWorld,matProj,matView: TD3DXmatrix;
    begin
    // Clear the backbuffer and the zbuffer
    g_pd3dDevice.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
    D3DCOLOR_XRGB(0,0,255), 1.0, 0);

    // Begin the scene
    g_pd3dDevice.BeginScene;

    //setup matrices
    D3DXMatrixRotationY(matWorld, timeGetTime/1000.0);
    g_pd3dDevice.SetTransform(D3DTS_WORLD, matWorld);

    D3DXMatrixLookAtLH(matView, D3DXVector3(0.0, 0.0,-5.0),
    D3DXVector3(0.0, 0.0, 0.0),
    D3DXVector3(0.0, 1.0, 0.0));
    g_pd3dDevice.SetTransform(D3DTS_VIEW, matView);

    D3DXMatrixPerspectiveFovLH(matProj, D3DX_PI/4, 1.0, 1.0, 100.0);
    g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);

    //render first tiger
    for i:= 0 to g_dwNumMaterials - 1 do
    begin
    g_pd3dDevice.SetMaterial(g_pMeshMaterials[i]);
    g_pd3dDevice.SetTexture(0, g_pMeshTextures[i]);

    g_pMesh.DrawSubset(i);
    end;

    //translate second tiger
    D3DXMatrixTranslation(matWorld, 1,0,0);
    g_pd3dDevice.SetTransform(D3DTS_WORLD, matWorld);

    //set new projection matrix
    D3DXMatrixOrthoLH(matProj, 5.0, 5.0, 1.0, 100.0);
    g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);

    //render second tiger
    for i:= 0 to g_dwNumMaterials - 1 do
    begin
    g_pd3dDevice.SetMaterial(g_pMeshMaterials[i]);
    g_pd3dDevice.SetTexture(0, g_pMeshTextures[i]);

    g_pMesh.DrawSubset(i);
    end;

    g_pd3dDevice.EndScene;

    g_pd3dDevice.Present(nil, nil, 0, nil);
    end;
    [/pascal]

    The weird thing is that the second tiger is ALWAYS drawn over the first tiger. No matter what value i use for the Z translation of the second tiger. There is no way to make the meshes intersect, it's just like rendering 2d images of a tiger.
    The ZBuffer was enabled during these tests.

    What is the cause of this?? does D3D reset the zbuffer every time you change the projection matrix??

    thanks in advance.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  2. #2

    ZBuffer and matrix changes

    Edit: Damn I can't read today.. Nothing here...
    Peregrinus, expectavi pedes meos in cymbalis
    Nullus norvegicorum sole urinat

  3. #3

    ZBuffer and matrix changes

    Hmmm.... When you are change projection matrix you also change mapping of Z axis from your "world/view" space to post-transform space. While generally you could "compose" correctly between difference matrices - when switching from Ortho to Projection transformation is really impossible to get 100% correct composition.
    There are only 10 types of people in this world; those who understand binary and those who don't.

  4. #4

    ZBuffer and matrix changes

    Okay i did some more testing and the problem also occured when i mulitplied world/view/projection matrices and passed them to D3D as world matrix. So D3D doesn't change the ZBuffer, it's a pure mathematical problem.

    Not that i find perspective and ortho projections in one scene a usefull feature, i was curious whether it would work correctly, and it didn't work.

    But i dont understand why it doesn't work. :?
    What's exactly the difference between a perspective and an orthogonal projection. Are the following things true??

    An orthogonal field of view can be visualized as a box.
    The positive Z axis is pointing away from the viewer's eye.
    The only difference between a perspective and an ortho projection is that in perspective projection, the front face of the box is scaled so the box becomes a frustum. This has no influence on the Z axis.
    So i dont know why you say this:
    Hmmm.... When you are change projection matrix you also change mapping of Z axis from your "world/view" space to post-transform space.
    When you set the far/near planes to fixed values for both perspective and orthogonal, i dont see the problem. :?
    Why is the Z Mapping different??

    Can someone clarify this?? (Maybe a link would help)
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  5. #5

    ZBuffer and matrix changes

    My guess based on my own logic tells me that the zbuffering in a perspective projection would differ from orthographic projection in a way like this:
    Peregrinus, expectavi pedes meos in cymbalis
    Nullus norvegicorum sole urinat

  6. #6

    ZBuffer and matrix changes

    uh :eh: I dont think that's possible. You can't bend a space with a matrix. can you?? It requires some funcky math to do that.
    If the space is bended, the far and near planes should also be bended and that is, mathematicly, a lot of work.

    My logic tells me, that your drawing is correct, except for that bended line. I think that must be a straight line.
    So i still dont understand why z is mapped differently. :?
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  7. #7

    ZBuffer and matrix changes

    chronozphere
    Have you studied D3DXMatrixOrthoLH() and D3DXMatrixPerspectiveFovLH() documentation? Look how Z coordinates being calculated. And even worse - W coordinate gets different values too.

    JSoftware
    While intersection of Z planes with projection pyramid will be lines as chronozphere pointed - you are still kind of right too. Texture LOD calculation at lines parallel to front/back plane will "behave" something like you've drawn (as one/both texture coordinate line will change directtion per dx or dy -- i.e. at least one of the du/dx; du/dy; dt/dx; dt/dy will change).
    There are only 10 types of people in this world; those who understand binary and those who don't.

  8. #8

    ZBuffer and matrix changes

    ah yes... it's transformed differently.

    But that raises another question:

    I've read somewere that all visible geometry must be transformed to the canonical view (an AABB with dimentions X [-1,1] Y[-1,1], Z[0,1]).
    The orthogonal matrix contains this (for Z coordinate):

    1/(zf-zn)

    and z translation:

    -zn/(zf-zn)

    That makes perfectly sense. It scales all geometry, so it fits in the canonical view, and translates it to remove everything in front of the near plane.

    But i dont understand the perspective Z calculation.

    zf/(zf-zn)

    When zn is very low (almost equal to zero) this formula returns a value that's allmost one. So when i:

    >>Set zf to 2000 and zn to 10.. the formula returns: 2000/1990
    and the translation is ~10

    When i use the matrix to transform a vertex with Z = 1000
    the resulting Z value is ~995 wich is way outside the canonical view. So i guess the vertex isn't visible. :?

    This explains why geometry rendered with ortho projection is rendered in front of the perspective stuff. Z values for ortho projection always lie in the range [0,1] and those for perspective projection in the range [0,zf-zn].

    Can someone clarify this?? :?
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  9. #9

    ZBuffer and matrix changes

    Actually clipping volume is:
    -wc<= xc<= wc
    -wc<= yc<= wc
    0 <= zc<= wc

    So after transformed coordinates divided by W - you get expected [-1; 1] & [0; 1] range (for Direct3D). OpenGL uses [-1; 1] for all coordinates.
    There are only 10 types of people in this world; those who understand binary and those who don't.

  10. #10

    ZBuffer and matrix changes

    Thank you very much Things are clear now.

    So i could compose my own matrix wich doesn't use W, just the same method as the orthogonal matrix. This would solve the problem.

    But, is W usefull?? what would happen if i don't use it in the matrix. :?
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •