/** * @brief Really create the far texture for the given model. */ void CFarTextureHandler::CreateFarTexture(const CSolidObject* obj) { const S3DModel* model = obj->model; //! make space in the std::vectors while (cache.size() <= obj->team) { cache.push_back(std::vector<int>()); } while (cache[obj->team].size() <= model->id) { cache[obj->team].push_back(0); } cache[obj->team][model->id] = -1; //! check if there is enough free space in the atlas, if not try to resize it const int maxSprites = (texSizeX / iconSizeX)*(texSizeY / iconSizeY) / numOrientations - 1; if (usedFarTextures >= maxSprites) { const int oldTexSizeY = texSizeY; if (globalRendering->supportNPOTs) { texSizeY += std::max(iconSizeY, 4 * numOrientations * iconSizeX * iconSizeY / texSizeX); //! minimum additional space for 4 icons } else { texSizeY <<= 1; } if (texSizeY > globalRendering->maxTextureSize) { //logOutput.Print("Out of farTextures"); texSizeY = oldTexSizeY; return; } unsigned char* oldPixels = new unsigned char[texSizeX*texSizeY*4]; glBindTexture(GL_TEXTURE_2D, farTexture); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, oldPixels); memset(oldPixels + texSizeX*oldTexSizeY*4, 0, texSizeX*(texSizeY - oldTexSizeY)*4); GLuint newFarTexture; glGenTextures(1,&newFarTexture); glBindTexture(GL_TEXTURE_2D, newFarTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texSizeX, texSizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, oldPixels); delete[] oldPixels; fbo.Bind(); fbo.UnattachAll(); glDeleteTextures(1,&farTexture); farTexture = newFarTexture; fbo.AttachTexture(farTexture); fbo.CheckStatus("FARTEXTURE"); fbo.Unbind(); } if (!fbo.IsValid()) { //logOutput.Print("framebuffer not valid!"); return; } fbo.Bind(); fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT16, texSizeX, texSizeY); //! delete it after finished rendering to the texture fbo.CheckStatus("FARTEXTURE"); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_BLEND); unitDrawer->SetupForUnitDrawing(); unitDrawer->GetOpaqueModelRenderer(model->type)->PushRenderState(); if (model->type == MODELTYPE_S3O || model->type == MODELTYPE_OBJ) { // FIXME for some strange reason we need to invert the culling, why? if (model->type == MODELTYPE_S3O) { glCullFace(GL_FRONT); } texturehandlerS3O->SetS3oTexture(model->textureType); } unitDrawer->SetTeamColour(obj->team); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-model->radius, model->radius, -model->radius, model->radius, -model->radius*1.5f, model->radius*1.5f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glScalef(-1.0f, 1.0f, 1.0f); glRotatef(45.0f, 1.0f, 0.0f, 0.0f); //! draw the model in 8 different orientations for (size_t orient = 0; orient < numOrientations; ++orient) { //! setup viewport int2 pos = GetTextureCoordsInt(usedFarTextures, orient); glViewport(pos.x * iconSizeX, pos.y * iconSizeY, iconSizeX, iconSizeY); glClear(GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0, -model->height * 0.5f, 0); //! draw the model to a temporary buffer model->DrawStatic(); glPopMatrix(); //! rotate by 45 degrees for the next orientation glRotatef(-360.0f / numOrientations, 0, 1, 0); glLightfv(GL_LIGHT1, GL_POSITION, mapInfo->light.sunDir); } unitDrawer->GetOpaqueModelRenderer(model->type)->PopRenderState(); unitDrawer->CleanUpUnitDrawing(); //glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY); glPopAttrib(); fbo.Unattach(GL_DEPTH_ATTACHMENT_EXT); fbo.Unbind(); usedFarTextures++; cache[obj->team][model->id] = usedFarTextures; }
/** * @brief Really create the far texture for the given model. */ void CFarTextureHandler::CreateFarTexture(const CSolidObject* obj) { const S3DModel* model = obj->model; // make space in the std::vectors if (obj->team >= (int)cache.size()) { cache.resize(obj->team + 1); } if (model->id >= (int)cache[obj->team].size()) { cache[obj->team].resize(model->id + 1, 0); } cache[obj->team][model->id] = -1; // enough free space in the atlas? if (!CheckResizeAtlas()) { return; } // NOTE: // the icons are RTT'ed using a snapshot of the // current state (advModelShading, sunDir, etc) // and will not track later state-changes fbo.Bind(); fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT16, texSizeX, texSizeY); fbo.CheckStatus("FARTEXTURE"); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_BLEND); glFrontFace(GL_CW); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glFogi(GL_FOG_MODE, GL_LINEAR); glFogf(GL_FOG_START, 0.0f); glFogf(GL_FOG_END, 1e6); glFogf(GL_FOG_DENSITY, 1.0f); unitDrawer->SetupForUnitDrawing(); unitDrawer->GetOpaqueModelRenderer(model->type)->PushRenderState(); unitDrawer->SetTeamColour(obj->team); if (model->type != MODELTYPE_3DO) { texturehandlerS3O->SetS3oTexture(model->textureType); } //const float xs = std::max(math::fabs(model->relMidPos.x + model->maxs.x), math::fabs(model->relMidPos.x + model->mins.x)); //const float ys = std::max(math::fabs(model->relMidPos.y + model->maxs.y), math::fabs(model->relMidPos.y + model->mins.y)); //const float zs = std::max(math::fabs(model->relMidPos.z + model->maxs.z), math::fabs(model->relMidPos.z + model->mins.z)); //const float modelradius = std::max(xs, std::max(ys, zs));*/ const float modelradius = 1.15f * model->radius; // overwrite the matrices set by SetupForUnitDrawing // RTT with a top-down view; the view-matrix must be // on the PROJECTION stack for the model shaders glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-modelradius, modelradius, -modelradius, modelradius, -modelradius, modelradius); glRotatef(45.0f, 1.0f, 0.0f, 0.0f); glScalef(-1.0f, 1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); for (int orient = 0; orient < numOrientations; ++orient) { // setup viewport const int2 pos = GetTextureCoordsInt(usedFarTextures, orient); glViewport(pos.x * iconSizeX, pos.y * iconSizeY, iconSizeX, iconSizeY); glClear(GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0f, -model->height * 0.5f, 0.0f); // draw model model->DrawStatic(); glPopMatrix(); // rotate by 360 / numOrientations degrees for the next orientation glRotatef(-360.0f / numOrientations, 0.0f, 1.0f, 0.0f); } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); unitDrawer->GetOpaqueModelRenderer(model->type)->PopRenderState(); unitDrawer->CleanUpUnitDrawing(); // glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY); glPopAttrib(); fbo.Detach(GL_DEPTH_ATTACHMENT_EXT); fbo.Unbind(); cache[obj->team][model->id] = ++usedFarTextures; }
/** * @brief Really create the far texture for the given model. */ void CFarTextureHandler::CreateFarTexture(const CSolidObject* obj) { const S3DModel* model = obj->model; // make space in the std::vectors if (obj->team >= (int)cache.size()) { cache.resize(obj->team + 1); } if (model->id >= (int)cache[obj->team].size()) { cache[obj->team].resize(model->id + 1, 0); } cache[obj->team][model->id] = -1; if (!fbo.IsValid()) { LOG_L(L_DEBUG, "framebuffer not valid!"); return; } fbo.Bind(); fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT16, texSizeX, texSizeY); fbo.CheckStatus("FARTEXTURE"); // overwrite the matrices set by SetupForUnitDrawing // RTT with a top-down view; the view-matrix must be // on the PROJECTION stack for the model shaders glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-model->radius, model->radius, -model->radius, model->radius, -model->radius * 1.5f, model->radius * 1.5f); glRotatef(90.0f, 1.0f, 0.0f, 0.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_BLEND); for (int orient = 0; orient < numOrientations; ++orient) { // setup viewport const int2 pos = GetTextureCoordsInt(usedFarTextures, orient); glViewport(pos.x * iconSizeX, pos.y * iconSizeY, iconSizeX, iconSizeY); glClear(GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0f, -model->height * 0.5f, 0.0f); // draw the model to a temporary buffer model->DrawStatic(); glPopMatrix(); // rotate by 360 / numOrientations degrees for the next orientation glRotatef(360.0f / numOrientations, 0.0f, 1.0f, 0.0f); } // glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY); glPopAttrib(); fbo.Detach(GL_DEPTH_ATTACHMENT_EXT); fbo.Unbind(); cache[obj->team][model->id] = ++usedFarTextures; }