void CBasicTreeDrawer::CreateTreeTex(GLuint& texnum, unsigned char *data, int xsize, int ysize) { glGenTextures(1, &texnum); glBindTexture(GL_TEXTURE_2D, texnum); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, data); }
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; }
const unsigned int CBitmap::CreateTexture(bool mipmaps) const { ScopedTimer timer("Textures::CBitmap::CreateTexture"); if (type == BitmapTypeDDS) { return CreateDDSTexture(); } if (mem == NULL) { return 0; } // jcnossen: Some drivers return "2.0" as a version string, // but switch to software rendering for non-power-of-two textures. // GL_ARB_texture_non_power_of_two indicates that the hardware will actually support it. if (!globalRendering->supportNPOTs && (xsize != next_power_of_2(xsize) || ysize != next_power_of_2(ysize))) { CBitmap bm = CreateRescaled(next_power_of_2(xsize), next_power_of_2(ysize)); return bm.CreateTexture(mipmaps); } unsigned int texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //FIXME add glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for NPOTs if (mipmaps) { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, mem); } else { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,xsize, ysize, 0,GL_RGBA, GL_UNSIGNED_BYTE, mem); //gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, mem); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, xsize, ysize, 0, GL_RGBA, GL_UNSIGNED_BYTE, mem); } return texture; }
CInMapDraw::CInMapDraw(void) { keyPressed = false; wantLabel = false; drawAll = false; allowSpecMapDrawing = true; allowLuaMapDrawing = true; lastLineTime = 0; lastLeftClickTime = 0; lastPos = float3(1, 1, 1); drawQuadsX = gs->mapx / DRAW_QUAD_SIZE; drawQuadsY = gs->mapy / DRAW_QUAD_SIZE; numQuads = drawQuadsX * drawQuadsY; drawQuads.resize(numQuads); unsigned char tex[64][128][4]; for (int y = 0; y < 64; y++) { for (int x = 0; x < 128; x++) { tex[y][x][0] = 0; tex[y][x][1] = 0; tex[y][x][2] = 0; tex[y][x][3] = 0; } } #define SMOOTHSTEP(x,y,a) (unsigned char)(x * (1.0f - a) + y * a) for (int y = 0; y < 64; y++) { // circular thingy for (int x = 0; x < 64; x++) { float dist = sqrt((float)(x - 32) * (x - 32) + (y - 32) * (y - 32)); if (dist > 31.0f) { // do nothing - leave transparent } else if (dist > 30.0f) { // interpolate (outline -> nothing) float a = (dist - 30.0f); tex[y][x][3] = SMOOTHSTEP(255,0,a); } else if (dist > 24.0f) { // black outline tex[y][x][3] = 255; } else if (dist > 23.0f) { // interpolate (inner -> outline) float a = (dist - 23.0f); tex[y][x][0] = SMOOTHSTEP(255,0,a); tex[y][x][1] = SMOOTHSTEP(255,0,a); tex[y][x][2] = SMOOTHSTEP(255,0,a); tex[y][x][3] = SMOOTHSTEP(200,255,a); } else { tex[y][x][0] = 255; tex[y][x][1] = 255; tex[y][x][2] = 255; tex[y][x][3] = 200; } } } for (int y = 0; y < 64; y++) { // linear falloff for (int x = 64; x < 128; x++) { float dist = abs(y - 32); if (dist > 31.0f) { // do nothing - leave transparent } else if (dist > 30.0f) { // interpolate (outline -> nothing) float a = (dist - 30.0f); tex[y][x][3] = SMOOTHSTEP(255,0,a); } else if (dist > 24.0f) { // black outline tex[y][x][3] = 255; } else if (dist > 23.0f) { // interpolate (inner -> outline) float a = (dist - 23.0f); tex[y][x][0] = SMOOTHSTEP(255,0,a); tex[y][x][1] = SMOOTHSTEP(255,0,a); tex[y][x][2] = SMOOTHSTEP(255,0,a); tex[y][x][3] = SMOOTHSTEP(200,255,a); } else { tex[y][x][0] = 255; tex[y][x][1] = 255; tex[y][x][2] = 255; tex[y][x][3] = 200; } } } glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_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); glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, 128, 64, GL_RGBA, GL_UNSIGNED_BYTE, tex[0]); blippSound = sound->GetSoundId("MapPoint", false); }
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; }
CInMapDrawView::CInMapDrawView() { unsigned char tex[64][128][4]; for (int y = 0; y < 64; y++) { for (int x = 0; x < 128; x++) { tex[y][x][0] = 0; tex[y][x][1] = 0; tex[y][x][2] = 0; tex[y][x][3] = 0; } } for (int y = 0; y < 64; y++) { // circular thingy for (int x = 0; x < 64; x++) { float dist = math::sqrt((float)(x - 32) * (x - 32) + (y - 32) * (y - 32)); if (dist > 31.0f) { // do nothing - leave transparent } else if (dist > 30.0f) { // interpolate (outline -> nothing) float a = (dist - 30.0f); tex[y][x][3] = smoothStep(255, 0, a); } else if (dist > 24.0f) { // black outline tex[y][x][3] = 255; } else if (dist > 23.0f) { // interpolate (inner -> outline) float a = (dist - 23.0f); tex[y][x][0] = smoothStep(255, 0, a); tex[y][x][1] = smoothStep(255, 0, a); tex[y][x][2] = smoothStep(255, 0, a); tex[y][x][3] = smoothStep(200, 255, a); } else { tex[y][x][0] = 255; tex[y][x][1] = 255; tex[y][x][2] = 255; tex[y][x][3] = 200; } } } for (int y = 0; y < 64; y++) { // linear falloff for (int x = 64; x < 128; x++) { float dist = abs(y - 32); if (dist > 31.0f) { // do nothing - leave transparent } else if (dist > 30.0f) { // interpolate (outline -> nothing) float a = (dist - 30.0f); tex[y][x][3] = smoothStep(255, 0, a); } else if (dist > 24.0f) { // black outline tex[y][x][3] = 255; } else if (dist > 23.0f) { // interpolate (inner -> outline) float a = (dist - 23.0f); tex[y][x][0] = smoothStep(255, 0, a); tex[y][x][1] = smoothStep(255, 0, a); tex[y][x][2] = smoothStep(255, 0, a); tex[y][x][3] = smoothStep(200, 255, a); } else { tex[y][x][0] = 255; tex[y][x][1] = 255; tex[y][x][2] = 255; tex[y][x][3] = 200; } } } glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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); glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, 128, 64, GL_RGBA, GL_UNSIGNED_BYTE, tex[0]); }
Lightmap::Lightmap(Heightmap *orghm, int level, int shadowLevelDif, LightingInfo *li) { int startTicks = SDL_GetTicks(); tilesize.x = orghm->w-1; tilesize.y = orghm->h-1; name = "lightmap"; Heightmap *hm; int w; for(;;) { hm = orghm->GetLevel(-level); w=hm->w-1; GLint maxw; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxw); if (w > maxw) level ++; else break; } shadowLevelDif=0; Heightmap *shadowhm = orghm->GetLevel(-(level+shadowLevelDif)); int shadowScale=1<<shadowLevelDif; int shadowW=shadowhm->w-1; assert (w/shadowW == shadowScale); //float org2c = w/float(orghm->w-1); //float c2org = (float)(orghm->w-1)/w; float *centerhm = SAFE_NEW float[w*w]; Vector3 *shading = SAFE_NEW Vector3[w*w]; for (int y=0;y<w;y++) for (int x=0;x<w;x++) { centerhm[y*w+x] =/* hm->scale * */ 0.25f * ( (int)hm->at(x,y)+ (int)hm->at(x+1,y)+ (int)hm->at(x,y+1) + (int)hm->at(x+1,y+1) ); //+ hm->offset; shading[y*w+x] = li->ambient; } uchar *lightMap = SAFE_NEW uchar[shadowW*shadowW]; for (std::vector<StaticLight>::const_iterator l=li->staticLights.begin();l!=li->staticLights.end();++l) { float lightx; float lighty; if (l->directional) { lightx = l->position.x; lighty = l->position.y; } else { lightx = (int)(l->position.x / shadowhm->squareSize); lighty = (int)(l->position.z / shadowhm->squareSize); } CalculateShadows(lightMap, shadowW, lightx, lighty, l->position.y, centerhm, w, shadowScale, l->directional); for (int y=0;y<w;y++) { for (int x=0;x<w;x++) { if (!lightMap[(y*shadowW+x)/shadowScale]) continue; Vector3 wp; if (l->directional) wp = l->position; else wp = l->position - Vector3((x+0.5f)*hm->squareSize,centerhm[y*w+x],(y+0.5f)*hm->squareSize); uchar* normal = hm->GetNormal (x,y); Vector3 normv((2 * (int)normal[0] - 256)/255.0f, (2 * (int)normal[1] - 256)/255.0f, (2 * (int)normal[2] - 256)/255.0f); wp.Normalize(); float dot = wp.dot(normv); if(dot < 0.0f) dot = 0.0f; if(dot > 1.0f) dot = 1.0f; dot *= lightMap[(y*shadowW+x)/shadowScale]*(1.0f/255.0f); shading[y*w+x] += l->color * dot; } } } delete[] lightMap; glGenTextures(1,&shadingTex); glBindTexture (GL_TEXTURE_2D, shadingTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); uchar *shadingTexData=SAFE_NEW uchar[w*w*4]; for(int y=0;y<w;y++) { for (int x=0;x<w;x++) { shadingTexData[(y*w+x)*4+0] = (uchar)(min(1.0f, shading[y*w+x].x) * 255); shadingTexData[(y*w+x)*4+1] = (uchar)(min(1.0f, shading[y*w+x].y) * 255); shadingTexData[(y*w+x)*4+2] = (uchar)(min(1.0f, shading[y*w+x].z) * 255); shadingTexData[(y*w+x)*4+3] = CReadMap::EncodeHeight(centerhm[w*y+x]); } } SaveImage ("lightmap.png", 4, IL_UNSIGNED_BYTE, w,w, shadingTexData); glBuildMipmaps(GL_TEXTURE_2D, 4, w,w, GL_RGBA, GL_UNSIGNED_BYTE, shadingTexData); delete[] shadingTexData; id = shadingTex; delete[] shading; delete[] centerhm; int numTicks = SDL_GetTicks() - startTicks; d_trace ("Lightmap generation: %2.3f seconds\n", numTicks * 0.001f); }
/* #define W_SIZE 4 #define WF_SIZE 4096 #define WH_SIZE 2048 */ CDynWater::CDynWater(void) { if (!FBO::IsSupported()) throw content_error("DynWater Error: missing FBO support"); lastWaveFrame=0; noWakeProjectiles=true; firstDraw=true; drawSolid=true; camPosBig=float3(2048,0,2048); refractSize=gu->viewSizeY>=1024 ? 1024:512; glGenTextures(1, &reflectTexture); glBindTexture(GL_TEXTURE_2D, reflectTexture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,512, 512, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0); glGenTextures(1, &refractTexture); glBindTexture(GL_TEXTURE_2D, refractTexture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,refractSize, refractSize, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0); glGenTextures(1, &detailNormalTex); glBindTexture(GL_TEXTURE_2D, detailNormalTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,256, 256, 0,GL_RGBA, GL_FLOAT, 0); glGenerateMipmapEXT(GL_TEXTURE_2D); float* temp=new float[1024*1024*4]; for(int y=0;y<64;++y){ for(int x=0;x<64;++x){ temp[(y*64+x)*4+0]=(sin(x*PI*2.0f/64.0f)) + (x<32 ? -1:1)*0.3f; temp[(y*64+x)*4+1]=temp[(y*64+x)*4+0]; temp[(y*64+x)*4+2]=(cos(x*PI*2.0f/64.0f)) + (x<32 ? 16-x:x-48)/16.0f*0.3f; temp[(y*64+x)*4+3]=0; } } glGenTextures(3, rawBumpTexture); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,64, 64, 0,GL_RGBA, GL_FLOAT, temp); CBitmap foam; if (!foam.Load(mapInfo->water.foamTexture)) throw content_error("Could not load foam from file " + mapInfo->water.foamTexture); if (count_bits_set(foam.xsize)!=1 || count_bits_set(foam.ysize)!=1) throw content_error("Foam texture not power of two!"); unsigned char* scrap=new unsigned char[foam.xsize*foam.ysize*4]; for(int a=0;a<foam.xsize*foam.ysize;++a) scrap[a]=foam.mem[a*4]; glGenTextures(1, &foamTex); glBindTexture(GL_TEXTURE_2D, foamTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glBuildMipmaps(GL_TEXTURE_2D, GL_LUMINANCE,foam.xsize,foam.ysize, GL_LUMINANCE, GL_UNSIGNED_BYTE, scrap); delete[] scrap; if(ProgramStringIsNative(GL_VERTEX_PROGRAM_ARB,"waterDyn.vp")) waterVP=LoadVertexProgram("waterDyn.vp"); else waterVP=LoadVertexProgram("waterDynNT.vp"); waterFP=LoadFragmentProgram("waterDyn.fp"); waveFP=LoadFragmentProgram("waterDynWave.fp"); waveVP=LoadVertexProgram("waterDynWave.vp"); waveFP2=LoadFragmentProgram("waterDynWave2.fp"); waveVP2=LoadVertexProgram("waterDynWave2.vp"); waveNormalFP=LoadFragmentProgram("waterDynNormal.fp"); waveNormalVP=LoadVertexProgram("waterDynNormal.vp"); waveCopyHeightFP=LoadFragmentProgram("waterDynWave3.fp"); waveCopyHeightVP=LoadVertexProgram("waterDynWave3.vp"); dwGroundRefractVP=LoadVertexProgram("dwgroundrefract.vp"); dwGroundReflectIVP=LoadVertexProgram("dwgroundreflectinverted.vp"); dwDetailNormalFP=LoadFragmentProgram("dwDetailNormal.fp"); dwDetailNormalVP=LoadVertexProgram("dwDetailNormal.vp"); dwAddSplashFP=LoadFragmentProgram("dwAddSplash.fp"); dwAddSplashVP=LoadVertexProgram("dwAddSplash.vp"); waterSurfaceColor = mapInfo->water.surfaceColor; for(int y=0;y<1024;++y){ for(int x=0;x<1024;++x){ temp[(y*1024+x)*4+0]=0; temp[(y*1024+x)*4+1]=0; temp[(y*1024+x)*4+2]=0; temp[(y*1024+x)*4+3]=0; } } glGenTextures(1, &waveHeight32); glBindTexture(GL_TEXTURE_2D, waveHeight32); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,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); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F_ARB ,256, 256, 0,GL_RGBA, GL_FLOAT, temp); glGenTextures(1, &waveTex1); glBindTexture(GL_TEXTURE_2D, waveTex1); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp); for(int y=0;y<1024;++y){ for(int x=0;x<1024;++x){ //float dist=(x-500)*(x-500)+(y-450)*(y-450); temp[(y*1024+x)*4+0]=0;//max(0.0f,15-sqrt(dist));//sin(y*PI*2.0f/64.0f)*0.5f+0.5f; temp[(y*1024+x)*4+1]=0; temp[(y*1024+x)*4+2]=0; temp[(y*1024+x)*4+3]=0; } } glGenTextures(1, &waveTex2); glBindTexture(GL_TEXTURE_2D, waveTex2); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp); for(int y=0;y<1024;++y){ for(int x=0;x<1024;++x){ temp[(y*1024+x)*4+0]=0; temp[(y*1024+x)*4+1]=1; temp[(y*1024+x)*4+2]=0; temp[(y*1024+x)*4+3]=0; } } glGenTextures(1, &waveTex3); glBindTexture(GL_TEXTURE_2D, waveTex3); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp); for(int y=0;y<64;++y){ float dy=y-31.5f; for(int x=0;x<64;++x){ float dx=x-31.5f; float dist=sqrt(dx*dx+dy*dy); temp[(y*64+x)*4+0]=std::max(0.0f,1-dist/30.f)*std::max(0.0f,1-dist/30.f); temp[(y*64+x)*4+1]=std::max(0.0f,1-dist/30.f); temp[(y*64+x)*4+2]=std::max(0.0f,1-dist/30.f)*std::max(0.0f,1-dist/30.f); temp[(y*64+x)*4+3]=0; } } glGenTextures(1, &splashTex); glBindTexture(GL_TEXTURE_2D, splashTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_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); //gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA32F_ARB ,64, 64, GL_RGBA, GL_FLOAT, temp); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,64, 64, 0,GL_RGBA, GL_FLOAT, temp); unsigned char temp2[]={0,0,0,0}; glGenTextures(1, &zeroTex); glBindTexture(GL_TEXTURE_2D, zeroTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,1, 1, 0,GL_RGBA, GL_UNSIGNED_BYTE, temp2); unsigned char temp3[]={0,255,0,0}; glGenTextures(1, &fixedUpTex); glBindTexture(GL_TEXTURE_2D, fixedUpTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,1, 1, 0,GL_RGBA, GL_UNSIGNED_BYTE, temp3); CBitmap bm; if (!bm.Load("bitmaps/boatshape.bmp")) throw content_error("Could not load boatshape from file bitmaps/boatshape.bmp"); for(int a=0;a<bm.xsize*bm.ysize;++a){ bm.mem[a*4+2]=bm.mem[a*4]; bm.mem[a*4+3]=bm.mem[a*4]; } boatShape=bm.CreateTexture(); CBitmap bm2; if (!bm.Load("bitmaps/hovershape.bmp")) throw content_error("Could not load hovershape from file bitmaps/hovershape.bmp"); for(int a=0;a<bm2.xsize*bm2.ysize;++a){ bm2.mem[a*4+2]=bm2.mem[a*4]; bm2.mem[a*4+3]=bm2.mem[a*4]; } hoverShape=bm2.CreateTexture(); delete[] temp; glGenFramebuffersEXT(1,&frameBuffer); reflectFBO.Bind(); reflectFBO.AttachTexture(reflectTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT); reflectFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT32, 512, 512); refractFBO.Bind(); refractFBO.AttachTexture(refractTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT); refractFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT32, refractSize, refractSize); FBO::Unbind(); if (!reflectFBO.IsValid() || !refractFBO.IsValid()) throw content_error("DynWater Error: Invalid FBO"); }
bool CNamedTextures::Load(const string& texName, GLuint texID) { //! strip off the qualifiers string filename = texName; bool border = false; bool clamped = false; bool nearest = false; bool linear = false; bool aniso = false; bool invert = false; bool greyed = false; bool tint = false; float tintColor[3]; bool resize = false; int2 resizeDimensions; if (filename[0] == ':') { int p; for (p = 1; p < (int)filename.size(); p++) { const char ch = filename[p]; if (ch == ':') { break; } else if (ch == 'n') { nearest = true; } else if (ch == 'l') { linear = true; } else if (ch == 'a') { aniso = true; } else if (ch == 'i') { invert = true; } else if (ch == 'g') { greyed = true; } else if (ch == 'c') { clamped = true; } else if (ch == 'b') { border = true; } else if (ch == 't') { const char* cstr = filename.c_str() + p + 1; const char* start = cstr; char* endptr; tintColor[0] = (float)strtod(start, &endptr); if ((start != endptr) && (*endptr == ',')) { start = endptr + 1; tintColor[1] = (float)strtod(start, &endptr); if ((start != endptr) && (*endptr == ',')) { start = endptr + 1; tintColor[2] = (float)strtod(start, &endptr); if (start != endptr) { tint = true; p += (endptr - cstr); } } } } else if (ch == 'r') { const char* cstr = filename.c_str() + p + 1; const char* start = cstr; char* endptr; resizeDimensions.x = (int)strtoul(start, &endptr, 10); if ((start != endptr) && (*endptr == ',')) { start = endptr + 1; resizeDimensions.y = (int)strtoul(start, &endptr, 10); if (start != endptr) { resize = true; p += (endptr - cstr); } } } } if (p < (int)filename.size()) { filename = filename.substr(p + 1); } else { filename.clear(); } } //! get the image CBitmap bitmap; TexInfo texInfo; if (!bitmap.Load(filename)) { texMap[texName] = texInfo; glBindTexture(GL_TEXTURE_2D, 0); return false; } if (bitmap.type == CBitmap::BitmapTypeDDS) { texID = bitmap.CreateDDSTexture(texID); } else { if (resize) { bitmap = bitmap.CreateRescaled(resizeDimensions.x,resizeDimensions.y); } if (invert) { bitmap.InvertColors(); } if (greyed) { bitmap.GrayScale(); } if (tint) { bitmap.Tint(tintColor); } //! make the texture glBindTexture(GL_TEXTURE_2D, texID); if (clamped) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } if (nearest || linear) { if (border) { GLfloat white[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, white); } if (nearest) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } //! Note: NPOTs + nearest filtering seems broken on ATIs if ( !(count_bits_set(bitmap.xsize)==1 && count_bits_set(bitmap.ysize)==1) && (!GLEW_ARB_texture_non_power_of_two || (gu->atiHacks && nearest)) ) { bitmap = bitmap.CreateRescaled(next_power_of_2(bitmap.xsize),next_power_of_2(bitmap.ysize)); } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bitmap.xsize, bitmap.ysize, border ? 1 : 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem); } else { //! MIPMAPPING (default) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); if ((count_bits_set(bitmap.xsize)==1 && count_bits_set(bitmap.ysize)==1) || GLEW_ARB_texture_non_power_of_two) { glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, bitmap.xsize, bitmap.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem); } else { //! glu auto resizes to next POT gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, bitmap.xsize, bitmap.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem); } } if (aniso && GLEW_EXT_texture_filter_anisotropic) { static GLfloat maxAniso = -1.0f; if (maxAniso == -1.0f) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso); } } texInfo.id = texID; texInfo.type = bitmap.type; texInfo.xsize = bitmap.xsize; texInfo.ysize = bitmap.ysize; texMap[texName] = texInfo; return 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); }
CGrassDrawer::CGrassDrawer() : grassOff(false) , grassDL(0) , grassBladeTex(0) , farTex(0) , grassMap(nullptr) { const int detail = configHandler->GetInt("GrassDetail"); // some ATI drivers crash with grass enabled, default to disabled if ((detail == 0) || ((detail == 7) && globalRendering->haveATI)) { grassOff = true; return; } if (!GLEW_EXT_framebuffer_blit) { grassOff = true; return; } { MapBitmapInfo grassbm; unsigned char* grassdata = readMap->GetInfoMap("grass", &grassbm); if (!grassdata) { grassOff = true; return; } if (grassbm.width != gs->mapx / grassSquareSize || grassbm.height != gs->mapy / grassSquareSize) { char b[128]; SNPRINTF(b, sizeof(b), "grass-map has wrong size (%dx%d, should be %dx%d)\n", grassbm.width, grassbm.height, gs->mapx / 4, gs->mapy / 4); throw std::runtime_error(b); } const int grassMapSize = gs->mapx * gs->mapy / (grassSquareSize * grassSquareSize); grassMap = new unsigned char[grassMapSize]; memcpy(grassMap, grassdata, grassMapSize); readMap->FreeInfoMap("grass", grassdata); } ChangeDetail(detail); blocksX = gs->mapx / grassSquareSize / grassBlockSize; blocksY = gs->mapy / grassSquareSize / grassBlockSize; rng.Seed(15); grassDL = glGenLists(1); CreateGrassDispList(grassDL); { CBitmap grassBladeTexBM; if (!grassBladeTexBM.Load(mapInfo->grass.grassBladeTexName)) { //! map didn't define a grasstex, so generate one grassBladeTexBM.channels = 4; grassBladeTexBM.Alloc(256,64); for (int a = 0; a < 16; ++a) { CreateGrassBladeTex(&grassBladeTexBM.mem[a * 16 * 4]); } } glGenTextures(1, &grassBladeTex); glBindTexture(GL_TEXTURE_2D, grassBladeTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, grassBladeTexBM.xsize, grassBladeTexBM.ysize, GL_RGBA, GL_UNSIGNED_BYTE, &grassBladeTexBM.mem[0]); } CreateFarTex(); LoadGrassShaders(); configHandler->NotifyOnChange(this); }
C3DOTextureHandler::C3DOTextureHandler() { std::vector<TexFile*> texfiles = LoadTexFiles(); // TODO: make this use TextureAtlas directly CTextureAtlas atlas; atlas.SetName("3DOModelTextureAtlas"); IAtlasAllocator* atlasAlloc = atlas.GetAllocator(); // NOTE: most Intels report maxTextureSize=2048, some even 1024 (!) atlasAlloc->SetNonPowerOfTwo(globalRendering->supportNPOTs); atlasAlloc->SetMaxSize(std::min(globalRendering->maxTextureSize, 2048), std::min(globalRendering->maxTextureSize, 2048)); // default for 3DO primitives that point to non-existing textures textures["___dummy___"] = UnitTexture(0.0f, 0.0f, 1.0f, 1.0f); for (std::vector<TexFile*>::iterator it = texfiles.begin(); it != texfiles.end(); ++it) { atlasAlloc->AddEntry((*it)->name, int2((*it)->tex.xsize, (*it)->tex.ysize)); } const bool allocated = atlasAlloc->Allocate(); const int2 curAtlasSize = atlasAlloc->GetAtlasSize(); const int2 maxAtlasSize = atlasAlloc->GetMaxSize(); if (!allocated) { // either the algorithm simply failed to fit all // textures or the textures would really not fit LOG_L(L_WARNING, "[%s] failed to allocate 3DO texture-atlas memory (size=%dx%d max=%dx%d)", __FUNCTION__, curAtlasSize.x, curAtlasSize.y, maxAtlasSize.x, maxAtlasSize.y ); return; } else { assert(curAtlasSize.x <= maxAtlasSize.x); assert(curAtlasSize.y <= maxAtlasSize.y); } unsigned char* bigtex1 = new unsigned char[curAtlasSize.x * curAtlasSize.y * 4]; unsigned char* bigtex2 = new unsigned char[curAtlasSize.x * curAtlasSize.y * 4]; for (int a = 0; a < (curAtlasSize.x * curAtlasSize.y); ++a) { bigtex1[a*4 + 0] = 128; bigtex1[a*4 + 1] = 128; bigtex1[a*4 + 2] = 128; bigtex1[a*4 + 3] = 0; bigtex2[a*4 + 0] = 0; bigtex2[a*4 + 1] = 128; bigtex2[a*4 + 2] = 0; bigtex2[a*4 + 3] = 255; } for (std::vector<TexFile*>::iterator it = texfiles.begin(); it != texfiles.end(); ++it) { CBitmap& curtex1 = (*it)->tex; CBitmap& curtex2 = (*it)->tex2; const size_t foundx = atlasAlloc->GetEntry((*it)->name).x; const size_t foundy = atlasAlloc->GetEntry((*it)->name).y; const float4 texCoords = atlasAlloc->GetTexCoords((*it)->name); for (int y = 0; y < curtex1.ysize; ++y) { for (int x = 0; x < curtex1.xsize; ++x) { for (int col = 0; col < 4; ++col) { bigtex1[(((foundy + y) * curAtlasSize.x + (foundx + x)) * 4) + col] = curtex1.mem[(((y * curtex1.xsize) + x) * 4) + col]; bigtex2[(((foundy + y) * curAtlasSize.x + (foundx + x)) * 4) + col] = curtex2.mem[(((y * curtex1.xsize) + x) * 4) + col]; } } } textures[(*it)->name] = UnitTexture(texCoords); delete (*it); } const int maxMipMaps = atlasAlloc->GetMaxMipMaps(); { glGenTextures(1, &atlas3do1); glBindTexture(GL_TEXTURE_2D, atlas3do1); 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_LINEAR); 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, curAtlasSize.x, curAtlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); //FIXME disable texcompression } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, curAtlasSize.x, curAtlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); } } { glGenTextures(1, &atlas3do2); glBindTexture(GL_TEXTURE_2D, atlas3do2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (maxMipMaps > 0) ? GL_NEAREST_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, curAtlasSize.x, curAtlasSize.y, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); //FIXME disable texcompression } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, curAtlasSize.x, curAtlasSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); } } if (CTextureAtlas::GetDebug()) { CBitmap tex1(bigtex1, curAtlasSize.x, curAtlasSize.y); CBitmap tex2(bigtex2, curAtlasSize.x, curAtlasSize.y); tex1.Save(atlas.GetName() + "-1-" + IntToString(curAtlasSize.x) + "x" + IntToString(curAtlasSize.y) + ".png"); tex2.Save(atlas.GetName() + "-2-" + IntToString(curAtlasSize.x) + "x" + IntToString(curAtlasSize.y) + ".png"); } delete[] bigtex1; delete[] bigtex2; }