X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Frenderer.cc;h=deff1b9b2f2b38972174f2bc4c90f918d592c67c;hp=bb274f21960f29b6f30da8de90ae79380d1ef0c4;hb=9480e20f4de41693ebd1f22e63d3bcecde878f70;hpb=fc00873a180b1b7272d94a32dcc40d0d44ed2b72 diff --git a/src/renderer.cc b/src/renderer.cc index bb274f2..deff1b9 100644 --- a/src/renderer.cc +++ b/src/renderer.cc @@ -1,16 +1,65 @@ #include "renderer.h" +#include "rtarg.h" +#include "app.h" +#include "sdr.h" + +enum { + USE_TEXMAP = 1, + USE_MIRROR = 2, +}; +static const char *use_flag_str[] = { + "#define USE_TEXMAP\n", + "#define USE_MIRROR\n" +}; +#define NUM_USE_FLAGS ((int)(sizeof use_flag_str / sizeof *use_flag_str)) + + +static RenderTarget *rtmirror; Renderer::Renderer() { mscn = 0; + ropt = RENDER_ALL; + shaders = 0; } Renderer::~Renderer() { + destroy(); + delete [] shaders; } bool Renderer::init() { + static bool once; + if(!rtmirror && !once) { + once = true; + rtmirror = new RenderTarget; + if(!rtmirror->create(vp_width, vp_height, GL_SRGB)) { + error_log("failed to create mirror render target (%dx%d)\n", vp_width, vp_height); + } + } + + int numsdr = 1 << NUM_USE_FLAGS; + shaders = new unsigned int[numsdr]; + + for(int i=0; imirrors && /* scene contains mirrors */ \ + (ropt & RENDER_MIRRORS) && /* mirror rendering is enabled */ \ + rtmirror /* mirror render target succesfully created */ + void Renderer::draw() const { if(!mscn) return; + if(DO_MIRRORS && current_render_target() != rtmirror) { + // check if the render target needs resizing + if(rtmirror->get_width() != vp_width || rtmirror->get_height() != vp_height) { + if(!rtmirror->resize(vp_width, vp_height)) { + error_log("failed to resize mirror render target (%dx%d)\n", vp_width, vp_height); + goto abort_mirrors; + } + } + + FlatMirror *mir = mscn->mirrors; + while(mir) { + draw_mirror(mir); + mir = mir->next; + } + } +abort_mirrors: + int num = (int)mscn->scenes.size(); for(int i=0; iscenes[i]; int nobj = (int)scn->objects.size(); for(int j=0; jobjects[j]->mtl.flat_mirror) { + continue; + } draw_object(scn->objects[j]); } } @@ -56,6 +132,64 @@ void Renderer::draw_object(Object *obj) const } if(vis) { + unsigned int use_mask = 0; + if(obj->mtl.stdtex[MTL_TEX_DIFFUSE]) { + use_mask |= USE_TEXMAP; + } + if(obj->mtl.stdtex[MTL_TEX_REFLECT] && obj->mtl.flat_mirror) { + use_mask |= USE_MIRROR; + } + + unsigned int sdr = shaders[use_mask]; + if(use_mask & USE_MIRROR) { + float sx = 1.0f / rtmirror->texture()->get_width(); + float sy = 1.0f / rtmirror->texture()->get_height(); + set_uniform_float2(sdr, "mirtex_scale", sx, sy); + set_uniform_float(sdr, "reflectivity", obj->mtl.reflect); + } + bind_program(sdr); + obj->draw(); } } + +void Renderer::draw_mirror(FlatMirror *mir) const +{ + push_render_target(rtmirror); + glClearColor(1, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearColor(1, 1, 1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + // TODO update mirror plane for movable mirrors? + + Mat4 mirmat; + mirmat.mirror(mir->wplane.normal, dot(mir->wplane.normal, mir->wplane.pt)); + glMultMatrixf(mirmat[0]); + + glFrontFace(GL_CW); + draw(); + glFrontFace(GL_CCW); + + glPopMatrix(); + pop_render_target(); + + if(dbg_key_pending & 1) { + dump_gl_texture(rtmirror->texture()->get_id(), "mirror.ppm"); + dbg_key_pending &= ~1; + } + + int nobj = mir->objects.size(); + for(int i=0; iobjects[i]; + + Texture *prev_refl_tex = obj->mtl.stdtex[MTL_TEX_REFLECT]; + obj->mtl.stdtex[MTL_TEX_REFLECT] = rtmirror->texture(); + + draw_object(mir->objects[i]); + + obj->mtl.stdtex[MTL_TEX_REFLECT] = prev_refl_tex; + } +}