How to Render Only a Section of a Texture (OpenGL 3.1)?

Started by
6 comments, last by swiftcoder 11 years, 4 months ago
Hello, I have a problem of which I couldn't seem to find any advice of on Google. I'm using a tileset creator (Tiled) for my game, which takes images and splits them up into tilesets for rendering. I figure this is very efficient and I would like to adopt this in my rendering. However, how can I actually just render a PORTION of a texture in OpenGL? Changing the texture coordinates does nothing more than just move the actual corners of the image. What I want to do is choose what area of the texture to render from, rather than having to split up the image into a bunch of smaller images and load them, which sounds extremely inefficient. Is this a GLSL or an OpenGL problem? Help!
Advertisement
Changing the texture coordinates on your vertices is pretty much the only efficient way to access a portion of your texture. (EDIT: This could be done by modifying the vertices on the CPU, or on the GPU by applying an offset and scale to the UVs in your vertex shader)

It's not clear from your post why you feel this is insufficient. Perhaps you need to have wrapping functionality - in which case you're unfortunately out of luck, there's no efficient way to wrap on a portion of a texture.
I don't see how this could be done CPU wise? But here's what I'm attempting to use to render a section of a texture (frag shader)
#version 140
in vec4 frag_color;
in vec2 frag_tex_coord;
uniform sampler2D tex;
uniform vec2 frag_tex_coord_offset;
void main(){
gl_FragColor = texture(tex, frag_tex_coord + frag_tex_coord_offset);
}
The UVs must be being created on the CPU from somewhere (e.g. are you loading a model from the disk, are you creating quads in a 2D renderer?).

In general if the vertices are dynamic (e.g. they're coming from your 2D system or your particle system or something), I'd imagine you're best off adjusting the vertex UVs before you render them. If the vertices are static (e.g. you're animating part of a world mesh, like a TV screen), then you might want to be doing something like your sample except:

1. You should do the offset in the vertex shader, not the fragment shader.
2. You probably need a scale as well as an offset.
The uvs are computed from xml files at run-time. But I can't 'skip' a portion of a texture using supplied uvs, right? Also, what I'm using is working, I just moved it to the fragment shader.

But I can't 'skip' a portion of a texture using supplied uvs, right?


Of course you can. Assuming you load a coordinate (u, v) from your source file you can adjust those texture coordinates to whatever you want before sending them to the graphics card.

For example the mesh assumes it has a texture of 128x128 pixels but in reality this texture is part of a bigger atlas texture (let's say 512x512, starting at (128, 64)). In this case you could simply transform the loaded (u, v) as such:

newU = (128.0f + (oldU * 128.0f)) / 512.0f;
newV = ( 64.0f + (oldV * 128.0f)) / 512.0f;
Ah well that makes sense. Although I thought UVs were only for supplying corners.

Although I thought UVs were only for supplying corners.

They supply the texture coordinate that matches the given vertex - if your vertices are all corners, then yes, your texture coordinates generally also define corners.

But that's just the trivial case of rendering quads. Consider a large mesh, such as a rectangular area of terrain: there will be many edge and interior vertices, in addition to the corners, and each has it's own texture coordinate, defining where on the texture should map to that vertex.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement