void CTextureAtlas::CreateTexture() { const int2 atlasSize = atlasAllocator->GetAtlasSize(); PBO pbo; pbo.Bind(); pbo.Resize(atlasSize.x * atlasSize.y * 4); unsigned char* data = (unsigned char*)pbo.MapBuffer(GL_WRITE_ONLY); { // make spacing between textures black transparent to avoid ugly lines with linear filtering std::memset(data, 0, atlasSize.x * atlasSize.y * 4); for (std::vector<MemTex*>::iterator it = memtextures.begin(); it != memtextures.end(); ++it) { const float4 texCoords = atlasAllocator->GetTexCoords((*it)->names[0]); const float4 absCoords = atlasAllocator->GetEntry((*it)->names[0]); const int xpos = absCoords.x; const int ypos = absCoords.y; AtlasedTexture tex(texCoords); for (size_t n = 0; n < (*it)->names.size(); ++n) { textures[(*it)->names[n]] = tex; } for (int y = 0; y < (*it)->ysize; ++y) { int* dst = ((int*)data) + xpos + (ypos + y) * atlasSize.x; int* src = ((int*)(*it)->data) + y * (*it)->xsize; memcpy(dst, src, (*it)->xsize * 4); } } if (debug) { CBitmap tex(data, atlasSize.x, atlasSize.y); tex.Save(name + "-" + IntToString(atlasSize.x) + "x" + IntToString(atlasSize.y) + ".png"); } } pbo.UnmapBuffer(); const int maxMipMaps = atlasAllocator->GetMaxMipMaps(); glGenTextures(1, &atlasTexID); glBindTexture(GL_TEXTURE_2D, atlasTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxMipMaps); if (maxMipMaps > 0) { glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, atlasSize.x, atlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); //FIXME disable texcompression //FIXME 2 PBO!!!! } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, atlasSize.x, atlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); } pbo.Unbind(); initialized = true; }
void CTextureAtlas::CreateTexture() { PBO pbo; pbo.Bind(); pbo.Resize(xsize * ysize * 4); unsigned char* data = (unsigned char*)pbo.MapBuffer(GL_WRITE_ONLY); std::memset(data, 0, xsize * ysize * 4); //! make spacing between textures black transparent to avoid ugly lines with linear filtering for (size_t i = 0; i < memtextures.size(); ++i) { MemTex& tex = *memtextures[i]; for (int y = 0; y < tex.ysize; ++y) { int* dst = ((int*)data) + tex.xpos + (tex.ypos + y) * xsize; int* src = ((int*)tex.data) + y * tex.xsize; memcpy(dst, src, tex.xsize * 4); } } if (debug) { //! hack to make sure we don't overwrite our own atlases static int count = 0; char fname[256]; SNPRINTF(fname, sizeof(fname), "textureatlas%d.png", ++count); //! even pbo.MapBuffer(GL_WRITE_ONLY) we can readback from it. GL_READ is only needed if we want to readback GPU data! CBitmap save(data,xsize,ysize); save.Save(fname); logOutput.Print("Saved finalized textureatlas to '%s'.", fname); } pbo.UnmapBuffer(); glGenTextures(1, &gltex); glBindTexture(GL_TEXTURE_2D, gltex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST/*GL_NEAREST_MIPMAP_LINEAR*/); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, xsize, ysize, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); pbo.Unbind(); initialized = true; }
void CTextureAtlas::CreateTexture() { const int2 atlasSize = atlasAllocator->GetAtlasSize(); xsize = atlasSize.x; ysize = atlasSize.y; PBO pbo; pbo.Bind(); pbo.Resize(atlasSize.x * atlasSize.y * 4); unsigned char* data = (unsigned char*)pbo.MapBuffer(GL_WRITE_ONLY); std::memset(data, 0, atlasSize.x * atlasSize.y * 4); // make spacing between textures black transparent to avoid ugly lines with linear filtering for(std::vector<MemTex*>::iterator it = memtextures.begin(); it != memtextures.end(); ++it) { float4 texCoords = atlasAllocator->GetTexCoords((*it)->names[0]); float4 absCoords = atlasAllocator->GetEntry((*it)->names[0]); const int xpos = absCoords.x; const int ypos = absCoords.y; AtlasedTexture tex(texCoords); for (size_t n = 0; n < (*it)->names.size(); ++n) { textures[(*it)->names[n]] = tex; } for (int y = 0; y < (*it)->ysize; ++y) { int* dst = ((int*)data) + xpos + (ypos + y) * atlasSize.x; int* src = ((int*)(*it)->data) + y * (*it)->xsize; memcpy(dst, src, (*it)->xsize * 4); } } if (debug) { // hack to make sure we don't overwrite our own atlases static int count = 0; char fname[256]; SNPRINTF(fname, sizeof(fname), "textureatlas%d.png", ++count); CBitmap save(data, atlasSize.x, atlasSize.y); save.Save(fname); LOG("Saved finalized texture-atlas to '%s'.", fname); } pbo.UnmapBuffer(); const int maxMipMaps = atlasAllocator->GetMaxMipMaps(); glGenTextures(1, &gltex); glBindTexture(GL_TEXTURE_2D, gltex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxMipMaps); if (maxMipMaps > 0) { glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, atlasSize.x, atlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); //FIXME disable texcompression //FIXME 2 PBO!!!! } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, atlasSize.x, atlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); } pbo.Unbind(); initialized = true; }
bool CTextureAtlas::CreateTexture() { const int2 atlasSize = atlasAllocator->GetAtlasSize(); const int maxMipMaps = atlasAllocator->GetMaxMipMaps(); // ATI drivers like to *crash* in glTexImage if x=0 or y=0 if (atlasSize.x <= 0 || atlasSize.y <= 0) { LOG_L(L_ERROR, "[TextureAtlas::%s] bad allocation for atlas \"%s\" (size=<%d,%d>)", __func__, name.c_str(), atlasSize.x, atlasSize.y); return false; } PBO pbo; pbo.Bind(); pbo.New(atlasSize.x * atlasSize.y * 4); unsigned char* data = reinterpret_cast<unsigned char*>(pbo.MapBuffer(GL_WRITE_ONLY)); if (data != nullptr) { // make spacing between textures black transparent to avoid ugly lines with linear filtering std::memset(data, 0, atlasSize.x * atlasSize.y * 4); for (const MemTex& memTex: memTextures) { const float4 texCoords = atlasAllocator->GetTexCoords(memTex.names[0]); const float4 absCoords = atlasAllocator->GetEntry(memTex.names[0]); const int xpos = absCoords.x; const int ypos = absCoords.y; const AtlasedTexture tex(texCoords); for (size_t n = 0; n < memTex.names.size(); ++n) { textures[memTex.names[n]] = tex; } for (int y = 0; y < memTex.ysize; ++y) { int* dst = ((int*) data ) + xpos + (ypos + y) * atlasSize.x; int* src = ((int*)memTex.mem.data()) + ( y) * memTex.xsize; memcpy(dst, src, memTex.xsize * 4); } } if (debug) { CBitmap tex(data, atlasSize.x, atlasSize.y); tex.Save(name + "-" + IntToString(atlasSize.x) + "x" + IntToString(atlasSize.y) + ".png"); } } else { LOG_L(L_ERROR, "[TextureAtlas::%s] failed to map PBO for atlas \"%s\" (size=<%d,%d>)", __func__, name.c_str(), atlasSize.x, atlasSize.y); } pbo.UnmapBuffer(); glGenTextures(1, &atlasTexID); glBindTexture(GL_TEXTURE_2D, atlasTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxMipMaps); if (maxMipMaps > 0) { glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, atlasSize.x, atlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); //FIXME disable texcompression, PBO } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, atlasSize.x, atlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pbo.GetPtr()); } pbo.Invalidate(); pbo.Unbind(); return (data != nullptr); }