// ============================================================== // 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 MeshCallbackTeamColor // =============================================== void MeshCallbackTeamColor::execute(const Mesh *mesh){ //team color if(mesh->getCustomTexture() && teamTexture!=NULL){ //texture 0 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //set color to interpolation glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); //texture 1 glActiveTexture(GL_TEXTURE1); glMultiTexCoord2f(GL_TEXTURE1, 0.f, 0.f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(teamTexture)->getHandle()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); glActiveTexture(GL_TEXTURE0); } else{ glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } // =============================================== // 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 += "MegaGlest 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 += "MegaGlest 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", "MegaGlest"); } } 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, 3); customTextureRed->getPixmap()->setPixel(0, 0, Vec3f(1.f, 0.f, 0.f)); //blue tex customTextureBlue= textureManager->newTexture2D(); customTextureBlue->getPixmap()->init(1, 1, 3); customTextureBlue->getPixmap()->setPixel(0, 0, Vec3f(0.f, 0.f, 1.f)); //green tex customTextureGreen= textureManager->newTexture2D(); customTextureGreen->getPixmap()->init(1, 1, 3); customTextureGreen->getPixmap()->setPixel(0, 0, Vec3f(0.f, 0.5f, 0.f)); //yellow tex customTextureYellow= textureManager->newTexture2D(); customTextureYellow->getPixmap()->init(1, 1, 3); customTextureYellow->getPixmap()->setPixel(0, 0, Vec3f(1.f, 1.f, 0.f)); //white tex customTextureWhite= textureManager->newTexture2D(); customTextureWhite->getPixmap()->init(1, 1, 3); customTextureWhite->getPixmap()->setPixel(0, 0, Vec3f(1.f, 1.f, 1.f)); //cyan tex customTextureCyan= textureManager->newTexture2D(); customTextureCyan->getPixmap()->init(1, 1, 3); customTextureCyan->getPixmap()->setPixel(0, 0, Vec3f(0.f, 1.f, 0.8f)); //orange tex customTextureOrange= textureManager->newTexture2D(); customTextureOrange->getPixmap()->init(1, 1, 3); customTextureOrange->getPixmap()->setPixel(0, 0, Vec3f(1.f, 0.5f, 0.f)); //magenta tex customTextureMagenta= textureManager->newTexture2D(); customTextureMagenta->getPixmap()->init(1, 1, 3); customTextureMagenta->getPixmap()->setPixel(0, 0, Vec3f(1.f, 0.5f, 1.f)); 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; } meshCallbackTeamColor.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, &meshCallbackTeamColor); 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