user2924261
user2924261

Reputation: 127

Tiling + OpenGL texture flipping

I am trying to convert tiling rendering from SDL2 to OpenGL. Here is the image from SDL2;

SDL2 rendering

And the same image rendered using OpenGL without texture flipped in Y-axis;

OpenGL with no texture flipping

And here is the image from OpenGL rendering with texture flipped in Y-axis;

OpenGL with texture flipped

Where should I compensate the coordinates with a Y-flipped texture and to get it rendered properly in the OpenGL coordinate system? Here is the code I used to get the texture uv's to render the second picture(texture not flipped) and third picture(flipped texture) in OpenGL;

glm::vec4 srcRect;
srcRect.x = (float)((tileLayer->GetTileId(x, y) - (tileY * tilesPerRow))* (tileWidth+ spacing) )/imageWidth;
srcRect.y = (float)(tileY * (tileHeight + spacing)+ margin)/imageHeight;
srcRect.z = (float)tileWidth/imageWidth;
srcRect.w = (float)tileHeight/imageHeight ;

Upvotes: 2

Views: 2343

Answers (1)

MaKo
MaKo

Reputation: 786

If I didn't understood the problem correctly, just ignore this post. If I understood the problem correctly, instead of tweaking ready-made graphics and computations in working code, I would alter OpenGL perspective transformation to match SDL. OpenGL does not have any preference to coordinate system, so you can tweak it freely to suit your purposes.

I assume you are using modern OpenGL (programmable shaders, no fixed pipeline) and some OpenGL math library (e.g. glm for C++). Most libraries have ortho() to create orthographic perspective with coordinate transformation. The syntax is:

glm::ortho(left, right, bottom, top, near, far)

Just flip bottom and top, and you get flipped y. For 2D graphics, near and far fields can be close anything, as your objects all have zero as z coordinate:

glm::ortho(
    -1,  1,    // X goes -1 to 1
     1, -1,    // Y goes 1 (at bottom!) to -1 (at top!)
    -1, 1)     // -1 < 0 < 1

But you can get better. Use your window size parameters, and you can use regular pixel-based coordinates (instead of -1 ... 1 range):

glm::ortho(
    0, width,   // X goes 0 to width
    height, 0,  // Y goes 0 (top) to height (bottom)
    -1, 1)      // near & far

To make it with fixed pipeline (old OpenGL), use glOrtho().

Hope this was the problem, and if it was, hope this helps.

EDIT: Just in case... You can tweak perspective transformation even more to suit better tile based 2D games. Lets say your "unit size" of objects is like 32x32 (sprites, background tiles, etc). To get rid of multiplying and dividing with sprite width & length (converting map array indexes to screen coordinates and vice versa), just match coordinate "unit size" to tile size:

glm::ortho(
    0, width / tile.width,    // +1 X is +tile.width
    height / tile.height, 0,  // +1 Y is +tile.height
    -1, 1)                    // near & far

EDIT (see comments): Lets assume you use ortho(0, width, height, 0) to get "traditional" screen coordinates in pixels. To blit 32x32 bitmap to window, you have following rectangle constructed from two triangles:

uv (0, 0)               uv( 1, 0)
pos(0, 0)              pos(32, 0)
     +-----------------+
     |A               D|
     |                 |
     |B               C|
     +-----------------+
pos(0,32)              pos(32, 32)
uv (0, 1)              uv ( 1,  1)

Default winding is counter-clockwise (triangles ABC, CDA). "Reference" point can be also changed to center, using rectangle (-16, -16) - (16, 16). Furthermore: you can use "unitbox" (0,0)-(1,1) or (-0.5,-05)-(0.5,0.5), and scale it up to correct dimensions with model matrix you pass to shader. This allows you to easily use same box to blit textures in any sizes.

If you don't like to alter perspective, you can also do flipping by turning the rectangle you use to blit "upside down", and scaling the positions down to 32/width and 32/height (e.g. in model matrix). This affects to winding, so you may need to tweak face culling parameters (glCullFace, glFrontFace, glPolygonMode).

But IMO it is much more convenient for 2D graphics to tweak perspective and continue using "default" window coordinates you have used to use. 3D side is different beast.

Upvotes: 0

Related Questions