fixed reflections in VR
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 17 May 2018 02:43:25 +0000 (05:43 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 17 May 2018 02:43:25 +0000 (05:43 +0300)
Makefile
sdr/lightmap.p.glsl
src/app.cc
src/renderer.cc
src/rtarg.cc
src/rtarg.h

index 072abdb..370828e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ obj = $(src:.cc=.o) $(csrc:.c=.o)
 dep = $(obj:.o=.d)
 bin = demo
 
-#opt = -O3 -ffast-math
+opt = -O3 -ffast-math
 dbg = -g
 
 incpath = -Isrc -Isrc/machine -I/usr/local/include `pkg-config --cflags sdl2`
@@ -51,6 +51,10 @@ $(bin): .clang_complete $(obj)
 cross:
        $(MAKE) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ sys=mingw
 
+.PHONY: cross-clean
+cross-clean:
+       $(MAKE) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ sys=mingw clean
+
 .PHONY: instalien
 instalien: demo.exe
        cp $< /alien/demo/$<
index 37b2abb..034da25 100644 (file)
@@ -5,6 +5,7 @@ uniform sampler2D texmap;
 uniform sampler2D lightmap;
 #ifdef USE_MIRROR
 uniform sampler2D mirrortex;
+uniform vec2 mirtex_offs;
 uniform vec2 mirtex_scale;
 uniform float reflectivity;
 #endif
@@ -23,7 +24,7 @@ void main()
 #endif
 
 #ifdef USE_MIRROR
-       vec3 refl = texture2D(mirrortex, gl_FragCoord.xy * mirtex_scale).rgb;
+       vec3 refl = texture2D(mirrortex, (gl_FragCoord.xy + mirtex_offs) * mirtex_scale).rgb;
        diffuse += refl * reflectivity; // just add it to diffuse until we get another source of specularity
 #endif
 
index 96e92f3..44c65fd 100644 (file)
@@ -15,6 +15,7 @@
 #include "opt.h"
 #include "post.h"
 #include "renderer.h"
+#include "rtarg.h"
 #include "avatar.h"
 #include "vrinput.h"
 #include "exman.h"
@@ -82,6 +83,7 @@ static ExhibitSlot exslot_left, exslot_right;
 #define exslot_mouse exslot_right
 
 static Renderer *rend;
+static RenderTarget *goatvr_rtarg;
 
 static Ray last_pick_ray;
 
@@ -123,6 +125,8 @@ bool app_init(int argc, char **argv)
                have_handtracking = goatvr_have_handtracking();
 
                goatvr_recenter();
+
+               goatvr_rtarg = new RenderTarget;
        }
 
        if(fb_srgb) {
@@ -222,6 +226,7 @@ void app_cleanup()
 
        app_grab_mouse(false);
        if(opt.vr) {
+               delete goatvr_rtarg;
                goatvr_shutdown();
        }
        destroy_vrhands();
@@ -421,14 +426,20 @@ void app_display()
                goatvr_draw_start();
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
+               unsigned int gfbo = goatvr_get_fbo();
+
                update(dt);
 
                for(int i=0; i<2; i++) {
                        // for each eye
                        goatvr_draw_eye(i);
-                       if(goatvr_get_fb_texture()) {
+                       if(gfbo) {
                                vp_width = goatvr_get_fb_eye_width(i);
                                vp_height = goatvr_get_fb_eye_height(i);
+
+                               // this is a lightweight operation
+                               goatvr_rtarg->create_wrap_fbo(gfbo, vp_width, vp_height);
+                               push_render_target(goatvr_rtarg, RT_FAKE);
                        } else {
                                vp_width = win_width / 2;
                        }
@@ -449,7 +460,12 @@ void app_display()
                        if(debug_gui) {
                                ImGui::Render();
                        }
+
+                       if(gfbo) {
+                               pop_render_target(RT_FAKE);
+                       }
                }
+
                goatvr_draw_done();
 
                vp_width = win_width;
index 0d23e38..a4f2edb 100644 (file)
@@ -15,6 +15,7 @@ static const char *use_flag_str[] = {
 
 
 static RenderTarget *rtmirror;
+static int cur_vport[4];
 
 Renderer::Renderer()
 {
@@ -90,12 +91,15 @@ void Renderer::draw() const
        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);
@@ -144,6 +148,7 @@ void Renderer::draw_object(Object *obj) const
                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);
                }
index 12a4ddb..8a232b0 100644 (file)
@@ -34,7 +34,7 @@ RenderTarget *current_render_target()
        return rstack[rtop].rt;
 }
 
