OpenGL Texture Coordinates in Pixel Space

I’m working on an iPhone app that uses OpenGL ES 2 for its drawing. I know that typically texture coordinates are defined in the 0-1 range, but ideally I’d like to map them from 0-1023 (the size of my TextureAtlas) for readability’s sake. I’ve seen sample code that defines coordinates in this manner, but haven’t been able to suss out what previous calls were made that allowed for this. glMatrixMode(GL_TEXTURE) seems like it might be involved, but I’m not quite sure how to implement it.

My end goal would be to accomplish something like this, where the texture I’d be using within the atlas is in the upper left 48px square:

  • How to merge two FBOs?
  • Why do I get the error “error: unknown type name 'virtual'” when trying to compile this code?
  • OpenGL ES 1.1 to 2.0 a major change?
  • EXC_BAD_ACCESS at lauch for EAGLContext renderbufferStorage: fromDrawable: in Cocos2d app whie debugging
  • ipad 3 - openGL bug with kEAGLDrawablePropertyRetainedBacking and retina?
  • Is OpenGL threadsafe for multiple threads with distinct contexts?
  • GLshort texcoords[]={
      48,48,
      0,48,
      48,0,
      0,0,
    };
    glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_SHORT, 0, 0, texcoords);
    glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
    

    3 Solutions Collect From Internet About “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.

    I waste 1 hour to find intuitive figure, but surprisingly nobody painted. So I did.

    Given 4 pixel texture, normalized texture coordinate [0,1], unnormalized texture coordinate [0, width), gl_FragCoord [0, width] are as follows

    enter image description here

    Reference

    1. p270 in https://www.khronos.org/registry/gles/specs/3.1/es_spec_3.1.pdf
    2. https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml
    3. https://www.opengl.org/wiki/Sampler_(GLSL)

    Turns out this is possible in OpenGl ES 2. Here’s how I accomplished it:

    Fragment Shader:

    precision mediump float; 
    varying vec2 v_texCoord;
    uniform sampler2D textureSample;
    uniform float texScale;
    void main()
    {
        vec2 mult=(2.0*v_texCoord - 1.0)/(2.0*texScale);
        gl_FragColor = texture2D(textureSample,mult);
    }
    

    Obj-C:

    GLshort texCoords[]={
        512,512,
        0,512,
        512,0,
        0,0,
    };
    GLfloat textureWidth = 512.0; //texture size, assumed square, power of 2
    texCoordLoc = glGetAttribLocation ( program, "a_texCoord");
    GLuint textureScale = glGetUniformLocation ( program, "texScale");
    glUniform1f(textureScale, textureWidth);
    glVertexAttribPointer ( texCoordLoc, 2, GL_SHORT, GL_FALSE, 0, texCoords);
    

    If anyone has comments on how this might work performance-wise, I would be interested.