6

How can I get my textures to align with the screen pixels for pixel perfect graphics in OpenGL ES 2.0? This is critical for a project I'm working on which uses pixel art graphics. Any help on this would be great!

genpfault
  • 51,148
  • 11
  • 85
  • 139
Marc
  • 159
  • 2
  • 7
  • 1
    One more thing... make sure you have `precision highp float;` at the top of your shader. If your texture is larger than 1024x1024, mediump won't give you enough precision to sample every pixel in the texture. – Danny Dulai Jun 24 '15 at 21:08

2 Answers2

8

See my answer here: OpenGL Texture Coordinates in Pixel Space


This has been asked a few times, but I don't have the links at hand, so a quick and rough explanation. Let's say the texture is 8 pixels wide:

 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 ^   ^   ^   ^   ^   ^   ^   ^   ^
0.0  |   |   |   |   |   |   |  1.0
 |   |   |   |   |   |   |   |   |
0/8 1/8 2/8 3/8 4/8 5/8 6/8 7/8 8/8

The digits denote the texture's pixels, the bars the edges of the texture and in case of nearest filtering the border between pixels. You however want to hit the pixels' centers. So you're interested in the texture coordinates

(0/8 + 1/8)/2 = 1 / (2 * 8)

(1/8 + 2/8)/2 = 3 / (2 * 8)

...

(7/8 + 8/8)/2 = 15 / (2 * 8)

Or more generally for pixel i in a N wide texture the proper texture coordinate is

(2i + 1)/(2N)

However if you want to perfectly align your texture with the screen pixels, remember that what you specify as coordinates are not a quad's pixels, but edges, which, depending on projection may align with screen pixel edges, not centers, thus may require other texture coordinates.

Community
  • 1
  • 1
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • 1
    I disagree a bit - there is no reason to do anything special. GL ensures that the varying sample will always be calculated somewhere inside the pixel (usually the center), so there is no need to do anything special. Just draw the texture as a quad, use GL_NEAREST for texture filturing and (0,0,1,1) as your texture coordinates. As long as the the texture is the same size as the quad in screen space, your texture draw will be pixelperfect. – Arne Bergene Fossaa Sep 01 '11 at 21:07
1

This link may be usefull:

http://glprogramming.com/red/appendixg.html#name1

Look at "If exact two-dimensional rasterization is desired...". This OpenGl tip tells you how to best setup your ortho matrix for 2D.

Also, you may need to disable any kind of texture filtering.

neodelphi
  • 2,706
  • 1
  • 15
  • 22
  • That's good advice for legacy OpenGL, but doesn't apply directly to ES 2.0 – andrewmu Sep 01 '11 at 16:43
  • @andrewmu: Didn't knew it - Could you explain why ? Is ES so different ? – neodelphi Sep 01 '11 at 16:48
  • Thank you very much but as ardrewmu said, such matrix operations are not available in ES 2.0. Though had I looked at this before, It might have helped. – Marc Sep 01 '11 at 17:05
  • @neodelphi: in ES 2.0 it's very different. A lot has been removed since so much can be achieved with fragment and vertex shaders. – andrewmu Sep 01 '11 at 17:58
  • @andrewmu Ok. Couldn't the projection matrix with the right offsets be done in the vertex shader ? – neodelphi Sep 01 '11 at 18:09
  • @neodelphi Yes sir, thats exactly how I fixed my problem. – Marc Sep 01 '11 at 23:40