simple ubershader system, reflection debugging
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 18 Mar 2018 12:42:28 +0000 (14:42 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 18 Mar 2018 12:42:28 +0000 (14:42 +0200)
src/app.cc
src/app.h
src/material.cc
src/material.h
src/metascene.cc
src/metascene.h
src/renderer.cc
src/renderer.h
src/scene.cc
src/sceneload.cc
src/snode.cc

index 30222f9..fcf5fe0 100644 (file)
@@ -41,10 +41,10 @@ bool opt_gear_wireframe;
 TextureSet texman;
 SceneSet sceneman;
 
-unsigned int sdr_ltmap, sdr_ltmap_notex;
-
 int fpexcept_enabled;
 
+unsigned int dbg_key_pending;
+
 static Avatar avatar;
 
 static float cam_dist = 0.0;
@@ -175,18 +175,6 @@ bool app_init(int argc, char **argv)
        }
        exui_setnode(&exslot_left.node);
 
-       if(!(sdr_ltmap_notex = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-notex.p.glsl"))) {
-               return false;
-       }
-       set_uniform_int(sdr_ltmap_notex, "texmap", MTL_TEX_DIFFUSE);
-       set_uniform_int(sdr_ltmap_notex, "lightmap", MTL_TEX_LIGHTMAP);
-
-       if(!(sdr_ltmap = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-tex.p.glsl"))) {
-               return false;
-       }
-       set_uniform_int(sdr_ltmap, "texmap", MTL_TEX_DIFFUSE);
-       set_uniform_int(sdr_ltmap, "lightmap", MTL_TEX_LIGHTMAP);
-
        if(!fb_srgb) {
                sdr_post_gamma = create_program_load("sdr/post_gamma.v.glsl", "sdr/post_gamma.p.glsl");
        }
@@ -671,6 +659,13 @@ void app_keyboard(int key, bool pressed)
                case KEY_RIGHT:
                        exui_change_tab(1);
                        break;
+
+               case KEY_F5:
+               case KEY_F6:
+               case KEY_F7:
+               case KEY_F8:
+                       dbg_key_pending |= 1 << (key - KEY_F5);
+                       break;
                }
        }
 
index 0e41312..8f40515 100644 (file)
--- a/src/app.h
+++ b/src/app.h
@@ -15,12 +15,12 @@ extern bool fb_srgb;
 extern TextureSet texman;
 extern SceneSet sceneman;
 
-extern unsigned int sdr_ltmap, sdr_ltmap_notex;
-
 extern ExSelection exsel_active;       // active (info/interact) exhibit
 extern ExSelection exsel_grab_left, exsel_grab_right; // grabbed on each hand
 extern ExSelection exsel_hover;                // hover
 
+extern unsigned int dbg_key_pending;
+
 extern int fpexcept_enabled;   // int so that C modules may fwd-delcare and use it
 
 enum {
index 26ab63d..a079c83 100644 (file)
@@ -37,9 +37,11 @@ void Material::setup() const
                }
        }
 
+       /*
        if(stdtex[MTL_TEX_LIGHTMAP]) {
                bind_program(stdtex[MTL_TEX_DIFFUSE] ? sdr_ltmap : sdr_ltmap_notex);
        }
+       */
 }
 
 void Material::add_texture(Texture *tex, int type)
@@ -78,7 +80,7 @@ int mtl_parse_type(const char *str)
        } else if(strcmp(str, "lightmap") == 0) {
                return MTL_TEX_LIGHTMAP;
        } else if(strcmp(str, "envmap") == 0) {
-               return MTL_TEX_ENVMAP;
+               return MTL_TEX_REFLECT;
        }
        return MTL_TEX_UNKNOWN;
 }
@@ -94,7 +96,7 @@ const char *mtl_type_string(int type)
                return "normalmap";
        case MTL_TEX_LIGHTMAP:
                return "lightmap";
-       case MTL_TEX_ENVMAP:
+       case MTL_TEX_REFLECT:
                return "envmap";
        default:
                break;
index a1244d4..4ca5c7d 100644 (file)
@@ -11,7 +11,7 @@ enum {
        MTL_TEX_SPECULAR,
        MTL_TEX_NORMALMAP,
        MTL_TEX_LIGHTMAP,
-       MTL_TEX_ENVMAP,
+       MTL_TEX_REFLECT,
 
        MTL_TEX_UNKNOWN
 };
index a85b65e..a45bfec 100644 (file)
@@ -203,7 +203,7 @@ Scene *MetaScene::extract_nodes(const char *qstr)
 
 int MetaScene::calc_mirror_planes()
 {
-       std::vector<Vec4> world_planes;
+       FlatMirror *planes = 0;
 
        int num_mirrors = 0;
        while(mirrors) {
@@ -241,33 +241,44 @@ int MetaScene::calc_mirror_planes()
                                } else {
                                        int plane_idx = obj->mtl.flat_mirror - MTL_MIRROR_AABB_PX;
                                        mir->plane = obj->get_aabox().get_plane(plane_idx);
-                                       debug_log("mirror plane: p(%f %f %f) n(%f %f %f)\n", mir->plane.pt.x, mir->plane.pt.y,
-                                                       mir->plane.pt.z, mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z);
                                }
 
-                               float pdist = dot(mir->plane.normal, mir->plane.pt);
-                               Vec4 plane_eq = Vec4(mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z, pdist);
-
+                               mir->wplane = mir->plane;
                                if(obj->node) {
-                                       plane_eq = obj->node->get_matrix() * plane_eq;
+                                       const Mat4 &xform = obj->node->get_matrix();
+                                       mir->wplane.pt = xform * mir->wplane.pt;
+                                       mir->wplane.normal = normalize(xform.upper3x3() * mir->wplane.normal);
                                }
 
                                // check to see if we have found this mirror plane already
                                bool found = false;
-                               int nplanes = world_planes.size();
-                               for(int k=0; k<nplanes; k++) {
-                                       if(1.0f - dot(plane_eq.xyz(), world_planes[k].xyz()) < 1e-4f &&
-                                                       fabs(plane_eq.w - world_planes[k].w) < 1e-4) {
+                               FlatMirror *node = planes;
+                               while(node) {
+                                       float d1 = dot(mir->wplane.normal, mir->wplane.pt);
+                                       float d2 = dot(node->wplane.normal, node->wplane.pt);
+
+                                       if(1.0f - dot(mir->wplane.normal, node->wplane.normal) < 1e-4f &&
+                                                       fabs(d1 - d2) < 1e-4) {
                                                found = true;
                                                break;
                                        }
+                                       node = node->next;
                                }
 
+                               debug_log("[%s@%s] mirror plane: local(%g %g %g %g), world(%g %g %g %g)%s\n",
+                                               obj->get_name(), obj->node ? obj->node->get_name() : "<no-node>",
+                                               mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z,
+                                               dot(mir->plane.normal, mir->plane.pt), mir->wplane.normal.x, mir->wplane.normal.y,
+                                               mir->wplane.normal.z, dot(mir->wplane.normal, mir->wplane.pt), found ? " duplicate" : "");
+
                                if(!found) {
                                        mir->next = mirrors;
                                        mirrors = mir;
 
-                                       world_planes.push_back(plane_eq);
+                                       node = new FlatMirror;
+                                       node->wplane = mir->wplane;
+                                       node->next = planes;
+                                       planes = node;
 
                                        mir->objects.push_back(obj);
                                        objmirror[obj] = mir;   // associate with object
@@ -279,6 +290,12 @@ int MetaScene::calc_mirror_planes()
                }
        }
 
+       while(planes) {
+               FlatMirror *tmp = planes;
+               planes = planes->next;
+               delete tmp;
+       }
+
        return num_mirrors;
 }
 
index 6987f00..0565f3d 100644 (file)
@@ -11,7 +11,8 @@
 
 
 struct FlatMirror {
-       Plane plane;
+       Plane plane;    // plane in local coordinates (original)
+       Plane wplane;   // world coords plane (derived, identical to plane if node == 0)
        float reflect;
        std::vector<Object*> objects;
        SceneNode *node;
index 43a96db..deff1b9 100644 (file)
@@ -1,6 +1,18 @@
 #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;
 
@@ -8,11 +20,13 @@ Renderer::Renderer()
 {
        mscn = 0;
        ropt = RENDER_ALL;
+       shaders = 0;
 }
 
 Renderer::~Renderer()
 {
        destroy();
+       delete [] shaders;
 }
 
 bool Renderer::init()
@@ -26,6 +40,26 @@ 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;
 }
 
@@ -98,6 +132,23 @@ 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();
        }
 }
