nasty bug in Texture::create
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 20 Jan 2018 14:20:37 +0000 (16:20 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 20 Jan 2018 14:20:37 +0000 (16:20 +0200)
src/app.cc
src/rtarg.cc
src/rtarg.h
src/texture.cc
src/ui_exhibit.cc

index 7fc5c13..b1587f5 100644 (file)
@@ -147,8 +147,6 @@ bool app_init(int argc, char **argv)
        float ambient[] = {0.0, 0.0, 0.0, 0.0};
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
 
        float ambient[] = {0.0, 0.0, 0.0, 0.0};
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
 
-       glClearColor(1, 1, 1, 1);
-
        init_audio();
 
        if(!init_vrhands()) {
        init_audio();
 
        if(!init_vrhands()) {
@@ -386,6 +384,8 @@ void app_display()
                ImGui::ShowTestWindow();
        }
 
                ImGui::ShowTestWindow();
        }
 
+       glClearColor(1, 1, 1, 1);
+
        if(opt.vr) {
                // VR mode
                goatvr_draw_start();
        if(opt.vr) {
                // VR mode
                goatvr_draw_start();
index f90c1d3..12a4ddb 100644 (file)
@@ -1,3 +1,4 @@
+#include <assert.h>
 #include "rtarg.h"
 
 struct RTStackItem {
 #include "rtarg.h"
 
 struct RTStackItem {
@@ -51,9 +52,11 @@ bool push_render_target(RenderTarget *rt)
                vp[2] = prev->get_width();
                vp[3] = prev->get_height();
        } else {
                vp[2] = prev->get_width();
                vp[3] = prev->get_height();
        } else {
-               memcpy(vp, rstack[rtop].saved_vp, 4 * sizeof(int));
+               glGetIntegerv(GL_VIEWPORT, vp);
        }
        rstack[++rtop].rt = rt;
        }
        rstack[++rtop].rt = rt;
+
+       rt->bind();
        return true;
 }
 
        return true;
 }
 
@@ -79,6 +82,7 @@ RenderTarget::RenderTarget()
 {
        fbo = 0;
        rbdepth = 0;
 {
        fbo = 0;
        rbdepth = 0;
+       rbdepth_fmt = 0;
        width = height = tex_width = tex_height = 0;
        auto_vport = true;
        rtcount = 0;
        width = height = tex_width = tex_height = 0;
        auto_vport = true;
        rtcount = 0;
@@ -87,6 +91,7 @@ RenderTarget::RenderTarget()
                tex[i] = 0;
                own_texture[i] = true;
        }
                tex[i] = 0;
                own_texture[i] = true;
        }
+       depth = 0;
 }
 
 RenderTarget::~RenderTarget()
 }
 
 RenderTarget::~RenderTarget()
@@ -118,6 +123,7 @@ bool RenderTarget::create_mrt(int xsz, int ysz, int num, unsigned int fmt, unsig
                        tex[i]->create(tex_width, tex_height, TEX_2D, fmt);
                        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
                                        tex[i]->get_id(), 0);
                        tex[i]->create(tex_width, tex_height, TEX_2D, fmt);
                        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
                                        tex[i]->get_id(), 0);
+                       glBindTexture(GL_TEXTURE_2D, 0);
                        own_texture[i] = true;
                }
        } else {
                        own_texture[i] = true;
                }
        } else {
@@ -131,30 +137,31 @@ bool RenderTarget::create_mrt(int xsz, int ysz, int num, unsigned int fmt, unsig
        }
 
        if(flags & (RT_DEPTH | RT_STENCIL)) {
        }
 
        if(flags & (RT_DEPTH | RT_STENCIL)) {
-               unsigned int fmt, attachment;
+               unsigned int attachment;
 
                glGenRenderbuffers(1, &rbdepth);
                glBindRenderbuffer(GL_RENDERBUFFER, rbdepth);
 
                switch(flags & (RT_DEPTH | RT_STENCIL)) {
                case RT_DEPTH:
 
                glGenRenderbuffers(1, &rbdepth);
                glBindRenderbuffer(GL_RENDERBUFFER, rbdepth);
 
                switch(flags & (RT_DEPTH | RT_STENCIL)) {
                case RT_DEPTH:
-                       fmt = GL_DEPTH_COMPONENT24;
+                       rbdepth_fmt = GL_DEPTH_COMPONENT24;
                        attachment = GL_DEPTH_ATTACHMENT;
                        break;
 
                case RT_STENCIL:
                        attachment = GL_DEPTH_ATTACHMENT;
                        break;
 
                case RT_STENCIL:
-                       fmt = GL_STENCIL_INDEX8;
+                       rbdepth_fmt = GL_STENCIL_INDEX8;
                        attachment = GL_STENCIL_ATTACHMENT;
                        break;
 
                case RT_DEPTH | RT_STENCIL:
                        attachment = GL_STENCIL_ATTACHMENT;
                        break;
 
                case RT_DEPTH | RT_STENCIL:
-                       fmt = GL_DEPTH24_STENCIL8;
+                       rbdepth_fmt = GL_DEPTH24_STENCIL8;
                        attachment = GL_DEPTH_STENCIL_ATTACHMENT;
                        break;
                }
 
                        attachment = GL_DEPTH_STENCIL_ATTACHMENT;
                        break;
                }
 
-               glRenderbufferStorage(GL_RENDERBUFFER, fmt, width, height);
+               glRenderbufferStorage(GL_RENDERBUFFER, rbdepth_fmt, width, height);
                glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbdepth);
                glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbdepth);
+               glBindRenderbuffer(GL_RENDERBUFFER, 0);
 
        } else if(depth) {
                attach_depth_texture(depth);
 
        } else if(depth) {
                attach_depth_texture(depth);
@@ -182,6 +189,36 @@ void RenderTarget::destroy()
        }
 }
 
        }
 }
 
+bool RenderTarget::resize(int xsz, int ysz)
+{
+       int new_tx = next_pow2(xsz);
+       int new_ty = next_pow2(ysz);
+
+       if(new_tx != tex_width || new_ty != tex_height) {
+               tex_width = new_tx;
+               tex_height = new_ty;
+
+               for(int i=0; i<4; i++) {
+                       if(tex[i]) {
+                               tex[i]->create(new_tx, new_ty, TEX_2D, tex[i]->get_format());
+                       }
+               }
+
+               if(depth) {
+                       depth->create(new_tx, new_ty, TEX_2D, depth->get_format());
+               }
+       }
+
+       if(rbdepth) {
+               glBindRenderbuffer(GL_RENDERBUFFER, rbdepth);
+               glRenderbufferStorage(GL_RENDERBUFFER, rbdepth_fmt, xsz, ysz);
+       }
+
+       width = xsz;
+       height = ysz;
+       return true;
+}
+
 int RenderTarget::get_width() const
 {
        return width;
 int RenderTarget::get_width() const
 {
        return width;
@@ -282,7 +319,7 @@ static void attach_depth_texture(Texture *tex)
 
        default:
                error_log("failed to attach depth/stencil texture: unexpected texture format: %x\n", fmt);
 
        default:
                error_log("failed to attach depth/stencil texture: unexpected texture format: %x\n", fmt);
-               break;
+               return;
        }
 
        glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex->get_id(), 0);
        }
 
        glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex->get_id(), 0);
index f77682d..2cead11 100644 (file)
@@ -22,7 +22,7 @@ private:
        int rtcount;
        // either the depth texture or a dummy depth render target is used
        Texture *depth;
        int rtcount;
        // either the depth texture or a dummy depth render target is used
        Texture *depth;
-       unsigned int rbdepth;
+       unsigned int rbdepth, rbdepth_fmt;
        Mat4 texmat; // texture matrix to map tex coords from [0,1] to the useful area
 
        bool own_texture[4];
        Mat4 texmat; // texture matrix to map tex coords from [0,1] to the useful area
 
        bool own_texture[4];
@@ -38,6 +38,8 @@ public:
                        unsigned int flags = RT_COLOR | RT_DEPTH);
        void destroy();
 
                        unsigned int flags = RT_COLOR | RT_DEPTH);
        void destroy();
 
+       bool resize(int xsz, int ysz);
+
        int get_width() const;
        int get_height() const;
 
        int get_width() const;
        int get_height() const;
 
index ed34798..3af8116 100644 (file)
@@ -185,7 +185,7 @@ void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt)
        glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
        glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
-       switch(type) {
+       switch(textype) {
        case TEX_2D:
                glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
                break;
        case TEX_2D:
                glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
                break;
index eda39c6..dd09678 100644 (file)
@@ -4,6 +4,7 @@
 #include "app.h"
 #include "snode.h"
 #include "shader.h"
 #include "app.h"
 #include "snode.h"
 #include "shader.h"
+#include "rtarg.h"
 
 struct Rect {
        float x, y, w, h;
 
 struct Rect {
        float x, y, w, h;
@@ -15,11 +16,15 @@ static void draw_tabs(const Rect &rect);
 static void draw_text(const Rect &rect);
 static void layout_text(const char *text);
 
 static void draw_text(const Rect &rect);
 static void layout_text(const char *text);
 
+static float aspect;
+static int ui_width, ui_height;
+
+static RenderTarget *rtarg;
 static const SceneNode *parent;
 static Vec3 pos;
 static Vec2 size;
 static const SceneNode *parent;
 static Vec3 pos;
 static Vec2 size;
-static float text_padding;
-static float text_scale = 0.05f;
+static int text_padding;
+static float text_scale = 1.0f;//0.05f;
 static Exhibit *ex;
 static int vis_tab;
 static float scroll;
 static Exhibit *ex;
 static int vis_tab;
 static float scroll;
@@ -38,13 +43,24 @@ bool exui_init()
 {
        size.x = 15;
        size.y = 18;
 {
        size.x = 15;
        size.y = 18;
-       text_padding = size.x * 0.01;
+       text_padding = ui_width / 100;
+
+       aspect = size.x / size.y;
+       ui_height = 512;
+       ui_width = ui_height * aspect;
+
+       rtarg = new RenderTarget;
+       if(!rtarg->create(ui_width, ui_height, GL_RGB)) {
+               error_log("failed to create exui render target\n");
+               return false;
+       }
 
        return true;
 }
 
 void exui_shutdown()
 {
 
        return true;
 }
 
 void exui_shutdown()
 {
+       delete rtarg;
 }
 
 void exui_setnode(const SceneNode *node)
 }
 
 void exui_setnode(const SceneNode *node)
@@ -92,33 +108,28 @@ void exui_update(float dt)
        }
 }
 
        }
 }
 
