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:
GLshort texcoords[]={
48,48,
0,48,
48,0,
0,0,
};
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_SHORT, 0, 0, texcoords);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
Texture coordinates specify the point in the texture image that will correspond to the vertex you are specifying them for. Think of a rectangular rubber sheet with your texture image printed on it, where the length of each side is normalized to the range 0-1.
in display() function : GLuint texture; texture = LoadTexture("bubble. png"); glBindTexture(GL_TEXTURE_2D, texture);
GL_NEAREST (also known as nearest neighbor or point filtering) is the default texture filtering method of OpenGL. When set to GL_NEAREST , OpenGL selects the texel that center is closest to the texture coordinate. Below you can see 4 pixels where the cross represents the exact texture coordinate.
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
Reference
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With