From 2829b50d6b3d9e97fc9399f5b6929f7d64021366 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 17 May 2018 05:43:25 +0300 Subject: [PATCH] fixed reflections in VR --- Makefile | 6 ++++- sdr/lightmap.p.glsl | 3 ++- src/app.cc | 18 ++++++++++++++- src/renderer.cc | 5 +++++ src/rtarg.cc | 61 ++++++++++++++++++++++++++++++++++----------------- src/rtarg.h | 22 ++++++++++++++++--- 6 files changed, 89 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index 072abdb..370828e 100644 --- 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/$< diff --git a/sdr/lightmap.p.glsl b/sdr/lightmap.p.glsl index 37b2abb..034da25 100644 --- a/sdr/lightmap.p.glsl +++ b/sdr/lightmap.p.glsl @@ -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 diff --git a/src/app.cc b/src/app.cc index 96e92f3..44c65fd 100644 --- a/src/app.cc +++ b/src/app.cc @@ -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; diff --git a/src/renderer.cc b/src/renderer.cc index 0d23e38..a4f2edb 100644 --- a/src/renderer.cc +++ b/src/renderer.cc @@ -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); } diff --git a/src/rtarg.cc b/src/rtarg.cc index 12a4ddb..8a232b0 100644 --- a/src/rtarg.cc +++ b/src/rtarg.cc @@ -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); } } diff --git a/src/rtarg.h b/src/rtarg.h index 2cead11..22abc4f 100644 --- a/src/rtarg.h +++ b/src/rtarg.h @@ -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_ -- 1.7.10.4