Mirror image drawn when using VBO's

Started by Cornix, August 04, 2013, 17:15:12

Previous topic - Next topic

Cornix

Hi.

I am using VBO's for drawing right now, the classical:
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo);
		
		GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
		GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		
		GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, v_pointer);
		GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, t_pointer);
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);

With a VBO with positions and texture coordinates and another buffer with indices.

Now my question is, is there a simple and efficient way to flip the image horizontally / vertically without having to create another VBO?
I know I could just flip the texture coordinates inside the vbo but I would like not to since the same VBO might be used by several other sprites in my application.
So if there is some magic function call I dont remember or never saw please enlighten me.

Thank you very much.

quew8

No magic functions I'm afraid (at least that I know of). The solution is to manipulate the texture coords.

If you're using shaders, it is a very simple solution. (1 - s, 1 - t) instead of (s, t).

If you aren't using shaders, then you'll have to employ the texture matrix. I'm sure you'll manage to work out the correct matrix to use since you've git this far. (BTW manipulate the texture matrix exactly the same as modelview or projection, just call glMatrixMode(GL_TEXTURE) first.

Cornix

Thank you alot. Texture-Matrix, that might work.
Also read you could call
glScalef(-1, 1, 1)

for horizontal mirroring, but you would have to cull the other face and translate too since it will move out of place.
I dont exactly know which is the better solution but I guess I will go with the texture matrix for now since it will be less work on the CPU.

Cornix

Manipulating the texture matrix doesnt seem to work. I am sorry, but is there something I need to enable first or have to do before changes to the texture matrix take place?
Whatever I do, translate, rotate, scale, etc, nothing shows any effect on rendering.

quew8

No, there's nothing else you need to enable. I can't envisage any situation where it has no effect whatsoever. Following a quick google search, my advise (this is weak stuff) is make sure you are calling glMatrixMode(GL_TEXTURE), and not with GL_TEXTURE_2D or GL_TEXTURE_MATRIX or anything like that. But you would have seen the GL_INVALID_ENUM error anyway, right?

Last bit of advise, just before you render try getting the texture matrix and taking a look see what it contains. glGetFloatv(GL_TEXTURE_MATRIX); or something like that

Cornix

Code looks like this right now:
GL11.glMatrixMode(GL11.GL_TEXTURE);
			GL11.glPushMatrix();
			GL11.glRotatef(32, 1, 1, 1);
			GL11.glTranslatef(50, 0, 0);
			GL11.glScalef(0.5f, 1, 1);

			GL11.glMatrixMode(GL11.GL_MODELVIEW);

			FloatBuffer buf = ByteBuffer.allocateDirect(16 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
			GL11.glGetFloat(GL11.GL_TEXTURE, buf);
			float[] texMat = new float[16];
			buf.get(texMat);
			System.out.println(Arrays.toString(texMat));

			// Render logic

			GL11.glMatrixMode(GL11.GL_TEXTURE);
			GL11.glPopMatrix();
			GL11.glMatrixMode(GL11.GL_MODELVIEW);


The output says the texture matrix is 0 in all columns and rows.

In the specification it says to use GL_TEXTURE for the matrix mode:
http://www.opengl.org/sdk/docs/man2/xhtml/glMatrixMode.xml

When I use GL_TEXTURE_MATRIX in the glGetFloat method I get the following result:
Quote[0.44934937, 0.17829983, -0.1276492, 0.0, -0.2552984, 0.89869875, 0.35659966, 0.0, 0.35659966, -0.2552984, 0.89869875, 0.0, 44.934937, 17.829983, -12.76492, 1.0]
Looks promising, but still there is no effect on the image being drawn. I dont use any custom shaders by the way.

quew8

That should be glGetFloat(GL_TEXTURE_MATRIX, buf); (Someone isn't checking their OpenGL errors).

Also, what's up with the pushing and popping of matrices? The setup as you have it there prints the contents of the matrix after those transforms but then discards them just before you are about to render.

Cornix

I pop the texture matrix after the render logic. The rendering comes directly after the print and before the popMatrix call. Its very complicated and big thats why I left it out intentionally and inserted a comment instead.

Cornix

I noticed something fishy. I deleted all manipulations to the texture matrix in my code and just left the printing there to get the contents of the texture matrix.
In the first frame (before anything was ever rendered) the texture matrix was this:
[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
The identity matrix.

But after the first rendering of an image it was:
[0.0078125, 0.0, 0.0, 0.0, 0.0, 0.015625, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
at every other frame.
I dont know how this comes since I never do any changes to the texture matrix anywhere else in my program.

Edit: Nevermind, I do make a change to the texture matrix somewhere, now I think I am just stupid...
Ok manipulating the texture matrix works now.
But I found out it doesnt help me with my problem. Yes, the texture is mirrored, but not the image. The image only uses a small portion of the texture (its a spritesheet) so the result is not what I was looking for.
It still is good to have eliminated this small bug though.

quew8

Oh, sorry, completely misinterpreted - no wonder you can't fix this when I'm the one helping you.

Now that is fishy. During by very brief Google search, I found a topic on StackOverflow with something similar. http://stackoverflow.com/questions/11996529/what-could-globally-affect-texture-coordinate-values-in-opengl. (Just under the first picture he adds an edit with this problem). Unfortunately his solution  is to reset the texture matrix to the identity after rendering. Which I find somewhat unsatisfying, but if it works and in lieu of a better solution...

Cornix

I edited my post and already figured out that I am stupid.
At another point in my program, something I wrote quite a while ago, I was already manipulating the texture matrix without remembering.

But as I said, this is unfortunately not a solution to my original problem. I now go with calling glScalef(-1, 1, 1) on the ModelViewMatrix to mirror my image.
Then I have to call glTranslatef(-image_width, 0, 0) to put the image back in place.
But I also have to reverse the culling to render this image...

quew8

If you're going to go with that, change the front face (with glFrontFace(GL_CW);) rather than reversing the culling. Makes more sense to keep the front face as the front face rather than just pretend the back is.

Cornix

Thats a great idea. I didnt even know that was possible.
Thank you.

Edit: Just tested it, works GREAT.