struct ClampedTex { GLuint id; bool clamped; ClampedTex() : clamped(0) { glGenTextures(1, &id); } ~ClampedTex() { /*if (id) glDeleteTextures(1, &id);*/ } }; void clampTexture2D(float bordercolor, int w = 128, int h = 128, int c = 3) { static std::map clampedmap; GLuint id; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)(&id)); ClampedTex &t = clampedmap[id]; assert(c == 3); if (!t.clamped) { cout << "Creating a clamped version of texture " << id << " into texture " << t.id << "\n"; t.clamped = true; float *data = new float[w*h*c]; int level = 0; for (;;) { glBindTexture(GL_TEXTURE_2D, id); GLERR; glGetTexImage(GL_TEXTURE_2D, level, GL_RGB, GL_FLOAT, data); GLERR; for (int i = 0; i < w; i++) for (int a = 0; a < c; a++) { data[( i) * c + a] = bordercolor; data[((h-1) * w + i) * c + a] = bordercolor; } for (int i = 0; i < h; i++) for (int a = 0; a < c; a++) { data[(i * w ) * c + a] = bordercolor; data[(i * w + (w-1)) * c + a] = bordercolor; } glBindTexture(GL_TEXTURE_2D, t.id); GLERR; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_FLOAT, data); GLERR; level++; // XXX: bordering the lower LOD's does not seem to work break; if (w <= 1 && h <= 1) break; h = h+1>>1; w = w+1>>1; } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level - 1); GLERR; glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GLERR; } else { glBindTexture(GL_TEXTURE_2D, t.id); GLERR; } }