🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Understanding space transformations from local space to pixel coordinates.

Started by
1 comment, last by taby 3 years, 9 months ago

I'm trying to understand the details of space transformations that take a vertex from local space to a screen space. I'm working with DirectX so I'm following the following this documentation. This is an excerpt from there which shows how the pipeline should transform a vertex:

I'm pretty clear on the first 3 transformations, model to world, world to view space, view space to projection space (clip space). What I'm confused about is that some of the things in this flow don't seem to match my own experimentation in code. Here is an example:

In this vertex shader I do the 3 basic transform, after the perspective transform the object should be in clip space, and as you can see the dubug value of the vertex at the end of the perspective transform is <16.14 -2 7.3 7.4>

So now the vertex should be in projection space aka ‘clip space’.

Going back to the documentation, this is what the paper says happens in the clip space:

So looking at this in order for the vertex to pass the clip test X should be (X > -Wp) in my case X is 16.14 so and W is 7.4 so it's true, but X should also be (X ≤ Wp), and in my case that is not so. So that's the first issue I have, which is not making sense to me.

Ok so that issue aside, moving on to the next step after clipping, which is view port scaling. The doc says that this is the viewport matrix

It's scaling X by the dwWidth, and Y by (-Height) to flip it and scale it at the same time. However how can this be done at this stage? My vertex position is still <16.14 -2 7.3 7.4> as far as I understand, and in order to do this scaling doesn't the vertex already have to be in normalized device coordinates by the time this operation is performed? That's my second issue.

So moving to the last step, which is the perspective divide. In my case if I transform my current vertex by the Wp matrix (in the above diagram)

I get <12800 5640 7.3 7.4>, after the perspective divide the numbers are still completely out of bounds. So what am I missing here?

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

I have world space to screen space code, for OpenGL. Would this help you at all where you're using D3D?

vertex_2 p = get_screen_coords_from_world_coords(transformed_vertex, camera_pos, projection_modelview_mat, win_x, win_y);

i->draw(ortho.get_program(), static_cast<size_t>(p.x), static_cast<size_t>(p.y), win_x, win_y);


// where ...

void multiply_4x4_matrix_by_4_vector(const float(&in_a)[16], const float(&in_b)[4], float(&out)[4])
{
    float temp[4];

    for (int i = 0; i < 4; i++)
    {
        temp[i] = 0.0;

        for (int j = 0; j < 4; j++)
        {
            temp[i] += in_a[i*4 + j] * in_b[j];
        }
    }

    for (size_t i = 0; i < 4; i++)
        out[i] = temp[i];
}

vertex_2 get_screen_coords_from_world_coords(const vertex_3 p, const vertex_3 c, const float(&mat)[16], const int width, const int height)
{
    vertex_3 v = p - c;
    v.x /= v.z;
    v.y /= v.z;
    v.z /= v.z;

    float point[4];
    point[0] = c.x + v.x;
    point[1] = c.y + v.y;
    point[2] = c.z + v.z;
    point[3] = 0;

    float out[4];

    multiply_4x4_matrix_by_4_vector(mat, point, out);

    return  vertex_2(round(((1.0f + out[0]) * 0.5f) * (float)width),
        round(((1.0f - out[1]) * 0.5f) * (float)height));
}

This topic is closed to new replies.

Advertisement