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/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 ++ 7 files changed, 260 insertions(+), 142 deletions(-) (limited to 'src/render') 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