/* render/render.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #include #include #include #include "auxiliary/functions.h" #include "core/core.h" #include "filesystem/filesystem.h" #include "model/model.h" #include "render/gl.h" #include "render/dust.h" #include "render/textures.h" #include "render/tga.h" #include "render/render.h" #include "sys/sys.h" namespace render { core::Cvar *r_arraysize = 0; core::Cvar *r_bbox = 0; core::Cvar *r_grid = 0; core::Cvar *r_radius = 0; core::Cvar *r_sky = 0; core::Cvar *r_wireframe = 0; core::Cvar *screenshotformat = 0; core::Cvar *screenshotquality = 0; int screenshot_number = 0; using model::VertexArray; VertexArray *vertexarray = 0; void func_list_textures(std::string const &args) { Textures::list(); } void reset_gl() { // set clear color gl::clearcolor(0.0f, 0.0f, 0.0f, 1.0f); // load identity matrices gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); // shading model: Gouraud (smooth, the default) gl::shademodel(GL_SMOOTH); //gl::shademodel(GL_FLAT); // lighting settings for the default light GL_LIGHT0 GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat ambient_light[] = { 0.01f, 0.01f, 0.01f, 1.0f }; GLfloat diffuse_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat specular_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light); glLightfv(GL_LIGHT0, GL_SPECULAR, specular_light); // GL_LIGHT0 is always enabled gl::enable(GL_LIGHT0); // color tracking glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // material settings GLfloat specular_reflectance[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflectance); glMateriali(GL_FRONT, GL_SHININESS, 128); // shininess 1-128 // alpha blending function gl::blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl::disable(GL_LIGHTING); gl::disable(GL_COLOR_MATERIAL); gl::cullface(GL_BACK); gl::frontface(GL_CCW); gl::disable(GL_CULL_FACE); gl::disable(GL_DEPTH_TEST); gl::disable(GL_BLEND); gl::disable(GL_TEXTURE_2D); } void init() { con_print << "^BInitializing renderer..." << std::endl; con_print << " renderer ^B" << gl::renderer() << std::endl; con_print << " vendor ^B" << gl::vendor() << std::endl; con_print << " version ^B" << gl::version() << std::endl; // size of the vertex array in megabytes r_arraysize = core::Cvar::get("r_arraysize", 0.0f , core::Cvar::Archive); r_arraysize->set_info("[int] size of the vertex array in Mb"); size_t mb = (size_t) r_arraysize->value(); if (mb < 4 * sizeof(float)) mb = 4 * sizeof(float); if (mb > 256) mb = 256; (*r_arraysize) = (float) mb; vertexarray = new VertexArray(mb); r_radius = core::Cvar::get("r_radius", "0", core::Cvar::Archive); r_radius->set_info("[bool] render entity radius"); r_wireframe = core::Cvar::get("r_wireframe", "0", core::Cvar::Archive); r_wireframe->set_info("[bool] render wireframe"); r_grid = core::Cvar::get("r_grid", "0", core::Cvar::Archive); r_grid->set_info("[bool] render the space grid"); r_bbox = core::Cvar::get("r_bbox", "0", core::Cvar::Archive); r_bbox->set_info("[bool] render model bounding box"); r_sky = core::Cvar::get("r_sky", "1", core::Cvar::Archive); r_sky->set_info("[bool] render the sky globe"); screenshotformat = core::Cvar::get("screenshotformat", "jpg", core::Cvar::Archive); screenshotformat->set_info("[string] screenshot format: jpg png tga"); screenshotquality = core::Cvar::get("screenshotquality", "85", core::Cvar::Archive); screenshotquality->set_info("[int] screenshot jpg quality"); reset_gl(); Camera::init(); Textures::init(); Text::init(); Dust::init(); core::Func *func = core::Func::add("list_textures", func_list_textures); func->set_info("list loaded textures"); } void resize(int width, int height) { // setup our viewport. gl::viewport(0, 0, width, height); Camera::resize(width, height); } // unload game assets (zone change) void unload() { // clear zone sky textures for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { core::Zone *zone = (*it).second; if (zone->sky_texture()) { render::Textures::unload(zone->sky_texture()); zone->set_sky_texture(0); } } for (core::Entity::Registry::iterator it = core::Entity::registry().begin(); it != core::Entity::registry().end(); it++) { core:: Entity *entity = (*it).second; if (entity->type() == core::Entity::Globe) { core::EntityGlobe *globe = static_cast(entity); if (globe->render_texture) { render::Textures::unload(globe->render_texture); globe->render_texture = 0; } } } } // clear all assets void clear() { // clear zone sky textures for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { core::Zone *zone = (*it).second; zone->set_sky_texture(0); } // clear entity models, and globe textures, this will force a reload for (core::Entity::Registry::iterator it = core::Entity::registry().begin(); it != core::Entity::registry().end(); it++) { core::Entity *entity = (*it).second; if (entity->model()) entity->entity_model = 0; if (entity->type() == core::Entity::Globe) { core::EntityGlobe *globe = static_cast(entity); globe->render_texture = 0; } } // clear models model::Model::clear(); // clear vertex array delete vertexarray; vertexarray = 0; } // reset render subsystem void reset() { clear(); Textures::shutdown(); Textures::init(); size_t mb = (size_t) r_arraysize->value(); if (mb < 4 * sizeof(float)) mb = 4 * sizeof(float); if (mb > 256) mb = 256; (*r_arraysize) = (float) mb; vertexarray = new VertexArray(mb); reset_gl(); Dust::reset(); } void shutdown() { con_print << "^BShutting down renderer..." << std::endl; core::Func::remove("list_textures"); clear(); Text::shutdown(); Textures::shutdown(); Camera::shutdown(); Dust::shutdown(); } void screenshot() { bool available = false; std::string shortname; std::string filename; const int TYPETGA = 0; const int TYPEPNG = 1; const int TYPEJPG = 2; int filetype = TYPETGA; // make sure the screenshots folder exists filename.assign(filesystem::writedir()); filename.append("screenshots/"); sys::mkdir(filename); aux::lowercase(screenshotformat->str()); if ((screenshotformat->str().compare("jpg") == 0) || (screenshotformat->str().compare("jpeg") == 0)) { filetype = TYPEJPG; if (screenshotquality->value() < 10) { (*screenshotquality) = 10; } else if (screenshotquality->value() > 100) { (*screenshotquality) = 100; } } else if (screenshotformat->str().compare("png") == 0) { filetype = TYPEPNG; } else if (screenshotformat->str().compare("tga") == 0) { filetype = TYPETGA; } else { filetype = TYPETGA; (*screenshotformat) = "tga"; } // find the first available screenshotxxxx do { std::stringstream nstr; nstr << screenshot_number; shortname.assign(nstr.str()); while(shortname.size() < 4) shortname.insert(0, 1, '0'); shortname.insert(0, "screenshots/osirion"); shortname.append("."); shortname.append(screenshotformat->str()); filename.assign(filesystem::writedir()); filename.append(shortname); FILE *handle = fopen(filename.c_str(), "r"); if (handle) { fclose(handle); } else { available = true; } screenshot_number++; } while (!available); render::Image image(Camera::width(), Camera::height(), 3); glReadPixels(0, 0, (GLsizei) Camera::width(), (GLsizei) Camera::height(), GL_RGB, GL_UNSIGNED_BYTE, (void *) image.data()); image.flip(); if (filetype == TYPEPNG) { /* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { image.pad(); }*/ render::PNG::save(filename.c_str(), image); } else if (filetype == TYPEJPG) { /* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { image.pad(); } */ render::JPG::save(filename.c_str(), image, (int) screenshotquality->value()); } else if (filetype == TYPETGA) { render::TGA::save(filename.c_str(), image); } } }