Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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;
share|improve this question
up vote 1 down vote accepted

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.

share|improve this answer
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; – miviclin Dec 20 '12 at 17:18
Apologies, should have read your question more carefully =) – Jari Komppa Dec 20 '12 at 17:21
Um, you're not using varyings at all.. – Jari Komppa Dec 20 '12 at 17:22
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? – miviclin Dec 20 '12 at 22:26

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.