From a704318f507f486ac04834747eb209d0a9410702 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 24 Oct 2010 16:02:09 +0000 Subject: keepalive optimizations, r_lights engine variable, OpenGL VBO support --- src/core/entity.cc | 7 ++ src/core/gameserver.cc | 41 +++--- src/model/asefile.cc | 5 +- src/model/fragment.cc | 2 +- src/model/fragment.h | 29 ++--- src/model/mapfile.cc | 2 +- src/model/vertexarray.cc | 3 + src/model/vertexarray.h | 11 ++ src/render/draw.cc | 318 ++++++++++++++++++++++++++--------------------- src/render/gl.cc | 5 + src/render/gl.h | 11 ++ src/render/render.cc | 6 +- src/render/render.h | 2 + src/render/state.cc | 51 +++++++- src/render/state.h | 9 ++ 15 files changed, 318 insertions(+), 184 deletions(-) diff --git a/src/core/entity.cc b/src/core/entity.cc index c76b23a..c99c186 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -14,6 +14,7 @@ #include "core/cvar.h" #include "core/application.h" #include "core/gameinterface.h" +#include "core/gameserver.h" #include "BulletCollision/CollisionShapes/btBoxShape.h" @@ -596,6 +597,12 @@ void EntityDynamic::frame(float seconds) return; } + if (flag_is_set(KeepAlive)) { + if ((keepalive_time() > 0.0f) && (keepalive_time() < server()->time())) { + die(); + } + } + // transfer bullet state to entity state if (entity_body) { // this makes sure an update is sent if speed goes to 0 in the next step diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index e6c44d0..344c069 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -588,38 +588,35 @@ void GameServer::frame(unsigned long timestamp) // send network updates server_network->frame(server_timestamp); } - - // mark all entities as updated + const float keepalive_distance_squared = range::fxdistance * range::fxdistance; + + // FIXME KeepAlive sweep has to be done in linear order, O(n^2) is extremely slow with a large number of entities - for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end();) { + for (Entity::Registry::const_iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { - // perform a keep-alive pass - if ((*it).second->flag_is_set(Entity::KeepAlive) && ((*it).second->type() == Entity::Dynamic) && (*it).second->zone()) { + // set keepalive timeout + if ((*it).second->type() == Entity::Controlable) { + const EntityControlable *controlable = static_cast((*it).second); - bool keepalive = false; - EntityDynamic *entity = static_cast((*it).second); - - for (Zone::Content::const_iterator zit = entity->zone()->content().begin(); zit != entity->zone()->content().end(); zit++) { - - if (( (*zit)->type() == Entity::Controlable) && ( (*zit) != entity)) { + if ( (controlable->state() != Entity::Docked) && controlable->owner() && controlable->zone() ) { + for (Zone::Content::iterator zit = controlable->zone()->content().begin(); zit != controlable->zone()->content().end(); zit++) { - const EntityControlable *other = static_cast(*zit); - if (other->owner() && (other->state() != Entity::Docked) && (math::distancesquared(entity->location(), other->location()) < keepalive_distance_squared)) { - keepalive = true; + if ( ((*zit)->flag_is_set(Entity::KeepAlive)) && ((*zit)->type() == Entity::Dynamic) && ((*zit) != controlable) ) { + EntityDynamic *dynamic = static_cast(*zit); + if (math::distancesquared(controlable->location(), dynamic->location()) < keepalive_distance_squared) { + dynamic->set_keepalive_time(time() + dynamic->keepalive_timeout()); + } } } - } - if (keepalive) { - entity->set_keepalive_time(time() + entity->keepalive_timeout()); - } else if ((entity->keepalive_time() > 0.0f) && (entity->keepalive_time() < time())) { - entity->die(); - } } - - // delete the entity if necessary + } + + // remove deleted entities and mark remaining entities as updated + for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end();) { + // remove deleted entities if ((*it).second->entity_destroyed) { delete (*it).second; (*it).second = 0; diff --git a/src/model/asefile.cc b/src/model/asefile.cc index f02c450..0275603 100644 --- a/src/model/asefile.cc +++ b/src/model/asefile.cc @@ -686,8 +686,9 @@ Model *ASEFile::load(const std::string &name) model->model_maxbbox.assign (asefile.ase_maxbbox * SCALE); model->set_radius(math::max(model->model_minbbox.length(), model->model_maxbbox.length())); - for (FragmentGroup::iterator fit = asefile.fragmentgroup()->begin(); fit != asefile.fragmentgroup()->end(); fit++) { - Fragment *fragment = (*fit); + for (FragmentGroup::Fragments::const_iterator fit = asefile.fragmentgroup()->fragments().begin(); fit != asefile.fragmentgroup()->fragments().end(); fit++) { + + const Fragment *fragment = (*fit); model->model_tris_count += fragment->structural_size() + fragment->detail_size(); } model->add_group(asefile.fragmentgroup()); diff --git a/src/model/fragment.cc b/src/model/fragment.cc index 9071b00..30e89e0 100644 --- a/src/model/fragment.cc +++ b/src/model/fragment.cc @@ -74,7 +74,7 @@ FragmentGroup::~FragmentGroup() void FragmentGroup::clear() { - for (iterator it = group_fragments.begin(); it != group_fragments.end(); it++) { + for (Fragments::iterator it = group_fragments.begin(); it != group_fragments.end(); it++) { delete(*it); } group_fragments.clear(); diff --git a/src/model/fragment.h b/src/model/fragment.h index 6d65f7a..9da30b0 100644 --- a/src/model/fragment.h +++ b/src/model/fragment.h @@ -81,11 +81,14 @@ class FragmentGroup public: enum Type {None = 0, Rotate = 1, Door = 2 }; - typedef std::list::iterator iterator; + /// type definition for a list of model fragments + typedef std::list Fragments; FragmentGroup(); ~FragmentGroup(); + + /* ---- inspectors ----------------------------------------- */ inline const Type type() const { return group_type; @@ -111,7 +114,16 @@ public: return group_transform; } + inline const size_t size() const { + return group_fragments.size(); + } + inline const Fragments & fragments() const { + return group_fragments; + } + + /* ---- mutators ------------------------------------------- */ + inline void set_type(const Type type) { group_type = type; } @@ -136,18 +148,6 @@ public: group_transform = transform; } - inline iterator begin() { - return group_fragments.begin(); - } - - inline iterator end() { - return group_fragments.end(); - } - - inline const size_t size() const { - return group_fragments.size(); - } - inline void add_fragment(Fragment *fragment) { group_fragments.push_back(fragment); } @@ -155,9 +155,6 @@ public: void clear(); private: - /// type definition for a list of model fragments - typedef std::list Fragments; - Fragments group_fragments; math::Vector3f group_location; math::Axis group_axis; diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc index 6bac44e..e3fda6c 100644 --- a/src/model/mapfile.cc +++ b/src/model/mapfile.cc @@ -1451,7 +1451,7 @@ Model * MapFile::load(std::string const &name) groupdst->set_axis(groupsrc->axis() * tag_submodel->axis()); // copy fragments, this only copies the original fragment's pointer into the vertex array - for (FragmentGroup::iterator fit = groupsrc->begin(); fit != groupsrc->end(); fit++) { + for (FragmentGroup::Fragments::const_iterator fit = groupsrc->fragments().begin(); fit != groupsrc->fragments().end(); fit++) { Fragment *fragmentdst = new Fragment(*(*fit)); groupdst->add_fragment(fragmentdst); } diff --git a/src/model/vertexarray.cc b/src/model/vertexarray.cc index a559892..d06b976 100644 --- a/src/model/vertexarray.cc +++ b/src/model/vertexarray.cc @@ -40,6 +40,7 @@ VertexArray::~VertexArray() void VertexArray::clear() { + vertex_dirty = true; vertex_index = 0; vertex_overflow = false; @@ -127,6 +128,8 @@ size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, } vertex_index += 8; + + vertex_dirty = true; return 1; } diff --git a/src/model/vertexarray.h b/src/model/vertexarray.h index 2e43f2a..9a71811 100644 --- a/src/model/vertexarray.h +++ b/src/model/vertexarray.h @@ -38,6 +38,11 @@ public: return vertex_overflow; } + /// return true if the vertex data has changed and needs to uploaded to video memory + inline bool dirty() const { + return vertex_dirty; + } + /// pointer to model vertices, sequential in GL_T2F_N3F_V3F format inline const float *ptr() const { return vertex_data; @@ -52,6 +57,10 @@ public: inline size_t index() const { return vertex_index; } + + inline void set_dirty(const bool dirty = true) { + vertex_dirty = dirty; + } static inline VertexArray *instance() { return vertex_instance; @@ -69,6 +78,8 @@ private: static VertexArray *vertex_instance; bool vertex_overflow; + + bool vertex_dirty; }; } diff --git a/src/render/draw.cc b/src/render/draw.cc index 4fc0b60..ed2c8f7 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -51,6 +51,9 @@ float zone_light[4]; // locaton of the zone light math::Color zone_color; // color of the zone light bool has_zone_light = false; +bool draw_particles = true; +bool draw_lights = true; + typedef std::map Globes; Globes globes_list; @@ -59,7 +62,18 @@ Globes globes_list; void pass_prepare(float seconds) { using namespace model; - + + // render settings for this pass_prepare + draw_lights = true; + if (r_lights && (r_lights->value() <= 0.0f)) { + draw_lights = false; + } + + draw_particles = true; + if (r_particles && (r_particles->value() <= 0.0f)) { + draw_particles = false; + } + // lighting settings for the default light GL_LIGHT0 GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat ambient_light[] = { r_ambient->value(), r_ambient->value(), r_ambient->value(), 1.0f }; @@ -506,7 +520,7 @@ void draw_pass_default() /* ---- Model Fragments -------------------------------------------- */ -void draw_fragment(model::Fragment *fragment, bool draw_details) +void draw_fragment(const model::Fragment *fragment, bool draw_details) { size_t index = fragment->index(); @@ -564,9 +578,9 @@ void draw_model_fragments(model::Model *model, gl::texgeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); gl::texgeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - for (model::Model::Groups::iterator git = model->groups().begin(); git != model->groups().end(); git++) { + for (model::Model::Groups::const_iterator git = model->groups().begin(); git != model->groups().end(); git++) { - model::FragmentGroup *group = (*git); + const model::FragmentGroup *group = (*git); if (group->transform()) { gl::push(); @@ -585,9 +599,9 @@ void draw_model_fragments(model::Model *model, gl::scale(s, s, s); } - for (model::FragmentGroup::iterator fit = group->begin(); fit != group->end(); fit++) { + for (model::FragmentGroup::Fragments::const_iterator fit = group->fragments().begin(); fit != group->fragments().end(); fit++) { - model::Fragment *fragment = (*fit); + const model::Fragment *fragment = (*fit); if (fragment->material() != material) { material = fragment->material(); @@ -930,175 +944,178 @@ void draw_pass_model_fx(float elapsed) // default light texture size_t current_texture = Textures::bind("textures/fx/flare00"); gl::enable(GL_TEXTURE_2D); + + if (draw_lights) { - gl::begin(gl::Quads); + gl::begin(gl::Quads); - // draw model lights - for (model::Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) { - model::Light *light = (*lit); + // draw model lights + for (model::Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) { + model::Light *light = (*lit); - // engine activated lights - if (light->engine()) { - if (entity->type() == core::Entity::Controlable) { - core::EntityControlable *ec = static_cast(entity); - if ((ec->state() == core::Entity::ImpulseInitiate) || (ec->state() == core::Entity::Impulse)) { - thrust = 1.0f; - } else { - thrust = ec->thrust(); - if (thrust < 0.001f) { - continue; // next light + // engine activated lights + if (light->engine()) { + if (entity->type() == core::Entity::Controlable) { + core::EntityControlable *ec = static_cast(entity); + if ((ec->state() == core::Entity::ImpulseInitiate) || (ec->state() == core::Entity::Impulse)) { + thrust = 1.0f; + } else { + thrust = ec->thrust(); + if (thrust < 0.001f) { + continue; // next light + } } + } else { + continue; // next light } - } else { - continue; // next light } - } - // strobe frequency - if (light->strobe()) { - t = (core::application()->time() + ext_render(entity)->fuzz() - light->offset()) * light->frequency(); - if ((t - floorf(t)) > light->time()) { - continue; // next light + // strobe frequency + if (light->strobe()) { + t = (core::application()->time() + ext_render(entity)->fuzz() - light->offset()) * light->frequency(); + if ((t - floorf(t)) > light->time()) { + continue; // next light + } } - } - // default alpha is 0.8 - a = 0.8f; - if (light->entity()) { - color.assign(entity->color()); - } else if (light->engine()) { - color.assign(entity->model()->enginecolor()); - a *= thrust; - } else { - color.assign(light->color()); - } - color.a = a; + // default alpha is 0.8 + a = 0.8f; + if (light->entity()) { + color.assign(entity->color()); + } else if (light->engine()) { + color.assign(entity->model()->enginecolor()); + a *= thrust; + } else { + color.assign(light->color()); + } + color.a = a; - location.assign(entity->location() + (entity->axis() * light->location())); - light_size = 0.0625f * light->radius(); + location.assign(entity->location() + (entity->axis() * light->location())); + light_size = 0.0625f * light->radius(); - // track OpenGL state changes - if (current_texture != light->texture()) { - gl::end(); - current_texture = Textures::bind(light->texture()); - gl::begin(gl::Quads); - } + // track OpenGL state changes + if (current_texture != light->texture()) { + gl::end(); + current_texture = Textures::bind(light->texture()); + gl::begin(gl::Quads); + } - // draw the quad - gl::color(color); + // draw the quad + gl::color(color); - glTexCoord2f(0, 1); - gl::vertex(location + (Camera::axis().up() - Camera::axis().left()) * light_size); - glTexCoord2f(0, 0); - gl::vertex(location + (Camera::axis().up() + Camera::axis().left()) * light_size); - glTexCoord2f(1, 0); - gl::vertex(location + (Camera::axis().up() * -1 + Camera::axis().left()) * light_size); - glTexCoord2f(1, 1); - gl::vertex(location + (Camera::axis().up() * -1 - Camera::axis().left()) * light_size); - Stats::quads++; + glTexCoord2f(0, 1); + gl::vertex(location + (Camera::axis().up() - Camera::axis().left()) * light_size); + glTexCoord2f(0, 0); + gl::vertex(location + (Camera::axis().up() + Camera::axis().left()) * light_size); + glTexCoord2f(1, 0); + gl::vertex(location + (Camera::axis().up() * -1 + Camera::axis().left()) * light_size); + glTexCoord2f(1, 1); + gl::vertex(location + (Camera::axis().up() * -1 - Camera::axis().left()) * light_size); + Stats::quads++; - } + } - // draw flares - for (model::Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) { - model::Flare *flare = (*flit); + // draw flares + for (model::Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) { + model::Flare *flare = (*flit); - // engine activated flares - if (flare->engine()) { - if (entity->type() == core::Entity::Controlable) { - core::EntityControlable *ec = static_cast(entity); - if ((ec->state() == core::Entity::ImpulseInitiate) || (ec->state() == core::Entity::Impulse)) { - thrust = 1.0f; - } else { - thrust = ec->thrust(); - if (thrust < 0.001f) { - continue; // next flare + // engine activated flares + if (flare->engine()) { + if (entity->type() == core::Entity::Controlable) { + core::EntityControlable *ec = static_cast(entity); + if ((ec->state() == core::Entity::ImpulseInitiate) || (ec->state() == core::Entity::Impulse)) { + thrust = 1.0f; + } else { + thrust = ec->thrust(); + if (thrust < 0.001f) { + continue; // next flare + } } + } else { + continue; // next flare } - } else { - continue; // next flare } - } - // strobe frequency - if (flare->strobe()) { - t = (core::application()->time() + ext_render(entity)->fuzz() - flare->offset()) * flare->frequency(); - if ((t - floorf(t)) > flare->time()) { - continue; // next flare + // strobe frequency + if (flare->strobe()) { + t = (core::application()->time() + ext_render(entity)->fuzz() - flare->offset()) * flare->frequency(); + if ((t - floorf(t)) > flare->time()) { + continue; // next flare + } } - } - - // calulcate viewing angle factor - flare_axis.assign(entity->axis() * flare->axis()); - a = math::absf(dotproduct(flare_axis.forward(), Camera::axis().forward())); - if (a < 0.01f) { - continue; // next flare - } - // alpha decreases with viewing angle - a *= 0.8f; - if (flare->entity()) { - color.assign(entity->color()); - } else if (flare->engine()) { - color.assign(entity->model()->enginecolor()); - a *= thrust; - } else { - color.assign(flare->color()); - } - color.a = a; + // calulcate viewing angle factor + flare_axis.assign(entity->axis() * flare->axis()); + a = math::absf(dotproduct(flare_axis.forward(), Camera::axis().forward())); + if (a < 0.01f) { + continue; // next flare + } - location.assign(entity->location() + (entity->axis() * flare->location())); - light_size = 0.0625f * flare->radius(); + // alpha decreases with viewing angle + a *= 0.8f; + if (flare->entity()) { + color.assign(entity->color()); + } else if (flare->engine()) { + color.assign(entity->model()->enginecolor()); + a *= thrust; + } else { + color.assign(flare->color()); + } + color.a = a; - // track OpenGL state changes - if ((current_cull != flare->cull()) || (current_texture != flare->texture())) { - gl::end(); + location.assign(entity->location() + (entity->axis() * flare->location())); + light_size = 0.0625f * flare->radius(); - if (current_texture != flare->texture()) { - current_texture = Textures::bind(flare->texture()); - } + // track OpenGL state changes + if ((current_cull != flare->cull()) || (current_texture != flare->texture())) { + gl::end(); - if (current_cull != flare->cull()) { - if (flare->cull() == model::CullNone) { - gl::disable(GL_CULL_FACE); - current_cull = model::CullNone; - } else { - if (current_cull == model::CullNone) { - gl::enable(GL_CULL_FACE); - } + if (current_texture != flare->texture()) { + current_texture = Textures::bind(flare->texture()); + } - if (flare->cull() == model::CullBack) { - gl::cullface(GL_BACK); - current_cull = model::CullBack; + if (current_cull != flare->cull()) { + if (flare->cull() == model::CullNone) { + gl::disable(GL_CULL_FACE); + current_cull = model::CullNone; } else { - gl::cullface(GL_FRONT); - current_cull = model::CullFront; + if (current_cull == model::CullNone) { + gl::enable(GL_CULL_FACE); + } + + if (flare->cull() == model::CullBack) { + gl::cullface(GL_BACK); + current_cull = model::CullBack; + } else { + gl::cullface(GL_FRONT); + current_cull = model::CullFront; + } } } + + gl::begin(gl::Quads); } - gl::begin(gl::Quads); - } + // draw the quad + gl::color(color); - // draw the quad - gl::color(color); + glTexCoord2f(0, 1); + gl::vertex(location + (flare_axis.up() + flare_axis.left()) * light_size); + glTexCoord2f(0, 0); + gl::vertex(location + (flare_axis.up() - flare_axis.left()) * light_size); + glTexCoord2f(1, 0); + gl::vertex(location + (flare_axis.up() * -1 - flare_axis.left()) * light_size); + glTexCoord2f(1, 1); + gl::vertex(location + (flare_axis.up() * -1 + flare_axis.left()) * light_size); - glTexCoord2f(0, 1); - gl::vertex(location + (flare_axis.up() + flare_axis.left()) * light_size); - glTexCoord2f(0, 0); - gl::vertex(location + (flare_axis.up() - flare_axis.left()) * light_size); - glTexCoord2f(1, 0); - gl::vertex(location + (flare_axis.up() * -1 - flare_axis.left()) * light_size); - glTexCoord2f(1, 1); - gl::vertex(location + (flare_axis.up() * -1 + flare_axis.left()) * light_size); + Stats::quads++; + } - Stats::quads++; + gl::end(); } - gl::end(); - // draw particle systems - if (r_particles->value() && ext_render(entity)->particles().size()) { + if (draw_particles && ext_render(entity)->particles().size()) { for (RenderExt::ParticleSystems::iterator it = ext_render(entity)->particles().begin(); it != ext_render(entity)->particles().end(); it++) { ParticleSystem *particlesystem = (*it); @@ -1216,9 +1233,29 @@ void draw(float seconds) if (r_wireframe && r_wireframe->value()) { glPolygonMode(GL_FRONT, GL_LINE); } - + + // check if the vertexarray needs re-uploading // set vertex array pointers - glInterleavedArrays(GL_T2F_N3F_V3F, 0, core::game()->vertexarray()->ptr()); + if (State::has_vbo()) { + gl::bindbuffer(GL_ARRAY_BUFFER, State::vbo()); + + if (core::game()->vertexarray()->dirty()) { + gl::bufferdata(GL_ARRAY_BUFFER, sizeof(float) * core::game()->vertexarray()->index(), core::game()->vertexarray()->ptr(), GL_STATIC_DRAW); + core::game()->vertexarray()->set_dirty(false); + + } + // Interleaved format is GL_T2F_N3F_V3F + + // void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr ) + glTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), 0); + // void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr) + glNormalPointer(GL_FLOAT, 8 * sizeof(GLfloat), (void*) (2 * sizeof(GLfloat))); + // void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) + glVertexPointer(3, GL_FLOAT, 8 * sizeof(GLfloat), (void*) (5 * sizeof(GLfloat))); + + } else { + glInterleavedArrays(GL_T2F_N3F_V3F, 0, core::game()->vertexarray()->ptr()); + } // enable vertex arrays glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -1261,7 +1298,8 @@ void draw(float seconds) } // draw entity lights, flares and particles - draw_pass_model_fx(seconds); + if (draw_lights || draw_particles) + draw_pass_model_fx(seconds); // draw entity radius globe if (r_radius && r_radius->value()) { diff --git a/src/render/gl.cc b/src/render/gl.cc index f97468f..801c320 100644 --- a/src/render/gl.cc +++ b/src/render/gl.cc @@ -14,6 +14,11 @@ using math::Vector2f; using math::Vector3f; using math::Color; +genbuffers_func genbuffers = 0; +deletebuffers_func deletebuffers = 0; +bindbuffer_func bindbuffer = 0; +bufferdata_func bufferdata = 0; + std::string renderer() { return std::string((char *)glGetString(GL_RENDERER)); diff --git a/src/render/gl.h b/src/render/gl.h index dcac869..222ee0e 100644 --- a/src/render/gl.h +++ b/src/render/gl.h @@ -218,6 +218,17 @@ void frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdou void texgeni(GLenum coord, GLenum param, GLenum value); void texgenfv(GLenum coord, GLenum param, const GLfloat* value); + +typedef void (* genbuffers_func)(GLuint count, GLuint *id); +typedef void (* deletebuffers_func)(GLuint count, GLuint *id); +typedef void (* bindbuffer_func)(GLenum target, GLuint id); +typedef void (* bufferdata_func)(GLenum target, GLsizei size, const GLvoid *data, GLenum usage); + +extern genbuffers_func genbuffers; +extern deletebuffers_func deletebuffers; +extern bindbuffer_func bindbuffer; +extern bufferdata_func bufferdata; + } #endif // __INCLUDED_RENDER_GL_H__ diff --git a/src/render/render.cc b/src/render/render.cc index 398cb6b..baf9465 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -31,6 +31,7 @@ namespace render core::Cvar *r_axis = 0; core::Cvar *r_bbox = 0; core::Cvar *r_grid = 0; +core::Cvar *r_lights = 0; core::Cvar *r_particles = 0; core::Cvar *r_radius = 0; core::Cvar *r_sky = 0; @@ -66,7 +67,7 @@ void init(int width, int height) con_print << " renderer ^B" << gl::renderer() << std::endl; con_print << " vendor ^B" << gl::vendor() << std::endl; con_print << " version ^B" << gl::version() << std::endl; - + // initialize render state State::init(width, height); @@ -97,6 +98,9 @@ void init(int width, int height) r_particles = core::Cvar::get("r_particles", "1", core::Cvar::Archive); r_particles->set_info("[bool] render particles"); + + r_lights = core::Cvar::get("r_lights", "1", core::Cvar::Archive); + r_lights->set_info("[bool] render lights"); r_ambient = core::Cvar::get("r_ambient", "0.1", core::Cvar::Archive); r_ambient->set_info("[float] ambient light intensity"); diff --git a/src/render/render.h b/src/render/render.h index 5e5f3d1..97880cc 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -46,6 +46,8 @@ extern core::Cvar *r_axis; extern core::Cvar *r_bbox; /// render the spacegrid extern core::Cvar *r_grid; +/// render lights and flares +extern core::Cvar *r_lights; /// render particle systems extern core::Cvar *r_particles; /// render entity radius diff --git a/src/render/state.cc b/src/render/state.cc index 1a345c7..df2af75 100644 --- a/src/render/state.cc +++ b/src/render/state.cc @@ -7,6 +7,8 @@ #include #include +#include "SDL/SDL.h" + #include "render/state.h" #include "render/gl.h" #include "render/render.h" @@ -17,7 +19,9 @@ namespace render int State::render_width = 0; int State::render_height = 0; float State::render_aspect = 0; -bool State::render_has_generate_mipmaps = 0; +bool State::render_has_generate_mipmaps = false; +bool State::render_has_vbo = false; +GLuint State::render_vbo = 0; void State::init(int width, int height) { @@ -45,10 +49,55 @@ void State::init(int width, int height) } else { con_warn << "Could not determine OpenGL version!" << std::endl; } + + con_print << " Hardware generate mipmaps "; + if (render_has_generate_mipmaps) + con_print << "enabled" << std::endl; + else + con_print << "disabled" << std::endl; + + // initialize gl functions + render_has_vbo = true; + gl::genbuffers = (gl::genbuffers_func) SDL_GL_GetProcAddress("glGenBuffers"); + if (!gl::genbuffers) { + con_debug << " glGenBuffers not available" << std::endl; + render_has_vbo = false; + } + + gl::deletebuffers = (gl::deletebuffers_func) SDL_GL_GetProcAddress("glDeleteBuffers"); + if (!gl::deletebuffers) { + con_debug << " glDeleteBuffers not available" << std::endl; + render_has_vbo = false; + } + + gl::bindbuffer = (gl::bindbuffer_func) SDL_GL_GetProcAddress("glBindBuffer"); + if (!gl::bindbuffer) { + con_debug << " glBindBuffer not available" << std::endl; + render_has_vbo = false; + } + + gl::bufferdata = (gl::bufferdata_func) SDL_GL_GetProcAddress("glBufferData"); + if (!gl::bufferdata) { + con_debug << " glBufferData not available" << std::endl; + render_has_vbo = false; + } + + con_print << " Vertex bufer objects "; + if (render_has_vbo) + con_print << "enabled" << std::endl; + else + con_print << "disabled" << std::endl; + + // Generate VBO + if (render_has_vbo) + gl::genbuffers(1, &render_vbo); } void State::shutdown() { + // Delete VBO + if (render_has_vbo) + gl::deletebuffers(1, &render_vbo); } void State::resize(int width, int height) diff --git a/src/render/state.h b/src/render/state.h index 9a5a67c..3fa3b80 100644 --- a/src/render/state.h +++ b/src/render/state.h @@ -7,6 +7,7 @@ #ifndef __INCLUDED_RENDER_STATE_H__ #define __INCLUDED_RENDER_STATE_H__ +#include "render/gl.h" namespace render { @@ -32,6 +33,12 @@ public: inline static bool has_generate_mipmaps() { return render_has_generate_mipmaps; } + inline static bool has_vbo() { + return render_has_vbo; + } + inline static GLuint vbo() { + return render_vbo; + } private: static int render_width; @@ -39,6 +46,8 @@ private: static float render_aspect; static bool render_has_generate_mipmaps; + static bool render_has_vbo; + static GLuint render_vbo; }; } // namespace render -- cgit v1.2.3