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`
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/$<
uniform sampler2D lightmap;
#ifdef USE_MIRROR
uniform sampler2D mirrortex;
+uniform vec2 mirtex_offs;
uniform vec2 mirtex_scale;
uniform float reflectivity;
#endif
#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
#include "opt.h"
#include "post.h"
#include "renderer.h"
+#include "rtarg.h"
#include "avatar.h"
#include "vrinput.h"
#include "exman.h"
#define exslot_mouse exslot_right
static Renderer *rend;
+static RenderTarget *goatvr_rtarg;
static Ray last_pick_ray;
have_handtracking = goatvr_have_handtracking();
goatvr_recenter();
+
+ goatvr_rtarg = new RenderTarget;
}
if(fb_srgb) {
app_grab_mouse(false);
if(opt.vr) {
+ delete goatvr_rtarg;
goatvr_shutdown();
}
destroy_vrhands();
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;
}
if(debug_gui) {
ImGui::Render();
}
+
+ if(gfbo) {
+ pop_render_target(RT_FAKE);
+ }
}
+
goatvr_draw_done();
vp_width = win_width;
static RenderTarget *rtmirror;
+static int cur_vport[4];
Renderer::Renderer()
{
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(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);
}
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");
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;
}
auto_vport = true;
rtcount = 0;
+ own_fbo = true;
for(int i=0; i<4; i++) {
tex[i] = 0;
own_texture[i] = true;
{
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ own_fbo = true;
width = xsz;
height = ysz;
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++) {
glDeleteRenderbuffers(1, &rbdepth);
rbdepth = 0;
}
- if(fbo) {
+ if(fbo && own_fbo) {
glDeleteFramebuffers(1, &fbo);
fbo = 0;
}
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);
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);
}
}
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;
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;
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);
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_