14
\$\begingroup\$

I am looking for some insight into a small problem with unit translations on a grid.

Update and Solved

I solved my own issue. See below for details. Everything in this part of the post turned out to be correct. If anything it can act as a miniature tutorial / example / help for the next person.

Setup

  • FBO, VAO, VBO
  • 512x448 window
  • 64x64 grid
  • gl_Position = projection * world * position;
  • projection is defined by ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f); This is a textbook orthogonal projection function.
  • world is defined by a fixed camera position at (0, 0)
  • position is defined by the sprite's position.

Problem

In the screenshot below (1:1 scaling) the grid spacing is 64x64 and I am drawing the unit at (64, 64), however the unit draws roughly ~10px in the wrong position. I've tried uniform window dimensions to prevent any distortion on the pixel size, but now I am a bit lost in the proper way in providing a 1:1 pixel-to-world-unit projection. Anyhow, here are some quick images to aide in the problem.

64x64 Tiles on a 512x448 window

I decided to super-impose a bunch of the sprites at what the engine believes is 64x offsets.

64 offsets super-imposed

When this seemed off place, I went about and did the base case of 1 unit. Which seemed to line up as expected. The yellow shows a 1px difference in the movement.

Base case of 1 unit

What I Want

Ideally moving in any direction 64-units would output the following (super-imposed units):

Desired output

Vertices

It would appear that the vertices going into the vertex shader are correct. For example, in reference to the first image the data looks like this in the VBO:

      x    y           x    y
    ----------------------------    
tl | 0.0  24.0        64.0 24.0
bl | 0.0  0.0    ->   64.0 0.0
tr | 16.0 0.0         80.0 0.0
br | 16.0 24.0        80.0 24.0

For sake of completeness here is the actual array corresponding to the above movements:

      x     y    z   w   r   g   b   a      s          t
-------------------------------------------------------------
tl | 0.0   23.0 0.0 1.0 0.0 0.0 0.0 1.0 0.14210527 0.62650603 
bl | 0.0   0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.14210527 0.76506025 
tr | 16.0  0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.2263158  0.76506025 
br | 16.0  23.0 0.0 1.0 0.0 0.0 0.0 1.0 0.2263158  0.62650603 
-------------------------------------------------------------
-------------------------------------------------------------
tl | 64.0  24.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0        0.21084337 
bl | 64.0  0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.0        0.3554217 
tr | 80.0  0.0  0.0 1.0 0.0 0.0 0.0 1.0 0.08421053 0.3554217 
br | 80.0  24.0 0.0 1.0 0.0 0.0 0.0 1.0 0.08421053 0.21084337

// side bar: I know that I have unnecessary data with having a z-axis.
//           The engine flips between perspective and orthogonal and I
//           haven't selectively started pruning data.

Projection Matrix

The projection matrix for the 512x448 window looks like this:

0.00390625 0.0         0.0  0.0
0.0        0.004464286 0.0  0.0
0.0        0.0        -1.0  0.0
0.0        0.0         0.0  1.0

and is constructed with a textbook orthogonal projection function:

ortho(-w/2.0f, w/2.0f, -h/2.0f, h/2.0f);
// explicitly: ortho(-512/2.0f, 512/2.0f, -448/2.0f, 448.0f

ortho(float left, float right, float bottom, float top)
{
    projection.setIdentity();
    projection.m00 = 2.0f / (right - left);
    projection.m11 = 2.0f / (top - bottom);
    projection.m22 = -1;
    projection.m30 = -(right + left) / (right - left);
    projection.m31 = -(top + bottom) / (top - bottom);
    projection.m32 = 0;
}

World-view Matrix

The camera's position is just a translation matrix which in this case I just offset by -w/2 and -h/2 to be zero relative to center.

1.0 0.0 0.0 -256.0
0.0 1.0 0.0 -224.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0

Solutions I have attempted

  1. player.moveRight() would move 1-unit with the aspect ratio factored into the equation. So: gridWidth = 64 / 1.14f. Movement did not fit within the grid.

  2. Forced a 512x512 window with a matching orthogonal projection.

  3. Tried various magic numbers and tried to draw correlations between the two.

With that said, all I am left to believe is that I am munging up my actual projection. So, I am looking for any insight into maintaining the 1:1 pixel-to-world-unit projection.

\$\endgroup\$
4
  • 5
    \$\begingroup\$ Well constructed question, but maybe we could see your projection & world matrices. You mentioned them above, but didn't include their contents. The problem will be with one of those matrices. \$\endgroup\$
    – Ken
    Nov 27, 2012 at 9:38
  • \$\begingroup\$ @Ken No problem at all. I've added my projection and world-space view matrices. I've also included my desired output and my own attempts at the problem. \$\endgroup\$ Nov 27, 2012 at 14:09
  • \$\begingroup\$ You matrices look good (I compared them the ones produces by glOrtho and glTranslate. Grapsing at straws here, but opengl expects its matrices to arranged in column-major order, are you doing the same? \$\endgroup\$
    – Ken
    Nov 28, 2012 at 10:15
  • \$\begingroup\$ Hm, they are being stored column-major order. \$\endgroup\$ Nov 28, 2012 at 15:23

1 Answer 1

5
\$\begingroup\$

I solved my own problem--and rather than just blow it off as a simple explanation, I want to describe the steps I took to debug the issue. I left out that I was using a single FBO for special-effects.

First, it turns out everything above is in fact correct and a step I left out was the problem.

  • I verified my orthogonal matrices through-and-through.
  • Verified the byte-order of everything.
  • Created a square texture. <- Here is the magic
  • When I created a square texture, I noticed it was not square on the screen, but square going into the vertex shader.
  • This was my first clue that something was wrong. The dimensions of my textures on screen did not match the dimensions that were going to the vertex shader.
  • I forgot that I was using an FBO (here comes the sillyness).
  • The FBO texture size did not match my viewport texture size for whatever stupid reason.
  • Disabled the FBO and the results matched up.
  • Fixed the logic with defining my texture size and wah-lah.

Sillyness

I am sorry if this took up anyone's time. I will leave the question around as good measure for anyone that might run into the same problem without knowing it.

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .