// ============================================================== // This file is part of MegaGlest (www.glest.org) // // Copyright (C) 2011 - by Mark Vejvoda // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #include "renderer.h" #include "graphics_factory_gl.h" #include "graphics_interface.h" #include "config.h" #include "platform_common.h" //#include using namespace Shared::Graphics; using namespace Shared::Graphics::Gl; using namespace Glest::Game; using namespace Shared::Util; namespace Shared { namespace G3dViewer { int Renderer::windowX = 100; int Renderer::windowY = 100; int Renderer::windowW = 640; int Renderer::windowH = 480; // =============================================== // class Renderer // =============================================== Renderer::Renderer() { normals = false; wireframe = false; grid = true; modelRenderer = NULL; textureManager = NULL; particleRenderer = NULL; modelManager = NULL; width = 0; height = 0; red = 0.3f; green = 0.3f; blue = 0.3f; alpha = 1.0f; customTextureRed = NULL; customTextureBlue = NULL; customTextureGreen = NULL; customTextureYellow = NULL; customTextureWhite = NULL; customTextureCyan = NULL; customTextureOrange = NULL; customTextureMagenta = NULL; particleManager = NULL; } Renderer::~Renderer() { delete modelRenderer; delete textureManager; delete particleRenderer; //resources delete particleManager; delete modelManager; if (GraphicsInterface::getInstance().getFactory() != NULL) { delete GraphicsInterface::getInstance().getFactory(); GraphicsInterface::getInstance().setFactory(NULL); } } Renderer * Renderer::getInstance() { static Renderer * renderer = new Renderer(); return renderer; } void Renderer::transform(float rotX, float rotY, float zoom) { assertGl(); glMatrixMode(GL_MODELVIEW); glRotatef(rotY, 1.0f, 0.0f, 0.0f); glRotatef(rotX, 0.0f, 1.0f, 0.0f); glScalef(zoom, zoom, zoom); Vec4f pos(-8.0f, 5.0f, 10.0f, 0.0f); glLightfv(GL_LIGHT0, GL_POSITION, pos.ptr()); assertGl(); } void Renderer::checkGlCaps() { if (glActiveTexture == NULL) { string message; message += "Your system supports OpenGL version \""; message += getGlVersion() + string("\"\n"); message += "ZetaGlest needs a version that supports\n"; message += "glActiveTexture (OpenGL 1.3) or the ARB_multitexture extension."; throw megaglest_runtime_error(message.c_str()); } //opengl 1.3 //if(!isGlVersionSupported(1, 3, 0)) { if (glewIsSupported("GL_VERSION_1_3") == false) { string message; message += "Your system supports OpenGL version \""; message += getGlVersion() + string("\"\n"); message += "ZetaGlest needs at least version 1.3 to work\n"; message += "You may solve this problem by installing your latest video card drivers"; throw megaglest_runtime_error(message.c_str()); } //opengl 1.4 or extension //if(isGlVersionSupported(1, 4, 0) == false) { if (glewIsSupported("GL_VERSION_1_4") == false) { checkExtension("GL_ARB_texture_env_crossbar", "ZetaGlest"); } } void Renderer::checkExtension(const string &extension, const string &msg) { if (isGlExtensionSupported(extension.c_str()) == false) { string str = "OpenGL extension not supported: " + extension + ", required for " + msg; throw megaglest_runtime_error(str); } } Texture2D * Renderer::getNewTexture2D() { Texture2D *newTexture = textureManager->newTexture2D(); return newTexture; } Model * Renderer::newModel(ResourceScope rs, const string &path, bool deletePixMapAfterLoad, std::map > > *loadedFileList, string *sourceLoader) { return modelManager->newModel(path, deletePixMapAfterLoad, loadedFileList, sourceLoader); } void Renderer::endModel(ResourceScope rs, Model *model) { modelManager->endModel(model); } void Renderer::init() { assertGl(); GraphicsFactory *gf = GraphicsInterface::getInstance().getFactory(); if (gf == NULL) { gf = new GraphicsFactoryGl(); GraphicsInterface::getInstance().setFactory(gf); } Config &config = Config::getInstance(); if (config.getBool("CheckGlCaps")) { if (SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n", extractFileFromDirectoryPath(__FILE__).c_str(), __FUNCTION__, __LINE__); checkGlCaps(); } if (glActiveTexture == NULL) { char szBuf[8096] = ""; snprintf(szBuf, 8096, "Error: glActiveTexture == NULL\nglActiveTexture is only supported if the GL version is 1.3 or greater,\nor if the ARB_multitexture extension is supported!"); throw megaglest_runtime_error(szBuf); } modelRenderer = gf->newModelRenderer(); textureManager = gf->newTextureManager(); particleRenderer = gf->newParticleRenderer(); //resources particleManager = gf->newParticleManager(); modelManager = gf->newModelManager(); modelManager->setTextureManager(textureManager); //red tex customTextureRed = textureManager->newTexture2D(); customTextureRed->getPixmap()->init(1, 1, 4); customTextureRed->getPixmap()->setPixel(0, 0, Vec4f(1.f, 0.f, 0.f, 1.0f)); //blue tex customTextureBlue = textureManager->newTexture2D(); customTextureBlue->getPixmap()->init(1, 1, 4); customTextureBlue->getPixmap()->setPixel(0, 0, Vec4f(0.f, 0.f, 1.f, 1.0f)); //green tex customTextureGreen = textureManager->newTexture2D(); customTextureGreen->getPixmap()->init(1, 1, 4); customTextureGreen->getPixmap()->setPixel(0, 0, Vec4f(0.f, 0.5f, 0.f, 1.0f)); //yellow tex customTextureYellow = textureManager->newTexture2D(); customTextureYellow->getPixmap()->init(1, 1, 4); customTextureYellow->getPixmap()->setPixel(0, 0, Vec4f(1.f, 1.f, 0.f, 1.0f)); //white tex customTextureWhite = textureManager->newTexture2D(); customTextureWhite->getPixmap()->init(1, 1, 4); customTextureWhite->getPixmap()->setPixel(0, 0, Vec4f(1.f, 1.f, 1.f, 1.0f)); //cyan tex customTextureCyan = textureManager->newTexture2D(); customTextureCyan->getPixmap()->init(1, 1, 4); customTextureCyan->getPixmap()->setPixel(0, 0, Vec4f(0.f, 1.f, 0.8f, 1.0f)); //orange tex customTextureOrange = textureManager->newTexture2D(); customTextureOrange->getPixmap()->init(1, 1, 4); customTextureOrange->getPixmap()->setPixel(0, 0, Vec4f(1.f, 0.5f, 0.f, 1.0f)); //magenta tex customTextureMagenta = textureManager->newTexture2D(); customTextureMagenta->getPixmap()->init(1, 1, 4); customTextureMagenta->getPixmap()->setPixel(0, 0, Vec4f(1.f, 0.5f, 1.f, 1.0f)); glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3 //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* once the GL context is valid : */ //GLint alpha_bits; //glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); //printf("#1 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits); glEnable(GL_TEXTURE_2D); glFrontFace(GL_CW); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_ALPHA_TEST); //glAlphaFunc(GL_GREATER, 0.5f); glAlphaFunc(GL_GREATER, 0.0f); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); Vec4f diffuse = Vec4f(1.0f, 1.0f, 1.0f, 1.0f); Vec4f ambient = Vec4f(0.3f, 0.3f, 0.3f, 1.0f); Vec4f specular = Vec4f(0.1f, 0.1f, 0.1f, 1.0f); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient.ptr()); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse.ptr()); glLightfv(GL_LIGHT0, GL_SPECULAR, specular.ptr()); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); assertGl(); } void Renderer::reset(int w, int h, PlayerColor playerColor) { assertGl(); width = w; height = h; //glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* once the GL context is valid : */ //GLint alpha_bits; //glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); //printf("#2 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0f, static_cast(w) / h, 1.0f, 200.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, -1.5, -5); Texture2D *customTexture = NULL; switch (playerColor) { case pcRed: customTexture = customTextureRed; break; case pcBlue: customTexture = customTextureBlue; break; case pcGreen: customTexture = customTextureGreen; break; case pcYellow: customTexture = customTextureYellow; break; case pcWhite: customTexture = customTextureWhite; break; case pcCyan: customTexture = customTextureCyan; break; case pcOrange: customTexture = customTextureOrange; break; case pcMagenta: customTexture = customTextureMagenta; break; default: assert(false); break; } meshCallback.setTeamTexture(customTexture); if (wireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); } else { glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } assertGl(); } void Renderer::renderGrid() { if (grid) { float i = 0; assertGl(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glBegin(GL_LINES); glColor3f(1.0f, 1.0f, 1.0f); // gridcolor constant for (i = -10.0f; i <= 10.0f; i += 1.0f) { glVertex3f(i, 0.0f, 10.0f); glVertex3f(i, 0.0f, -10.0f); } for (i = -10.0f; i <= 10.0f; i += 1.0f) { glVertex3f(10.f, 0.0f, i); glVertex3f(-10.f, 0.0f, i); } glEnd(); glPopAttrib(); assertGl(); } } void Renderer::toggleNormals() { normals = normals ? false : true; } void Renderer::toggleWireframe() { wireframe = wireframe ? false : true; } void Renderer::toggleGrid() { grid = grid ? false : true; } void Renderer::renderTheModel(Model *model, float f) { if (model != NULL) { modelRenderer->begin(true, true, !wireframe, false, &meshCallback); model->updateInterpolationData(f, true); modelRenderer->render(model); if (normals) { glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glColor3f(1.0f, 1.0f, 1.0f); //normalscolor constant modelRenderer->renderNormalsOnly(model); glPopAttrib(); } modelRenderer->end(); } } void Renderer::manageParticleSystem(ParticleSystem *particleSystem) { particleManager->manage(particleSystem); } void Renderer::updateParticleManager() { particleManager->update(); } bool Renderer::hasActiveParticleSystem(ParticleSystem::ParticleSystemType type) const { return particleManager->hasActiveParticleSystem(type); } void Renderer::renderParticleManager() { glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDepthFunc(GL_LESS); particleRenderer->renderManager(particleManager, modelRenderer); glPopAttrib(); } Texture2D * Renderer::getPlayerColorTexture(PlayerColor playerColor) { Texture2D *customTexture = NULL; switch (playerColor) { case pcRed: customTexture = customTextureRed; break; case pcBlue: customTexture = customTextureBlue; break; case pcGreen: customTexture = customTextureGreen; break; case pcYellow: customTexture = customTextureYellow; break; case pcWhite: customTexture = customTextureWhite; break; case pcCyan: customTexture = customTextureCyan; break; case pcOrange: customTexture = customTextureOrange; break; case pcMagenta: customTexture = customTextureMagenta; break; default: throw megaglest_runtime_error("Unknown playercolor: " + intToStr(playerColor)); break; } return customTexture; } void Renderer::initTextureManager() { textureManager->init(); } void Renderer::initModelManager() { modelManager->init(); } void Renderer::end() { //delete resources //textureManager->end(); particleManager->end(); modelManager->end(); } void Renderer::setBackgroundColor(float red, float green, float blue) { this->red = red; this->green = green; this->blue = blue; glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3 //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* once the GL context is valid : */ //GLint alpha_bits; //glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); //printf("#3 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits); } void Renderer::setAlphaColor(float alpha) { this->alpha = alpha; glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3 //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* once the GL context is valid : */ //GLint alpha_bits; //glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); //printf("#3.1 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits); } void Renderer::saveScreen(const string &path, std::pair *overrideSize) { Pixmap2D *pixmapScreenShot = new Pixmap2D(width, height, 4); //glFinish(); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, pixmapScreenShot->getW(), pixmapScreenShot->getH(), GL_RGBA, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels()); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //if(overrideSize != NULL && overrideSize->first > 0 && overrideSize->second > 0) { // pixmapScreenShot->Scale(GL_RGBA,overrideSize->first,overrideSize->second); //} pixmapScreenShot->save(path); delete pixmapScreenShot; } } }//end namespace