void CGrassDrawer::ChangeDetail(int detail) { // TODO: get rid of the magic constants const int detail_lim = std::min(3, detail); maxGrassDist = 800 + std::sqrt((float) detail) * 240; maxDetailedDist = 146 + detail * 24; detailedBlocks = int((maxDetailedDist + 128.f * 1.5f) / bMSsq) + 1; numTurfs = 3 + int(detail_lim * 0.5f); strawPerTurf = std::min(50 + int(std::sqrt((float)detail_lim) * 10), mapInfo->grass.maxStrawsPerTurf); // recreate textures & XBOs CreateGrassDispList(grassDL); CreateFarTex(); // reset all cached blocks for (GrassStruct& pGS: grass) { ResetPos(pGS.posX, pGS.posZ); } }
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); }