-bool push_render_target(RenderTarget *rt)
+bool push_render_target(RenderTarget *rt, unsigned int flags)
 {
        if(!rt) {
                error_log("push_render_target(0) is invalid\n");
@@ -44,36 +44,39 @@ bool push_render_target(RenderTarget *rt)
                warning_log("push_render_target: overflow\n");
                return false;
        }
-       int *vp = rstack[rtop + 1].saved_vp;
-       RenderTarget *prev = current_render_target();
 
-       if(prev) {
-               vp[0] = vp[1] = 0;
-               vp[2] = prev->get_width();
-               vp[3] = prev->get_height();
-       } else {
+       if(!(flags & RT_NO_VPORT)) {
+               int *vp = rstack[rtop + 1].saved_vp;
                glGetIntegerv(GL_VIEWPORT, vp);
        }
        rstack[++rtop].rt = rt;
 
-       rt->bind();
+       if(!(flags & RT_NO_BIND)) {
+               rt->bind();
+       }
        return true;
 }
 
-bool pop_render_target()
+bool pop_render_target(unsigned int flags)
 {
        if(rtop <= 0) {
-               error_log("pop_render_target: undeflow\n");
+               error_log("pop_render_target: underflow\n");
                return false;
        }
 
-       int *vp = rstack[rtop].saved_vp;
-       glViewport(vp[0], vp[1], vp[2], vp[3]);
+       if(!(flags & RT_NO_VPORT)) {
+               int *vp = rstack[rtop].saved_vp;
+               glViewport(vp[0], vp[1], vp[2], vp[3]);
+       }
+
+       --rtop;
 
-       if(rstack[--rtop].rt) {
-               rstack[rtop].rt->bind();
-       } else {
-               glBindFramebuffer(GL_FRAMEBUFFER, 0);
+       if(!(flags & RT_NO_BIND)) {
+               if(rstack[rtop].rt) {
+                       rstack[rtop].rt->bind(RT_NO_VPORT);
+               } else {
+                       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+               }
        }
        return true;
 }
@@ -87,6 +90,7 @@ RenderTarget::RenderTarget()
        auto_vport = true;
        rtcount = 0;
 
+       own_fbo = true;
        for(int i=0; i<4; i++) {
                tex[i] = 0;
                own_texture[i] = true;
@@ -108,6 +112,7 @@ bool RenderTarget::create_mrt(int xsz, int ysz, int num, unsigned int fmt, unsig
 {
        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+       own_fbo = true;
 
        width = xsz;
        height = ysz;
@@ -171,6 +176,20 @@ bool RenderTarget::create_mrt(int xsz, int ysz, int num, unsigned int fmt, unsig
        return true;
 }
 
+bool RenderTarget::create_wrap_fbo(unsigned int fbo, int xsz, int ysz)
+{
+       this->fbo = fbo;
+       own_fbo = false;
+
+       width = tex_width = xsz;
+       height = tex_height = ysz;
+       rtcount = 1;
+
+       texmat = Mat4::identity;
+
+       return true;
+}
+
 void RenderTarget::destroy()
 {
        for(int i=0; i<4; i++) {
@@ -183,7 +202,7 @@ void RenderTarget::destroy()
                glDeleteRenderbuffers(1, &rbdepth);
                rbdepth = 0;
        }
-       if(fbo) {
+       if(fbo && own_fbo) {
                glDeleteFramebuffers(1, &fbo);
                fbo = 0;
        }
@@ -191,6 +210,8 @@ void RenderTarget::destroy()
 
 bool RenderTarget::resize(int xsz, int ysz)
 {
+       if(!own_fbo) return false;      /* TODO */
+
        int new_tx = next_pow2(xsz);
        int new_ty = next_pow2(ysz);
 
@@ -276,11 +297,11 @@ bool RenderTarget::auto_viewport() const
        return auto_vport;
 }
 
-void RenderTarget::bind() const
+void RenderTarget::bind(unsigned int flags) const
 {
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
 
-       if(auto_vport) {
+       if(auto_vport && !(flags & RT_NO_VPORT)) {
                glViewport(0, 0, width, height);
        }
 }
index 2cead11..22abc4f 100644 (file)
@@ -12,6 +12,14 @@ enum {
        RT_STENCIL = 4
 };
 
+// flags for push_render_target/pop_render_target and RenderTarget::bind
+enum {
+       RT_NO_VPORT     = 1,
+       RT_NO_BIND      = 2,
+
+       RT_FAKE         = RT_NO_VPORT | RT_NO_BIND
+};
+
 class RenderTarget {
 private:
        int width, height;
@@ -25,6 +33,7 @@ private:
        unsigned int rbdepth, rbdepth_fmt;
        Mat4 texmat; // texture matrix to map tex coords from [0,1] to the useful area
 
+       bool own_fbo;
        bool own_texture[4];
        bool auto_vport;
 
@@ -36,6 +45,13 @@ public:
                        unsigned int flags = RT_COLOR | RT_DEPTH);
        bool create_mrt(int xsz, int ysz, int num, unsigned int fmt = GL_RGB16F,
                        unsigned int flags = RT_COLOR | RT_DEPTH);
+       /* create a RenderTarget wrapping an existing FBO.
+        * At this point this is just a hack with limited functionality.
+        * Calls which return textures might return 0. get_width/get_height
+        * will return whatever is passed here as xsz/ysz. resize will not do
+        * anything.
+        */
+       bool create_wrap_fbo(unsigned int fbo, int xsz, int ysz);
        void destroy();
 
        bool resize(int xsz, int ysz);
@@ -52,14 +68,14 @@ public:
        void set_auto_viewport(bool enable);
        bool auto_viewport() const;
 
-       void bind() const;
+       void bind(unsigned int flags = 0) const;
        const Mat4 &texture_matrix() const;
 };
 
 void set_render_target(RenderTarget *rt);
 RenderTarget *current_render_target();
 
-bool push_render_target(RenderTarget *rt);
-bool pop_render_target();
+bool push_render_target(RenderTarget *rt, unsigned int flags = 0);
+bool pop_render_target(unsigned int flags = 0);
 
 #endif // RTARG_H_