-void exui_draw()
+static void draw_2d_ui()
 {
 {
-       if(!exsel_active) return;
-       if(!ui_font) return;
-
        dtx_use_font(ui_font, ui_font_size);
        float rowspc = dtx_line_height() * text_scale;
 
        dtx_use_font(ui_font, ui_font_size);
        float rowspc = dtx_line_height() * text_scale;
 
-       Rect rect = {-size.x / 2.0f, -size.y / 2.0f, size.x, size.y};
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
+       glOrtho(0, ui_width, 0, ui_height, -1, 1);
 
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
 
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
-       if(parent) {
-               glMultMatrixf(parent->get_matrix()[0]);
-       }
-       glTranslatef(pos.x, pos.y, pos.z);
-       glScalef(1, -1, 1);
+       glLoadIdentity();
 
        bind_shader(0);
 
        glPushAttrib(GL_ENABLE_BIT);
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_LIGHTING);
 
        bind_shader(0);
 
        glPushAttrib(GL_ENABLE_BIT);
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_LIGHTING);
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-       glDepthMask(0);
+       glDisable(GL_DEPTH_TEST);
 
 
+       Rect rect = {0, 0, (float)ui_width, (float)ui_height};
        draw_frame(rect);
        Rect tbar_rect = {rect.x, rect.y, rect.w, rowspc};
        draw_titlebar(tbar_rect);
        draw_frame(rect);
        Rect tbar_rect = {rect.x, rect.y, rect.w, rowspc};
        draw_titlebar(tbar_rect);
@@ -127,9 +138,60 @@ void exui_draw()
        Rect text_rect = {rect.x, tabs_rect.y + rowspc, rect.w, rect.h - tabs_rect.y - rowspc};
        draw_text(text_rect);
 
        Rect text_rect = {rect.x, tabs_rect.y + rowspc, rect.w, rect.h - tabs_rect.y - rowspc};
        draw_text(text_rect);
 
+       glPopAttrib();
+
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+}
+
+void exui_draw()
+{
+       if(!exsel_active) return;
+       if(!ui_font) return;
+
+       // render the 2D UI in a texture
+       push_render_target(rtarg);
+       glClearColor(0, 1, 0, 0);
+       glClear(GL_COLOR_BUFFER_BIT);
+       draw_2d_ui();
+       pop_render_target();
+
+       // place UI image into the scene
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       if(parent) {
+               glMultMatrixf(parent->get_matrix()[0]);
+       }
+       glTranslatef(pos.x, pos.y, pos.z);
+
+       glPushAttrib(GL_ENABLE_BIT);
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+       glEnable(GL_TEXTURE_2D);
+       glDepthMask(0);
+
+       bind_shader(0);
+       bind_texture(rtarg->texture());
+
+       glMatrixMode(GL_TEXTURE);
+       glLoadMatrixf(rtarg->texture_matrix()[0]);
+
+       glBegin(GL_QUADS);
+       glColor3f(1, 1, 1);
+       glTexCoord2f(0, 0); glVertex2f(-size.x / 2, -size.y / 2);
+       glTexCoord2f(1, 0); glVertex2f(size.x / 2, -size.y / 2);
+       glTexCoord2f(1, 1); glVertex2f(size.x / 2, size.y / 2);
+       glTexCoord2f(0, 1); glVertex2f(-size.x / 2, size.y / 2);
+       glEnd();
+
+       glLoadIdentity();
+
        glDepthMask(1);
        glPopAttrib();
 
        glDepthMask(1);
        glPopAttrib();
 
+       glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
 }
 
        glPopMatrix();
 }
 
@@ -212,10 +274,10 @@ static void layout_text(const char *text)
                        last_break = text;
                }
 
                        last_break = text;
                }
 
-               if(pos >= size.x - text_padding) {
+               if(pos >= ui_width - text_padding) {
                        if(text == text_lines.back()) {
                                // not even a single character fits on a line... abort
                        if(text == text_lines.back()) {
                                // not even a single character fits on a line... abort
-                               warning_log("text layout failed. glyph %d doesn't fit in line (%g)\n", code, size.x - 2.0 * text_padding);
+                               warning_log("text layout failed. glyph %d doesn't fit in line (%d)\n", code, ui_width - 2 * text_padding);
                                text_lines.clear();
                                return;
                        }
                                text_lines.clear();
                                return;
                        }