4

My issue is that I have a (working) orthographic vertex and fragment shader pair that allow me to specify center X and Y of a sprite via 'translateX' and 'translateY' uniforms being passed in. I multiply by a projectionMatrix that is hardcoded and works great. Everything works as far as orthographic operation. My incoming geometry to this shader is based around 0, 0, 0 as its center point.

I want to now figure out what that center point (0, 0, 0 in local coordinate space) becomes after the translations. I need to know this information in the fragment shader. I assumed that I can create a vector at 0, 0, 0 and then apply the same translations. However, I'm NOT getting the correct answer.

My question: what I am I doing wrong, and how can I even debug what's going on? I know that the value being computed must be wrong, but I have no insight in to what it is. (My platform is Xcode 4.2 on OS X developing for OpenGL ES 2.0 iOS)

Here's my vertex shader:

// Vertex Shader for pixel-accurate rendering
attribute vec4 a_position;
attribute vec2 a_texCoord;

varying vec2 v_texCoord;

uniform float translateX;
uniform float translateY;

// Set up orthographic projection 
// this is for 640 x 960
mat4 projectionMatrix = mat4( 2.0/960.0, 0.0, 0.0, -1.0,
                             0.0, 2.0/640.0, 0.0, -1.0,
                             0.0, 0.0, -1.0, 0.0,
                             0.0, 0.0, 0.0, 1.0);                        

void main()
{
    // Set position
    gl_Position = a_position;

    // Translate by the uniforms for offsetting
    gl_Position.x += translateX;
    gl_Position.y += translateY;

    // Translate
    gl_Position *= projectionMatrix;


    // Do all the same translations to a vector with origin at 0,0,0
    vec4 toPass = vec4(0, 0, 0, 1); // initialize.  doesn't matter if w is 1 or 0
    toPass.x += translateX;
    toPass.y += translateY;
    toPass *= projectionMatrix;

    // this SHOULD pass the computed value to my fragment shader.
    // unfortunately,  whatever value is sent, isn't right.
    //v_translatedOrigin = toPass;

    // instead, I use this as a workaround, since I do know the correct values for my
    // situation.  of course this is hardcoded and is terrible.
    v_translatedOrigin = vec4(500.0, 200.0, 0.0, 0.0);
}

EDIT: In response to my orthographic matrix being wrong, the following is what wikipedia has to say about ortho projections, and my -1's look right. because in my case for example the 4th element of my mat should be -((right+left)/(right-left)) which is right of 960 left of 0, so -1 * (960/960) which is -1.

EDIT: I've possibly uncovered the root issue here - what do you think?

enter image description here

Community
  • 1
  • 1
Nektarios
  • 10,173
  • 8
  • 63
  • 93
  • "However, I'm NOT getting the correct answer." So, what answer are you getting? – Nicol Bolas Aug 07 '11 at 20:01
  • @Nicol I have no clue what I'm getting. How can I know? That's part of my question. I know from what I'm doing with it, that it's pretty far off though. – Nektarios Aug 07 '11 at 23:20
  • 1
    To know what answers you're getting, you have to use shader debugging tactics. This includes, but is not limited to: writing the values you feed the fragment shader to the screen (transformed to fit the color range). Writing the values you feed the fragment shader to a secondary render target (via FBO) and reading those back with `glReadPixels`. You should be able to predict what you expect to see, then note the differences from that. – Nicol Bolas Aug 08 '11 at 00:50
  • WRT to your projection, do values in the right-most column correspond to values 12, 13, 14 in your matrix? – luke Aug 08 '11 at 20:59
  • Transposing my projection matrix made my currently-displaying-on-screen sprites not display. – Nektarios Aug 08 '11 at 23:44

2 Answers2

4

Why does your ortho matrix have -1's in the bottom of each column? Those should be zeros. Granted, that should not affect anything.

I'm more concerned about this:

gl_Position *= projectionMatrix;

What does that mean? Matrix multiplication is not commutative; M * a is not the same as a * M. So which side do you expect gl_Position to be multiplied on?

Oddly, the GLSL spec does not say (I filed a bug report on this). So you should go with what is guaranteed to work:

gl_Position = projectionMatrix * gl_Position;

Also, you should use proper vectorized code. You should have one translate uniform, which is a vec2. Then you can just do gl_Position.xy = a_position.xy + translate;. You'll have to fill in the Z and W with constants (gl_Position.zw = vec2(0, 1);).


Matrices in GLSL are column major. The first four values are the first column of the matrix, not the first row. You are multiplying with a transposed ortho matrix.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • I tried breaking it out as ` .. = projectionMatrix * .. ` and it has no change in effect on my regular orthographic projection or translating this local origin point. I don't know why my ortho matrix has -1's in the bottom of each column but when I painstakingly set all this ortho drawing up it appeared I needed that, and I still do need it, because if I change to 0's my sprites draw in the "wrong" place. Vectorized code is an optimization that's not impacting what's going on but thanks for the suggestion. – Nektarios Aug 07 '11 at 23:27
  • 1
    @Nektarios: If removing those -1's makes things break, then they were already broken. Two wrongs happened to make things work, but that doesn't make them any less wrong. – Nicol Bolas Aug 08 '11 at 00:48
  • please see my edit. Can you show me why these should not be -1? Because, it is working in the way I expect, and I looked up the ortho matrix definition again and it matches what I'm doing – Nektarios Aug 08 '11 at 02:49
  • I'm not that sure if you can read from `gl_Position`, anyway. But I suppose it would have been a compile error if not. – Christian Rau Aug 08 '11 at 14:42
  • @Christian you definitely can - that part of my code works as I expect it to – Nektarios Aug 08 '11 at 16:52
1

I have to echo Nicol Bolas's sentiment. Two wrongs happening to make things work is frustrating, but doesn't make them any less wrong. The fact that things are showing up where you expect is likely because the translation portion of your matrix is 0, 0, 0.

The equation you posted is correct, but the notation is row major, and OpenGL is column major: 4 columns of the OpenGL's matrix

I run afoul of this stuff every new project I start. This site is a really good resource that helped me keep these things straight. They've got another page on projection matrices.

If you're not sure if your orthographic projection is correct (right now it isn't), try plugging the same values into glOrtho, and reading the values back out of GL_PROJECTION.

luke
  • 36,103
  • 8
  • 58
  • 81
  • Unfortunately glOrtho doesn't exist on ES 2.0. I'm trying to figure out the 2 wrongs - since my ortho matrix is the one wrong, what could possibly be its wrong counterpart? I send in vertex data, that could be wrong but that doesn't make sense. The vertex shader multiplies by this ortho matrix (which is the 'wrong' part). The fragment shader just adds color, that can't be wrong. And then that's it. If I pass in different geometry, I get rendering in different places on screen as I'd expected. If I pass in my "translateX" and add it, that works. There aren't a lot of pieces to this. – Nektarios Aug 11 '11 at 16:52
  • And since there aren't a lot of pieces to this, the obvious answer is that I should cook up an example and post that. – Nektarios Aug 11 '11 at 16:52
  • Judging by your hard-coded ortho matrix, it looks like your origin is the lower left corner. Is it possible that you're specifying coordinates assuming upper left? Re: glOrtho, you could try it in a regular GL project, or take my word for it :) – luke Aug 11 '11 at 19:34