I'm trying to write a shader that only maps a portion of a large texture to my sprite and I'm getting a strange behaviour with my current code.
This is what I have right now:

Texture atlas example (256x256px):
256x256 texture atlas example

I've changed both shaders and I get the following output right now (first image), but I need to zoom the texture so I only render the highlighted portion of the second image, how should I modify the shaders to achieve that?
atlas example 2 -> atlas example 2 highlight

These are my current shaders:

uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec2 aTextureCoord;
varying vec2 vTextureCoord;
varying vec2 vTextureCoordOffset;
void main() {
    // offset and texSize will be defined as attributes later.
    // They're defined here for test purposes only
    vec2 offset = vec2(128.0, 64.0);
    vec2 texSize = vec2(256.0, 256.0);

    float u = offset.x / texSize.x;
    float v = offset.y / texSize.y;
    vTextureCoordOffset = vec2(u, v);
    vTextureCoord = aTextureCoord;
    gl_Position = uMVPMatrix * aPosition;


precision mediump float;
uniform sampler2D sTexture;
varying vec2 vTextureCoord;
varying vec2 vTextureCoordOffset;
void main() {
    gl_FragColor = texture2D(sTexture, fract(vTextureCoord) + vTextureCoordOffset);

I solved it changing the fragment shader to:

gl_FragColor = texture2D(sTexture, fract(vTextureCoord) * vZoom + vTextureCoordOffset);

vZoom is calculated in the vertex shader:

vZoom = subTextureSize / texSize;

1 Answer 1


You're not interpolating the texture coordinates at all. You're sampling a single point at all times.

f(N) = (N + 0.5) / 256

N = 0 -> 0.001953125
N = 64 -> 0.251953125
N = 128 -> 0.501953125

So in case of (0,0) you're always sampling a point near top corner, and with (128,128) you're sampling a single point near the center, but somewhat on the magenta (although bilinear interpolation may cause other colors to appear).

You should be using varyings to interpolate the texture.. and while at it, you might want to do all of these calculations on the vertex shader, so they're done per polygon instead of per pixel.

  • \$\begingroup\$ I'm still quite lost, could you extend a little more please? I think the coordinates should be in the 0..1 range when I do this: float u = (x + 0.5) / texSize.x; float v = (y + 0.5) / texSize.y; \$\endgroup\$
    – miviclin
    Dec 20, 2012 at 17:18
  • \$\begingroup\$ Apologies, should have read your question more carefully =) \$\endgroup\$ Dec 20, 2012 at 17:21
  • \$\begingroup\$ Um, you're not using varyings at all.. \$\endgroup\$ Dec 20, 2012 at 17:22
  • \$\begingroup\$ I solved part of the problem using varyings, thank you! But I'm still having some troubles (I've updated the question), might you take a look at it? \$\endgroup\$
    – miviclin
    Dec 20, 2012 at 22:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .