#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;
+static int cur_vport[4];
Renderer::Renderer()
{
mscn = 0;
ropt = RENDER_ALL;
+ shaders = 0;
}
Renderer::~Renderer()
{
destroy();
+ delete [] shaders;
}
bool Renderer::init()
}
}
+ int numsdr = 1 << NUM_USE_FLAGS;
+ shaders = new unsigned int[numsdr];
+
+ for(int i=0; i<numsdr; i++) {
+ clear_shader_header(0);
+
+ for(int j=0; j<NUM_USE_FLAGS; j++) {
+ if(i & (1 << j)) {
+ add_shader_header(0, use_flag_str[j]);
+ }
+ }
+
+ if(!(shaders[i] = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap.p.glsl"))) {
+ return false;
+ }
+ set_uniform_int(shaders[i], "texmap", MTL_TEX_DIFFUSE);
+ set_uniform_int(shaders[i], "lightmap", MTL_TEX_LIGHTMAP);
+ set_uniform_int(shaders[i], "mirrortex", MTL_TEX_REFLECT);
+ }
+
return true;
}
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) {
+ info_log("resizing mirror render target to %dx%d\n", vp_width, 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;
}
}
+ glGetIntegerv(GL_VIEWPORT, cur_vport);
+
FlatMirror *mir = mscn->mirrors;
while(mir) {
draw_mirror(mir);
}
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_offs", -cur_vport[0], -cur_vport[1]);
+ set_uniform_float2(sdr, "mirtex_scale", sx, sy);
+ set_uniform_float(sdr, "reflectivity", obj->mtl.reflect);
+ }
+ bind_program(sdr);
+
obj->draw();
}
}
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
- float pdist = dot(mir->plane.normal, mir->plane.pt);
- Vec4 peq = Vec4(mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z, pdist);
-
- if(mir->node) {
- peq = mir->node->get_matrix() * peq;
- }
+ // TODO update mirror plane for movable mirrors?
Mat4 mirmat;
- mirmat.mirror(peq.x, peq.y, peq.z, peq.w);
+ mirmat.mirror(mir->wplane.normal, -dot(mir->wplane.normal, mir->wplane.pt));
glMultMatrixf(mirmat[0]);
glFrontFace(GL_CW);
glPopMatrix();
pop_render_target();
- dump_gl_texture(rtmirror->texture()->get_id(), "mirror.ppm");
+ 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; i<nobj; i++) {
+ Object *obj = (Object*)mir->objects[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;
}
}