void CSMFReadMap::CreateSplatDetailTextures() { if (!haveSplatTexture) { return; } CBitmap splatDistrTexBM; CBitmap splatDetailTexBM; // if the map supplies an intensity- AND a distribution-texture for // detail-splat blending, the regular detail-texture is not used if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) { // default detail-texture should be all-grey splatDetailTexBM.channels = 4; splatDetailTexBM.Alloc(1, 1); splatDetailTexBM.mem[0] = 127; splatDetailTexBM.mem[1] = 127; splatDetailTexBM.mem[2] = 127; splatDetailTexBM.mem[3] = 127; } if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) { splatDistrTexBM.channels = 4; splatDistrTexBM.Alloc(1, 1); splatDistrTexBM.mem[0] = 255; splatDistrTexBM.mem[1] = 0; splatDistrTexBM.mem[2] = 0; splatDistrTexBM.mem[3] = 0; } splatDetailTex = splatDetailTexBM.CreateTexture(true); splatDistrTex = splatDistrTexBM.CreateTexture(true); }
void CUnitDefHandler::SetUnitDefImage(const UnitDef* unitDef, const std::string& texName) { if (unitDef->buildPic == NULL) { unitDef->buildPic = new UnitDefImage(); } else { unitDef->buildPic->Free(); } CBitmap bitmap; if (!texName.empty()) { bitmap.Load("unitpics/" + texName); } else { if (!LoadBuildPic("unitpics/" + unitDef->name + ".dds", bitmap) && !LoadBuildPic("unitpics/" + unitDef->name + ".png", bitmap) && !LoadBuildPic("unitpics/" + unitDef->name + ".pcx", bitmap) && !LoadBuildPic("unitpics/" + unitDef->name + ".bmp", bitmap)) { bitmap.Alloc(1, 1); // last resort } } const unsigned int texID = bitmap.CreateTexture(false); UnitDefImage* unitImage = unitDef->buildPic; unitImage->textureID = texID; unitImage->imageSizeX = bitmap.xsize; unitImage->imageSizeY = bitmap.ysize; }
void CBitmap::Blur(int iterations, float weight) { if (type == BitmapTypeDDS) { return; } CBitmap* src = this; CBitmap* dst = new CBitmap(); dst->channels = src->channels; dst->Alloc(xsize,ysize); for (int i=0; i < iterations; ++i){ { int j,y,x; // Threading::OMPCheck(); // This is currently used too early, OMP is not initialized here // #pragma omp parallel for private(j,x,y) for (y=0; y < ysize; y++) { for (x=0; x < xsize; x++) { for (j=0; j < channels; j++) { kernelBlur(dst, src->mem, x, y, j, weight); } } } } std::swap(src, dst); } if (dst == this) { // make sure we don't delete `this` std::swap(src, dst); } delete dst; }
void CBitmap::Blur(int iterations, float weight) { if (type == BitmapTypeDDS) { return; } CBitmap* src = this; CBitmap* dst = new CBitmap(); dst->channels = src->channels; dst->Alloc(xsize,ysize); for (int i=0; i < iterations; ++i){ { for_mt(0, ysize, [&](const int y) { for (int x=0; x < xsize; x++) { for (int j=0; j < channels; j++) { kernelBlur(dst, src->mem, x, y, j, weight); } } }); } std::swap(src, dst); } if (dst == this) { // make sure we don't delete `this` std::swap(src, dst); } delete dst; }
void glSaveTexture(const GLuint textureID, const char* filename) { const GLenum target = GL_TEXTURE_2D; GLenum format = GL_RGBA8; int sizeX, sizeY; int bits = 0; { glBindTexture(GL_TEXTURE_2D, textureID); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &sizeX); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &sizeY); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&format); GLint _cbits; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &_cbits); bits += _cbits; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &_cbits); bits += _cbits; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &_cbits); bits += _cbits; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &_cbits); bits += _cbits; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH_SIZE, &_cbits); bits += _cbits; } assert(bits == 32); assert(format == GL_RGBA8); CBitmap bmp; bmp.Alloc(sizeX, sizeY, 4); glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, bmp.GetRawMem()); bmp.Save(filename, false); }
bool CMouseCursor::LoadCursorImage(const string& name, ImageData& image) { CFileHandler f(name); if (!f.FileExists()) { return false; } CBitmap b; if (!b.Load(name)) { LOG_L(L_ERROR, "CMouseCursor: Bad image file: %s", name.c_str()); return false; } // hardcoded bmp transparency mask if (FileSystem::GetExtension(name) == "bmp") { b.SetTransparent(SColor(84, 84, 252)); } if (hwCursor->NeedsYFlip()) { //WINDOWS b.ReverseYAxis(); hwCursor->PushImage(b.xsize,b.ysize,&b.mem[0]); }else{ //X11 hwCursor->PushImage(b.xsize,b.ysize,&b.mem[0]); b.ReverseYAxis(); } const int nx = next_power_of_2(b.xsize); const int ny = next_power_of_2(b.ysize); if (b.xsize != nx || b.ysize != ny) { CBitmap bn; bn.Alloc(nx, ny); bn.CopySubImage(b, 0, ny - b.ysize); image.texture = bn.CreateTexture(); image.xOrigSize = b.xsize; image.yOrigSize = b.ysize; image.xAlignedSize = bn.xsize; image.yAlignedSize = bn.ysize; } else { image.texture = b.CreateTexture(); image.xOrigSize = b.xsize; image.yOrigSize = b.ysize; image.xAlignedSize = b.xsize; image.yAlignedSize = b.ysize; } return true; }
void CSMFReadMap::CreateSplatDetailTextures() { if (!haveSplatDetailDistribTexture) return; CBitmap splatDistrTexBM; CBitmap splatDetailTexBM; // if the map supplies an intensity- AND a distribution-texture for // detail-splat blending, the regular detail-texture is not used if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) { // default detail-texture should be all-grey splatDetailTexBM.channels = 4; splatDetailTexBM.AllocDummy(SColor(127,127,127,127)); } if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) { splatDistrTexBM.channels = 4; splatDistrTexBM.AllocDummy(SColor(255,0,0,0)); } splatDetailTex.SetRawTexID(splatDetailTexBM.CreateTexture(texAnisotropyLevels[true], true)); splatDetailTex.SetRawSize(int2(splatDetailTexBM.xsize, splatDetailTexBM.ysize)); splatDistrTex.SetRawTexID(splatDistrTexBM.CreateTexture(texAnisotropyLevels[true], true)); splatDistrTex.SetRawSize(int2(splatDistrTexBM.xsize, splatDistrTexBM.ysize)); // only load the splat detail normals if any of them are defined and present if (!haveSplatNormalDistribTexture) return; for (size_t i = 0; i < mapInfo->smf.splatDetailNormalTexNames.size(); i++) { if (i == NUM_SPLAT_DETAIL_NORMALS) break; CBitmap splatDetailNormalTextureBM; if (!splatDetailNormalTextureBM.Load(mapInfo->smf.splatDetailNormalTexNames[i])) { splatDetailNormalTextureBM.channels = 4; splatDetailNormalTextureBM.Alloc(1, 1); splatDetailNormalTextureBM.mem[0] = 127; // RGB is packed standard normal map splatDetailNormalTextureBM.mem[1] = 127; splatDetailNormalTextureBM.mem[2] = 255; // With a single upward (+Z) pointing vector splatDetailNormalTextureBM.mem[3] = 127; // Alpha is diffuse as in old-style detail textures } splatNormalTextures[i].SetRawTexID(splatDetailNormalTextureBM.CreateTexture(texAnisotropyLevels[true], true)); splatNormalTextures[i].SetRawSize(int2(splatDetailNormalTextureBM.xsize, splatDetailNormalTextureBM.ysize)); } }
CBitmap CBitmap::CreateRescaled(int newx, int newy) const { newx = std::max(1, newx); newy = std::max(1, newy); CBitmap bm; bm.Alloc(newx, newy); const float dx = (float) xsize / newx; const float dy = (float) ysize / newy; float cy = 0; for (int y=0; y < newy; ++y) { const int sy = (int) cy; cy += dy; int ey = (int) cy; if (ey == sy) { ey = sy+1; } float cx = 0; for (int x=0; x < newx; ++x) { const int sx = (int) cx; cx += dx; int ex = (int) cx; if (ex == sx) { ex = sx + 1; } int r=0, g=0, b=0, a=0; for (int y2 = sy; y2 < ey; ++y2) { for (int x2 = sx; x2 < ex; ++x2) { const int index = (y2*xsize + x2) * 4; r += mem[index + 0]; g += mem[index + 1]; b += mem[index + 2]; a += mem[index + 3]; } } const int index = (y*bm.xsize + x) * 4; const int denom = (ex - sx) * (ey - sy); bm.mem[index + 0] = r / denom; bm.mem[index + 1] = g / denom; bm.mem[index + 2] = b / denom; bm.mem[index + 3] = a / denom; } } return bm; }
CBasicWater::CBasicWater() { CBitmap waterTexBM; if (!waterTexBM.Load(mapInfo->water.texture)) { LOG_L(L_WARNING, "[%s] could not read water texture from file \"%s\"", __FUNCTION__, mapInfo->water.texture.c_str()); // fallback waterTexBM.channels = 4; waterTexBM.Alloc(1, 1); waterTexBM.mem[0] = 0; waterTexBM.mem[1] = 0; waterTexBM.mem[2] = 255; waterTexBM.mem[3] = 255; } // create mipmapped texture textureID = waterTexBM.CreateTexture(true); displistID = GenWaterQuadsList(waterTexBM.xsize, waterTexBM.ysize); }
int CS3OTextureHandler::LoadS3OTextureNow(const S3DModel* model) { GML_STDMUTEX_LOCK(model); // LoadS3OTextureNow string totalName = model->tex1 + model->tex2; if (s3oTextureNames.find(totalName) != s3oTextureNames.end()){ return s3oTextureNames[totalName]; } const int newNum = s3oTextures.size(); S3oTex tex; tex.num = newNum; CBitmap bm; if (!bm.Load(std::string("unittextures/" + model->tex1))) { throw content_error("Could not load texture unittextures/" + model->tex1 + " from S3O model " + model->name); } tex.tex1 = bm.CreateTexture(true); tex.tex1SizeX = bm.xsize; tex.tex1SizeY = bm.ysize; tex.tex2 = 0; tex.tex2SizeX = 0; tex.tex2SizeY = 0; //if (unitDrawer->advShading) { CBitmap bm; // No error checking here... other code relies on an empty texture // being generated if it couldn't be loaded. // Also many map features specify a tex2 but don't ship it with the map, // so throwing here would cause maps to break. if (!bm.Load(std::string("unittextures/" + model->tex2))) { bm.Alloc(1, 1); bm.mem[3] = 255; // file not found, set alpha to white so unit is visible } tex.tex2 = bm.CreateTexture(true); tex.tex2SizeX = bm.xsize; tex.tex2SizeY = bm.ysize; } s3oTextures.push_back(tex); s3oTextureNames[totalName] = newNum; return newNum; }
void CSMFReadMap::CreateSpecularTex() { if (!haveSpecularTexture) { return; } CBitmap specularTexBM; CBitmap skyReflectModTexBM; CBitmap detailNormalTexBM; CBitmap lightEmissionTexBM; CBitmap parallaxHeightTexBM; if (!specularTexBM.Load(mapInfo->smf.specularTexName)) { // maps wants specular lighting, but no moderation specularTexBM.channels = 4; specularTexBM.Alloc(1, 1); specularTexBM.mem[0] = 255; specularTexBM.mem[1] = 255; specularTexBM.mem[2] = 255; specularTexBM.mem[3] = 255; } specularTex = specularTexBM.CreateTexture(false); // no default 1x1 textures for these if (skyReflectModTexBM.Load(mapInfo->smf.skyReflectModTexName)) { skyReflectModTex = skyReflectModTexBM.CreateTexture(false); } if (detailNormalTexBM.Load(mapInfo->smf.detailNormalTexName)) { detailNormalTex = detailNormalTexBM.CreateTexture(false); } if (lightEmissionTexBM.Load(mapInfo->smf.lightEmissionTexName)) { lightEmissionTex = lightEmissionTexBM.CreateTexture(false); } if (parallaxHeightTexBM.Load(mapInfo->smf.parallaxHeightTexName)) { parallaxHeightTex = parallaxHeightTexBM.CreateTexture(false); } }
/* * Class: aflobby_CUnitSyncJNIBindings * Method: WriteMiniMap * Signature: (II)I */ JNIEXPORT jboolean JNICALL Java_aflobby_CUnitSyncJNIBindings_WriteMiniMap (JNIEnv *env, jclass myobject, jstring mapfile, jstring imagename, jint miplevel){ const char *filename = env->GetStringUTFChars(mapfile, 0); const char *bitmap_filename = env->GetStringUTFChars(imagename, 0); void* minimap = GetMinimap(filename, miplevel); if (!minimap){ env->ReleaseStringUTFChars(mapfile, filename); env->ReleaseStringUTFChars(mapfile, bitmap_filename); return false; } int size = 1024 >> miplevel; CBitmap bm; bm.Alloc(size, size); unsigned short *src = (unsigned short*)minimap; unsigned char *dst = bm.mem; for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++){ dst[0] = RED_RGB565 ((*src)) << 3; dst[1] = GREEN_RGB565 ((*src)) << 2; dst[2] = BLUE_RGB565 ((*src)) << 3; dst[3] = 255; ++src; dst += 4; } } remove(bitmap_filename); //somehow overwriting doesn't work?? bm.Save(bitmap_filename); // check whether the bm.Save succeeded? FILE* f = fopen(bitmap_filename, "rb"); bool success = !!f; if (success) { fclose(f); } env->ReleaseStringUTFChars(mapfile, filename); env->ReleaseStringUTFChars(mapfile, bitmap_filename); return success; }
void CBitmap::Blur(int iterations, float weight) { if (type == BitmapTypeDDS) { return; } CBitmap* src = this; CBitmap* dst = new CBitmap(); dst->channels = src->channels; dst->Alloc(xsize,ysize); for (int i=0; i < iterations; ++i){ { int j,y,x; #pragma omp parallel for private(j,x,y) for (y=0; y < ysize; y++) { for (x=0; x < xsize; x++) { for (j=0; j < channels; j++) { kernelBlur(dst, src->mem, x, y, j, weight); } } } } CBitmap* buf = dst; dst = src; src = buf; } if (dst == this) { CBitmap* buf = dst; dst = src; src = buf; } delete dst; }
void CBitmap::Blur(int iterations, float weight) { if (type == BitmapTypeDDS) { return; } CBitmap* src = this; CBitmap* dst = new CBitmap(); dst->channels = src->channels; dst->Alloc(xsize,ysize); for (int i=0; i < iterations; ++i){ #pragma omp parallel private(y,x,i) { #pragma omp for for (int y=0; y < ysize; ++y) { for (int x=0; x < xsize; ++x) { for (int i=0; i < channels; ++i) { kernelBlur(dst, src->mem, x, y, i, weight); } } } } CBitmap* buf = dst; dst = src; src = buf; } if (dst == this) { CBitmap* buf = dst; dst = src; src = buf; } delete dst; }
CSMFReadMap::CSMFReadMap(std::string mapname): file(mapname) { loadscreen->SetLoadMessage("Loading SMF"); ConfigureAnisotropy(); for (int a = 0; a < 1024; ++a) { for (int b = 0; b < 3; ++b) { const float absorbColor = mapInfo->water.baseColor[b] - mapInfo->water.absorb[b] * a; const float clampedColor = max(mapInfo->water.minColor[b], absorbColor); waterHeightColors[a * 4 + b] = clampedColor * 210; } waterHeightColors[a * 4 + 3] = 1; } const SMFHeader& header = file.GetHeader(); const CMapInfo::smf_t& smf = mapInfo->smf; width = header.mapx; height = header.mapy; numBigTexX = (header.mapx / bigSquareSize); numBigTexY = (header.mapy / bigSquareSize); bigTexSize = (SQUARE_SIZE * bigSquareSize); tileMapSizeX = (header.mapx / tileScale); tileMapSizeY = (header.mapy / tileScale); tileCount = (header.mapx * header.mapy) / (tileScale * tileScale); mapSizeX = (header.mapx * SQUARE_SIZE); mapSizeZ = (header.mapy * SQUARE_SIZE); maxHeightMapIdx = ((header.mapx + 1) * (header.mapy + 1)) - 1; heightMapSizeX = (header.mapx + 1); cornerHeightMapSynced.resize((width + 1) * (height + 1)); #ifdef USE_UNSYNCED_HEIGHTMAP cornerHeightMapUnsynced.resize((width + 1) * (height + 1)); #endif groundDrawer = NULL; const float minH = smf.minHeightOverride ? smf.minHeight : header.minHeight; const float maxH = smf.maxHeightOverride ? smf.maxHeight : header.maxHeight; file.ReadHeightmap(&cornerHeightMapSynced[0], minH, (maxH - minH) / 65536.0f); CReadMap::Initialize(); shadingTexPixelRow.resize(gs->mapxp1 * 4, 0); shadingTexUpdateIter = 0; shadingTexUpdateRate = std::max(1.0f, math::ceil((width + 1) / float(height + 1))); // with GLSL, the shading texture has very limited use (minimap etc) so we increase the update interval if (globalRendering->haveGLSL) shadingTexUpdateRate *= 10; for (unsigned int a = 0; a < mapname.size(); ++a) { mapChecksum += mapname[a]; mapChecksum *= mapname[a]; } haveSpecularLighting = !(mapInfo->smf.specularTexName.empty()); haveSplatTexture = (!mapInfo->smf.splatDetailTexName.empty() && !mapInfo->smf.splatDistrTexName.empty()); CBitmap detailTexBM; CBitmap grassShadingTexBM; detailTex = 0; shadingTex = 0; normalsTex = 0; minimapTex = 0; specularTex = 0; splatDetailTex = 0; splatDistrTex = 0; skyReflectModTex = 0; detailNormalTex = 0; lightEmissionTex = 0; if (haveSpecularLighting) { CBitmap specularTexBM; CBitmap skyReflectModTexBM; CBitmap detailNormalTexBM; CBitmap lightEmissionTexBM; if (!specularTexBM.Load(mapInfo->smf.specularTexName)) { // maps wants specular lighting, but no moderation specularTexBM.channels = 4; specularTexBM.Alloc(1, 1); specularTexBM.mem[0] = 255; specularTexBM.mem[1] = 255; specularTexBM.mem[2] = 255; specularTexBM.mem[3] = 255; } specularTex = specularTexBM.CreateTexture(false); if (haveSplatTexture) { CBitmap splatDistrTexBM; CBitmap splatDetailTexBM; // if the map supplies an intensity- and a distribution-texture for // detail-splat blending, the regular detail-texture is not used if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) { // default detail-texture should be all-grey splatDetailTexBM.channels = 4; splatDetailTexBM.Alloc(1, 1); splatDetailTexBM.mem[0] = 127; splatDetailTexBM.mem[1] = 127; splatDetailTexBM.mem[2] = 127; splatDetailTexBM.mem[3] = 127; } if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) { splatDistrTexBM.channels = 4; splatDistrTexBM.Alloc(1, 1); splatDistrTexBM.mem[0] = 255; splatDistrTexBM.mem[1] = 0; splatDistrTexBM.mem[2] = 0; splatDistrTexBM.mem[3] = 0; } splatDetailTex = splatDetailTexBM.CreateTexture(true); splatDistrTex = splatDistrTexBM.CreateTexture(true); } // no default 1x1 textures for these if (skyReflectModTexBM.Load(mapInfo->smf.skyReflectModTexName)) { skyReflectModTex = skyReflectModTexBM.CreateTexture(false); } if (detailNormalTexBM.Load(mapInfo->smf.detailNormalTexName)) { detailNormalTex = detailNormalTexBM.CreateTexture(false); } if (lightEmissionTexBM.Load(mapInfo->smf.lightEmissionTexName)) { lightEmissionTex = lightEmissionTexBM.CreateTexture(false); } } if (!detailTexBM.Load(mapInfo->smf.detailTexName)) { throw content_error("Could not load detail texture from file " + mapInfo->smf.detailTexName); } { glGenTextures(1, &detailTex); glBindTexture(GL_TEXTURE_2D, detailTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); if (anisotropy != 0.0f) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); } glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, detailTexBM.xsize, detailTexBM.ysize, GL_RGBA, GL_UNSIGNED_BYTE, detailTexBM.mem); } { // the minimap is a static texture std::vector<unsigned char> minimapTexBuf(MINIMAP_SIZE, 0); file.ReadMinimap(&minimapTexBuf[0]); glGenTextures(1, &minimapTex); glBindTexture(GL_TEXTURE_2D, minimapTex); 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_MAX_LEVEL, MINIMAP_NUM_MIPMAP - 1); int offset = 0; for (unsigned int i = 0; i < MINIMAP_NUM_MIPMAP; i++) { const int mipsize = 1024 >> i; const int size = ((mipsize + 3) / 4) * ((mipsize + 3) / 4) * 8; glCompressedTexImage2DARB(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipsize, mipsize, 0, size, &minimapTexBuf[0] + offset); offset += size; } } { if (grassShadingTexBM.Load(mapInfo->smf.grassShadingTexName)) { // generate mipmaps for the grass shading-texture grassShadingTex = grassShadingTexBM.CreateTexture(true); } else { grassShadingTex = minimapTex; } } { // the shading/normal texture buffers must have PO2 dimensions // (excess elements that no vertices map into are left unused) 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_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); if (anisotropy != 0.0f) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } { #if (SSMF_UNCOMPRESSED_NORMALS == 1) std::vector<float> normalsTexBuf(gs->pwr2mapx * gs->pwr2mapy * 4, 0.0f); #else GLenum texFormat = GL_LUMINANCE_ALPHA16F_ARB; if (configHandler->GetBool("GroundNormalTextureHighPrecision")) { texFormat = GL_LUMINANCE_ALPHA32F_ARB; } #endif glGenTextures(1, &normalsTex); glBindTexture(GL_TEXTURE_2D, normalsTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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); #if (SSMF_UNCOMPRESSED_NORMALS == 1) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_FLOAT, &normalsTexBuf[0]); #else glTexImage2D(GL_TEXTURE_2D, 0, texFormat, gs->pwr2mapx, gs->pwr2mapy, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, NULL); #endif } file.ReadFeatureInfo(); }
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); }
CSmfReadMap::CSmfReadMap(std::string mapname): file(mapname) { loadscreen->SetLoadMessage("Loading SMF"); ConfigureAnisotropy(); for (int a = 0; a < 1024; ++a) { for (int b = 0; b < 3; ++b) { float c = max(mapInfo->water.minColor[b], mapInfo->water.baseColor[b] - mapInfo->water.absorb[b] * a); waterHeightColors[a * 4 + b] = (unsigned char)(c * 210); } waterHeightColors[a * 4 + 3] = 1; } const SMFHeader& header = file.GetHeader(); width = header.mapx; height = header.mapy; heightmap = new float[(width + 1) * (height + 1)]; groundDrawer = 0; const CMapInfo::smf_t& smf = mapInfo->smf; const float minH = smf.minHeightOverride ? smf.minHeight : header.minHeight; const float maxH = smf.maxHeightOverride ? smf.maxHeight : header.maxHeight; const float base = minH; const float mod = (maxH - minH) / 65536.0f; file.ReadHeightmap(heightmap, base, mod); CReadMap::Initialize(); for (unsigned int a = 0; a < mapname.size(); ++a) { mapChecksum += mapname[a]; mapChecksum *= mapname[a]; } haveSpecularLighting = (!(mapInfo->smf.specularTexName.empty()) && globalRendering->haveGLSL); haveSplatTexture = (!mapInfo->smf.splatDetailTexName.empty() && !mapInfo->smf.splatDistrTexName.empty()); CBitmap detailTexBM; CBitmap grassShadingTexBM; detailTex = 0; shadingTex = 0; normalsTex = 0; minimapTex = 0; specularTex = 0; splatDetailTex = 0; splatDistrTex = 0; skyReflectModTex = 0; if (haveSpecularLighting) { CBitmap specularTexBM; CBitmap skyReflectModTexBM; if (!specularTexBM.Load(mapInfo->smf.specularTexName)) { // maps wants specular lighting, but no moderation specularTexBM.Alloc(1, 1); specularTexBM.mem[0] = 255; specularTexBM.mem[1] = 255; specularTexBM.mem[2] = 255; specularTexBM.mem[3] = 255; } specularTex = specularTexBM.CreateTexture(false); if (haveSplatTexture) { CBitmap splatDistrTexBM; CBitmap splatDetailTexBM; // if the map supplies an intensity- and a distribution-texture for // detail-splat blending, the regular detail-texture is not used if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) { // default detail-texture should be all-grey splatDetailTexBM.Alloc(1, 1); splatDetailTexBM.mem[0] = 127; splatDetailTexBM.mem[1] = 127; splatDetailTexBM.mem[2] = 127; splatDetailTexBM.mem[3] = 127; } if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) { splatDistrTexBM.Alloc(1, 1); splatDistrTexBM.mem[0] = 255; splatDistrTexBM.mem[1] = 0; splatDistrTexBM.mem[2] = 0; splatDistrTexBM.mem[3] = 0; } splatDetailTex = splatDetailTexBM.CreateTexture(true); splatDistrTex = splatDistrTexBM.CreateTexture(true); } if (skyReflectModTexBM.Load(mapInfo->smf.skyReflectModTexName)) { skyReflectModTex = skyReflectModTexBM.CreateTexture(false); } } if (!detailTexBM.Load(mapInfo->smf.detailTexName)) { throw content_error("Could not load detail texture from file " + mapInfo->smf.detailTexName); } { glGenTextures(1, &detailTex); glBindTexture(GL_TEXTURE_2D, detailTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); if (anisotropy != 0.0f) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); } glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, detailTexBM.xsize, detailTexBM.ysize, GL_RGBA, GL_UNSIGNED_BYTE, detailTexBM.mem); } { // the minimap is a static texture std::vector<unsigned char> minimapTexBuf(MINIMAP_SIZE, 0); file.ReadMinimap(&minimapTexBuf[0]); glGenTextures(1, &minimapTex); glBindTexture(GL_TEXTURE_2D, minimapTex); 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_MAX_LEVEL, MINIMAP_NUM_MIPMAP - 1); int offset = 0; for (unsigned int i = 0; i < MINIMAP_NUM_MIPMAP; i++) { const int mipsize = 1024 >> i; const int size = ((mipsize + 3) / 4) * ((mipsize + 3) / 4) * 8; glCompressedTexImage2DARB(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipsize, mipsize, 0, size, &minimapTexBuf[0] + offset); offset += size; } } { if (grassShadingTexBM.Load(mapInfo->smf.grassShadingTexName)) { // generate mipmaps for the grass shading-texture grassShadingTex = grassShadingTexBM.CreateTexture(true); } else { grassShadingTex = minimapTex; } } { // the shading/normal texture buffers must have PO2 dimensions // (excess elements that no vertices map into are left unused) 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_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); if (anisotropy != 0.0f) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } { #if (SSMF_UNCOMPRESSED_NORMALS == 1) std::vector<float> normalsTexBuf(gs->pwr2mapx * gs->pwr2mapy * 4, 0.0f); #else GLenum texFormat = GL_LUMINANCE_ALPHA16F_ARB; if (!!configHandler->Get("GroundNormalTextureHighPrecision", 0)) { texFormat = GL_LUMINANCE_ALPHA32F_ARB; } #endif glGenTextures(1, &normalsTex); glBindTexture(GL_TEXTURE_2D, normalsTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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); #if (SSMF_UNCOMPRESSED_NORMALS == 1) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_FLOAT, &normalsTexBuf[0]); #else glTexImage2D(GL_TEXTURE_2D, 0, texFormat, gs->pwr2mapx, gs->pwr2mapy, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, NULL); #endif } file.ReadFeatureInfo(); }
CGrassDrawer::CGrassDrawer() : CEventClient("[GrassDrawer]", 199992, false) , grassOff(false) , blocksX(mapDims.mapx / grassSquareSize / grassBlockSize) , blocksY(mapDims.mapy / grassSquareSize / grassBlockSize) , grassDL(0) , grassBladeTex(0) , farTex(0) , farnearVA(nullptr) , updateBillboards(false) , grassMap(nullptr) { blockDrawer.ResetState(); rng.Seed(15); 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; } // needed to create the far tex if (!GLEW_EXT_framebuffer_blit) { grassOff = true; return; } // load grass density from map { MapBitmapInfo grassbm; unsigned char* grassdata = readMap->GetInfoMap("grass", &grassbm); if (!grassdata) { grassOff = true; return; } if (grassbm.width != mapDims.mapx / grassSquareSize || grassbm.height != mapDims.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, mapDims.mapx / 4, mapDims.mapy / 4); throw std::runtime_error(b); } const int grassMapSize = mapDims.mapx * mapDims.mapy / (grassSquareSize * grassSquareSize); grassMap = new unsigned char[grassMapSize]; memcpy(grassMap, grassdata, grassMapSize); readMap->FreeInfoMap("grass", grassdata); } // create/load blade texture { CBitmap grassBladeTexBM; if (!grassBladeTexBM.Load(mapInfo->grass.bladeTexName)) { // 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]); } } //grassBladeTexBM.Save("blade.png", false); grassBladeTex = grassBladeTexBM.CreateTexture(true); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } // create shaders * finalize grass.resize(blocksX * blocksY); farnearVA = new CVertexArray; grassDL = glGenLists(1); ChangeDetail(detail); LoadGrassShaders(); configHandler->NotifyOnChange(this); // eventclient autoLinkEvents = true; RegisterLinkedEvents(this); eventHandler.AddClient(this); }
CBasicTreeDrawer::CBasicTreeDrawer(): ITreeDrawer() { LuaParser resourcesParser("gamedata/resources.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!resourcesParser.Execute()) { LOG_L(L_ERROR, "%s", resourcesParser.GetErrorLog().c_str()); } const LuaTable treesTable = resourcesParser.GetRoot().SubTable("graphics").SubTable("trees"); const float tintc[3] = {0.6f, 0.7f, 0.6f}; std::string fn; CBitmap sprite; CBitmap TexImage; TexImage.Alloc(512, 512); { fn = "bitmaps/" + treesTable.GetString("gran1", "gran.bmp"); if (!sprite.Load(fn)) throw content_error("Could not load tree texture from " + fn); if (sprite.xsize != 256 || sprite.ysize != 256) throw content_error("texture " + fn + " must be 256x256!"); sprite.ReverseYAxis(); sprite.SetTransparent(SColor(72, 72, 72), SColor(33, 54, 29, 0)); TexImage.CopySubImage(sprite, 0, 0); } { fn = "bitmaps/" + treesTable.GetString("gran2", "gran2.bmp"); if (!sprite.Load(fn)) throw content_error("Could not load tree texture from file " + fn); if (sprite.xsize != 256 && sprite.ysize != 256) throw content_error("texture " + fn + " must be 256x256!"); sprite.ReverseYAxis(); sprite.SetTransparent(SColor(72, 72, 72), SColor(33, 54, 29, 0)); TexImage.CopySubImage(sprite, 255, 0); } { fn = "bitmaps/" + treesTable.GetString("birch1", "birch1.bmp"); if (!sprite.Load(fn)) throw content_error("Could not load tree texture from file " + fn); if (sprite.xsize != 128 || sprite.ysize != 256) throw content_error("texture " + fn + " must be 128x256!"); sprite.ReverseYAxis(); sprite.SetTransparent(SColor(72, 72, 72), SColor(75, 102, 49, 0)); sprite.Tint(tintc); TexImage.CopySubImage(sprite, 0, 255); } { fn = "bitmaps/" + treesTable.GetString("birch2", "birch2.bmp"); if (!sprite.Load(fn)) throw content_error("Could not load tree texture from file " + fn); if (sprite.xsize != 128 || sprite.ysize != 256) throw content_error("texture " + fn + " must be 128x256!"); sprite.ReverseYAxis(); sprite.SetTransparent(SColor(72, 72, 72), SColor(75, 102, 49, 0)); sprite.Tint(tintc); TexImage.CopySubImage(sprite, 127, 255); } { fn = "bitmaps/" + treesTable.GetString("birch3", "birch3.bmp"); if (!sprite.Load(fn)) throw content_error("Could not load tree texture from file " + fn); if (sprite.xsize != 256 || sprite.ysize != 256) throw content_error("texture " + fn + " must be 256x256!"); sprite.ReverseYAxis(); sprite.SetTransparent(SColor(72, 72, 72), SColor(75, 102, 49, 0)); sprite.Tint(tintc); TexImage.CopySubImage(sprite, 255, 255); } // create mipmapped texture treetex = TexImage.CreateTexture(true); lastListClean = 0; treesX = mapDims.mapx / TREE_SQUARE_SIZE; treesY = mapDims.mapy / TREE_SQUARE_SIZE; nTrees = treesX * treesY; trees = new TreeSquareStruct[nTrees]; for (TreeSquareStruct* pTSS = trees; pTSS < trees + nTrees; ++pTSS) { pTSS->dispList = 0; pTSS->farDispList = 0; } }
CUnitDrawer::CUnitDrawer(void) : showHealthBars(true), updateFace(0) { if(texturehandler==0) texturehandler=SAFE_NEW CTextureHandler; unitDrawDist=configHandler.GetInt("UnitLodDist",200); unitIconDist=configHandler.GetInt("UnitIconDist",200); iconLength=750*unitIconDist*unitIconDist; CBitmap white; white.Alloc(1,1); for(int a=0;a<4;++a) white.mem[a]=255; whiteTex=white.CreateTexture(false); unitAmbientColor=readmap->mapDefParser.GetFloat3(float3(0.4f,0.4f,0.4f),"MAP\\LIGHT\\UnitAmbientColor"); unitSunColor=readmap->mapDefParser.GetFloat3(float3(0.7f,0.7f,0.7f),"MAP\\LIGHT\\UnitSunColor"); float3 specularSunColor=readmap->mapDefParser.GetFloat3(unitSunColor,"MAP\\LIGHT\\SpecularSunColor"); readmap->mapDefParser.GetDef(unitShadowDensity,"0.8","MAP\\LIGHT\\UnitShadowDensity"); advShading=!!configHandler.GetInt("AdvUnitShading", GLEW_ARB_fragment_program ? 1 : 0); if (advShading && !GLEW_ARB_fragment_program) { logOutput.Print("You are missing an OpenGL extension needed to use advanced unit shading (GL_ARB_fragment_program)"); advShading = false; } if (advShading) { unitVP = LoadVertexProgram("unit.vp"); unitFP = LoadFragmentProgram("unit.fp"); unitS3oVP = LoadVertexProgram("units3o.vp"); unitS3oFP = LoadFragmentProgram("units3o.fp"); if (shadowHandler->canUseShadows) { unitShadowFP = LoadFragmentProgram("unit_shadow.fp"); unitShadowS3oFP = LoadFragmentProgram("units3o_shadow.fp"); unitShadowGenVP = LoadVertexProgram("unit_genshadow.vp"); } else { unitShadowFP = 0; unitShadowS3oFP = 0; unitShadowGenVP = 0; } glGenTextures(1,&boxtex); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, boxtex); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,0,GL_RGBA8,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,0); glGenTextures(1,&specularTex); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, specularTex); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,128,float3(1,1,1),float3(0,0,-2),float3(0,-2,0),gs->sunVector,100,specularSunColor); CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,128,float3(-1,1,-1),float3(0,0,2),float3(0,-2,0),gs->sunVector,100,specularSunColor); CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,128,float3(-1,1,-1),float3(2,0,0),float3(0,0,2),gs->sunVector,100,specularSunColor); CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,128,float3(-1,-1,1),float3(2,0,0),float3(0,0,-2),gs->sunVector,100,specularSunColor); CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,128,float3(-1,1,1),float3(2,0,0),float3(0,-2,0),gs->sunVector,100,specularSunColor); CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,128,float3(1,1,-1),float3(-2,0,0),float3(0,-2,0),gs->sunVector,100,specularSunColor); } }