@@ -105,20 +156,17 @@ void Renderer::draw_object(Object *obj) const
 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();
 
-       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);
@@ -128,10 +176,20 @@ void Renderer::draw_mirror(FlatMirror *mir) const
        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;
        }
 }
index e6aa8d5..01fc5fd 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef RENDERER_H_
 #define RENDERER_H_
 
+#include <vector>
 #include "metascene.h"
 
 enum {
@@ -12,6 +13,7 @@ enum {
 class Renderer {
 private:
        MetaScene *mscn;
+       unsigned int *shaders;
 
 public:
        unsigned int ropt;
index b439286..10304f6 100644 (file)
@@ -245,7 +245,7 @@ std::list<SceneNode*> Scene::match_nodes(const char *qstr) const
                std::regex re{qstr};
                find_nodes_rec(&res, nodes, re);
        }
-       return std::move(res);
+       return res;
 }
 
 Scene *Scene::extract_nodes(const char *qstr)
index 4c0d324..28f5877 100644 (file)
@@ -335,7 +335,7 @@ static int assimp_textype(aiTextureType type)
        case aiTextureType_EMISSIVE:
                return MTL_TEX_LIGHTMAP;
        case aiTextureType_REFLECTION:
-               return MTL_TEX_ENVMAP;
+               return MTL_TEX_REFLECT;
        default:
                break;
        }
index b171f35..fb2877d 100644 (file)
@@ -164,17 +164,17 @@ const Vec3 &SceneNode::get_node_scaling() const
 
 Vec3 SceneNode::get_position() const
 {
-       return xform * Vec3(0, 0, 0);
+       return xform.get_translation();
 }
 
 Quat SceneNode::get_rotation() const
 {
-       return rot;     // TODO
+       return xform.get_rotation();
 }
 
 Vec3 SceneNode::get_scaling() const
 {
-       return scale;   // TODO
+       return xform.get_scaling();
 }
 
 const Mat4 &SceneNode::get_matrix() const
@@ -220,6 +220,36 @@ void SceneNode::update(float dt)
 
                        ImGui::NextColumn();
                        ImGui::Checkbox("##vis", &visible);
+                       ImGui::SameLine();
+                       if(ImGui::Button("xform")) {
+                               ImGui::OpenPopup("xform_popup");
+                       }
+                       if(ImGui::BeginPopup("xform_popup")) {
+                               ImGui::Text("Local transform");
+                               Vec3 p = get_node_position();
+                               ImGui::BulletText("P: %g %g %g", p.x, p.y, p.z);
+                               Quat q = get_node_rotation();
+                               ImGui::BulletText("R: %g %g %g %g", q.x, q.y, q.z, q.w);
+                               Vec3 s = get_node_scaling();
+                               ImGui::BulletText("S: %g %g %g", s.x, s.y, s.z);
+
+                               ImGui::Separator();
+                               ImGui::Text("Global transform");
+                               p = get_position();
+                               ImGui::BulletText("P: %g %g %g", p.x, p.y, p.z);
+                               q = get_rotation();
+                               ImGui::BulletText("R: %g %g %g %g", q.x, q.y, q.z, q.w);
+                               s = get_scaling();
+                               ImGui::BulletText("S: %g %g %g", s.x, s.y, s.z);
+
+                               const Mat4 &mat = get_matrix();
+                               ImGui::BulletText("| %3.3f %3.3f %3.3f %3.3f |", mat[0][0], mat[0][1], mat[0][2], mat[0][3]);
+                               ImGui::BulletText("| %3.3f %3.3f %3.3f %3.3f |", mat[1][0], mat[1][1], mat[1][2], mat[1][3]);
+                               ImGui::BulletText("| %3.3f %3.3f %3.3f %3.3f |", mat[2][0], mat[2][1], mat[2][2], mat[2][3]);
+                               ImGui::BulletText("| %3.3f %3.3f %3.3f %3.3f |", mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
+
+                               ImGui::EndPopup();
+                       }
                        ImGui::NextColumn();
                        ImGui::PopID();
                }