+#include <assert.h>
#include "rtarg.h"
struct RTStackItem {
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;
+
+ rt->bind();
return true;
}
{
fbo = 0;
rbdepth = 0;
+ rbdepth_fmt = 0;
width = height = tex_width = tex_height = 0;
auto_vport = true;
rtcount = 0;
tex[i] = 0;
own_texture[i] = true;
}
+ depth = 0;
}
RenderTarget::~RenderTarget()
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 {
}
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:
- fmt = GL_DEPTH_COMPONENT24;
+ rbdepth_fmt = GL_DEPTH_COMPONENT24;
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:
- fmt = GL_DEPTH24_STENCIL8;
+ rbdepth_fmt = GL_DEPTH24_STENCIL8;
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);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
} else if(depth) {
attach_depth_texture(depth);
}
}
+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;
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);
#include "app.h"
#include "snode.h"
#include "shader.h"
+#include "rtarg.h"
struct Rect {
float x, y, w, h;
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 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;
{
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()
{
+ delete rtarg;
}
void exui_setnode(const SceneNode *node)
}
}
-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;
- 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();
- 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);
- 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);
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();
+ glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
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
- 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;
}