hey,
i was just trying to do something similar and built a subclass for ofTexture which does just this:
ofxTiledTexture.h
#ifndef _TILED_TEXTURE_H_
#define _TILED_TEXTURE_H_
#include "ofMain.h"
class ofxTiledTexture : public ofTexture {
public :
void allocate(int w, int h, int internalGlDataType);
void allocate(int w, int h, int internalGlDataType, bool smooth);
void draw(float x, float y, float w, float h, float p, float q);
};
#endif
ofxTiledTexture.cpp
#include "ofxTiledTexture.h"
//----------------------------------------------------------
void ofxTiledTexture::allocate(int w, int h, int internalGlDataType) {
allocate(w, h, internalGlDataType, true);
}
//----------------------------------------------------------
void ofxTiledTexture::allocate(int w, int h, int internalGlDataType, bool smooth) {
// can pass in anything (320x240) (10x5)
// here we make it power of 2 for opengl (512x256), (16x8)
if (GLEE_ARB_texture_rectangle){
tex_w = w;
tex_h = h;
} else {
tex_w = ofNextPow2(w);
tex_h = ofNextPow2(h);
}
if (GLEE_ARB_texture_rectangle){
tex_t = w;
tex_u = h;
} else {
tex_t = 1.0f;
tex_u = 1.0f;
}
// attempt to free the previous bound texture, if we can:
clear();
glGenTextures(1, (GLuint *)textureName); // could be more then one, but for now, just one
glEnable(textureTarget);
glBindTexture(textureTarget, (GLuint)textureName[0]);
glTexImage2D(textureTarget, 0, internalGlDataType, tex_w, tex_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); // init to black...
glTexParameterf(textureTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(textureTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
if (smooth) {
glTexParameterf(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
glTexParameterf(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(textureTarget);
width = w;
height = h;
bFlipTexture = false;
}
//----------------------------------------------------------
void ofxTiledTexture::draw(float x, float y, float w, float h, float p, float q) {
glEnable(textureTarget);
// bind the texture
glBindTexture( textureTarget, (GLuint)textureName[0] );
GLint px0 = 0; // up to you to get the aspect ratio right
GLint py0 = 0;
GLint px1 = (GLint)w;
GLint py1 = (GLint)h;
if (bFlipTexture == true){
GLint temp = py0;
py0 = py1;
py1 = temp;
}
// for rect mode center, let's do this:
if (ofGetRectMode() == OF_RECTMODE_CENTER){
px0 = (GLint)-w/2;
py0 = (GLint)-h/2;
px1 = (GLint)+w/2;
py1 = (GLint)+h/2;
}
// -------------------------------------------------
// complete hack to remove border artifacts.
// slightly, slightly alters an image, scaling...
// to remove the border.
// we need a better solution for this, but
// to constantly add a 2 pixel border on all uploaded images
// is insane..
GLfloat offsetw = 0;
GLfloat offseth = 0;
if (textureTarget == GL_TEXTURE_2D){
offsetw = 1.0f/(tex_w);
offseth = 1.0f/(tex_h);
}
// -------------------------------------------------
GLfloat tx0 = 0+offsetw;
GLfloat ty0 = 0+offseth;
GLfloat tx1 = tex_t - offsetw;
GLfloat ty1 = tex_u - offseth;
glPushMatrix();
glTranslated(x, y, 0);
float s = (px1-px0)/p;
float t = (py1-py0)/q;
for (int j = 0; j < q; j++) {
for (int i = 0; i < p; i++) {
glBegin(GL_QUADS);
glTexCoord2f(tx0,ty0); glVertex3i(px0+i*s, py0+j*t, 0);
glTexCoord2f(tx1,ty0); glVertex3i(px0+(i+1)*s, py0+j*t, 0);
glTexCoord2f(tx1,ty1); glVertex3i(px0+(i+1)*s, py0+(j+1)*t, 0);
glTexCoord2f(tx0,ty1); glVertex3i(px0+i*s, py0+(j+1)*t, 0);
glEnd();
}
}
glPopMatrix();
glDisable(textureTarget);
}
and a nice example using live video…
testApp.h
#ifndef _TEST_APP
#define _TEST_APP
#include "ofMain.h"
#include "ofAddons.h"
#include "ofxTiledTexture.h"
class testApp : public ofSimpleApp {
public:
void setup();
void update();
void draw();
void mouseMoved(int x, int y);
private:
int mouseX;
int mouseY;
ofxTiledTexture tex;
ofVideoGrabber video;
};
#endif
testApp.cpp
#include "testApp.h"
//--------------------------------------------------------------
void testApp::setup() {
video.initGrabber(160, 120);
tex.allocate(video.width, video.height, GL_RGB);
}
//--------------------------------------------------------------
void testApp::update() {
video.grabFrame();
if (video.isFrameNew()) {
tex.loadData(video.getPixels(), video.width, video.height, GL_RGB);
}
}
//--------------------------------------------------------------
void testApp::draw() {
tex.draw(0, 0, ofGetWidth(), ofGetHeight(), ofGetWidth()/float(ABS(mouseX)+1), ofGetHeight()/float(ABS(mouseY)+1));
}
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y) {
mouseX = x;
mouseY = y;
}
enjoy!