2 #include "bufferbuilder.h"
10 "#extension GL_ARB_shading_language_420pack : require\n"\
11 "#extension GL_ARB_explicit_attrib_location : require\n"\
13 "layout(std140, binding=0) uniform ViewBounds\n"\
15 "\tfloat bounds_x;\n"\
16 "\tfloat bounds_y;\n"\
17 "\tfloat bounds_w;\n"\
18 "\tfloat bounds_h;\n"\
21 "layout(location = 0) in vec2 position;\n"\
25 "\tvec2 transformed_position;\n"\
26 "\ttransformed_position.x = (position.x - bounds_x) / bounds_w;\n"\
27 "\ttransformed_position.y = (position.y - bounds_y) / bounds_h;\n"\
28 "\t// Transform to clip coordinates (-1,1, -1,1).\n"\
29 "\tgl_Position.x = (transformed_position.x*2) - 1;\n"\
30 "\tgl_Position.y = 1 - (transformed_position.y*2);\n"\
31 "\tgl_Position.z = 0.0;\n"\
32 "\tgl_Position.w = 1.0;\n"\
38 "out vec4 output_colour;\n"\
40 "uniform vec4 colour;\n"\
44 "\toutput_colour = colour;\n"\
47 #define RECT_OUTLINE_GEOM \
50 "layout(lines) in;\n"\
51 "layout(line_strip, max_vertices = 5) out;\n"\
55 "\tgl_Position = gl_in[0].gl_Position;\n"\
57 "\tgl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0);\n"\
59 "\tgl_Position = gl_in[1].gl_Position;\n"\
61 "\tgl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0);\n"\
63 "\tgl_Position = gl_in[0].gl_Position;\n"\
65 "\tEndPrimitive();\n"\
68 #define RECT_FILLED_GEOM \
71 "layout(lines) in;\n"\
72 "layout(triangle_strip, max_vertices = 4) out;\n"\
76 "\tgl_Position = gl_in[0].gl_Position;\n"\
78 "\tgl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0);\n"\
80 "\tgl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0);\n"\
82 "\tgl_Position = gl_in[1].gl_Position;\n"\
84 "\tEndPrimitive();\n"\
87 void View::Translate(Real x, Real y)
93 Debug("View Bounds => %s", m_bounds.Str().c_str());
94 if (!m_use_gpu_transform)
96 m_buffer_dirty = true;
98 m_bounds_dirty = true;
101 void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt)
103 // x and y are coordinates in the window
104 // Convert to local coords.
110 //Debug("Mouse wheel event %f %f %f\n", Float(x), Float(y), Float(scaleAmt));
112 Real top = y - m_bounds.y;
113 Real left = x - m_bounds.x;
118 m_bounds.x = x - left;
119 m_bounds.y = y - top;
120 m_bounds.w *= scaleAmt;
121 m_bounds.h *= scaleAmt;
122 Debug("View Bounds => %s", m_bounds.Str().c_str());
123 if (!m_use_gpu_transform)
124 m_buffer_dirty = true;
125 m_bounds_dirty = true;
128 Rect View::TransformToViewCoords(const Rect& inp) const
131 out.x = (inp.x - m_bounds.x) / m_bounds.w;
132 out.y = (inp.y - m_bounds.y) / m_bounds.h;
134 out.w = inp.w / m_bounds.w;
135 out.h = inp.h / m_bounds.h;
139 void View::DrawGrid()
141 //TODO: Implement this with OpenGL 3.1+
143 // Draw some grid lines at fixed pixel positions
144 glMatrixMode(GL_PROJECTION);
146 glOrtho(0.0, 1.0, 1.0, 0.0, -1.f, 1.f);
147 glMatrixMode(GL_MODELVIEW);
150 glColor4f(0.9,0.9,0.9,0.1);
151 const float num_lines = 50.0;
152 for (float i = 0; i < num_lines; ++i)
155 glVertex2f(i*(1.0/num_lines), 0.0);
156 glVertex2f(i*(1.0/num_lines), 1.0);
159 glVertex2f(0.0,i*(1.0/num_lines));
160 glVertex2f(1.0,i*(1.0/num_lines));
167 void View::Render(int width, int height)
169 if (width != m_cached_display.GetWidth() || height != m_cached_display.GetHeight())
171 m_cached_display.Create(width, height);
172 m_bounds_dirty = true;
177 m_cached_display.UnBind();
178 m_cached_display.Blit();
181 m_cached_display.Bind();
182 m_cached_display.Clear();
184 if (!m_render_inited)
188 UpdateObjBoundsVBO();
192 if (m_use_gpu_transform)
194 GLfloat glbounds[] = {static_cast<GLfloat>(Float(m_bounds.x)), static_cast<GLfloat>(Float(m_bounds.y)), static_cast<GLfloat>(Float(m_bounds.w)), static_cast<GLfloat>(Float(m_bounds.h))};
195 m_bounds_ubo.Upload(sizeof(float)*4, glbounds);
199 GLfloat glbounds[] = {0.0f, 0.0f, 1.0f, 1.0f};
200 m_bounds_ubo.Upload(sizeof(float)*4, glbounds);
203 m_bounds_dirty = false;
205 if (m_colour.a < 1.0f)
208 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
210 m_objbounds_vbo.Bind();
212 glEnableVertexAttribArray(0);
213 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
216 m_rect_filled_shader.Use();
218 glDrawElements(GL_LINES, m_rendered_filled*2, GL_UNSIGNED_INT, 0);
220 // Rectangle Outlines
221 m_rect_outline_shader.Use();
222 m_outline_ibo.Bind();
223 glDrawElements(GL_LINES, m_rendered_outline*2, GL_UNSIGNED_INT, 0);
224 glDisableVertexAttribArray(0);
225 if (m_colour.a < 1.0f)
229 m_cached_display.UnBind();
230 m_cached_display.Blit();
240 void View::UpdateObjBoundsVBO()
242 m_objbounds_vbo.Invalidate();
243 m_objbounds_vbo.SetType(GraphicsBuffer::BufferTypeVertex);
244 if (m_use_gpu_transform)
246 m_objbounds_vbo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
250 m_objbounds_vbo.SetUsage(GraphicsBuffer::BufferUsageDynamicDraw);
252 m_objbounds_vbo.Resize(m_document.ObjectCount()*sizeof(GPUObjBounds));
254 BufferBuilder<GPUObjBounds> obj_bounds_builder(m_objbounds_vbo.Map(false, true, true), m_objbounds_vbo.GetSize());
256 for (unsigned id = 0; id < m_document.ObjectCount(); ++id)
259 if (m_use_gpu_transform)
261 obj_bounds = m_document.m_objects.bounds[id];
265 obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]);
267 GPUObjBounds gpu_bounds = {
268 (float)Float(obj_bounds.x),
269 (float)Float(obj_bounds.y),
270 (float)Float(obj_bounds.x + obj_bounds.w),
271 (float)Float(obj_bounds.y + obj_bounds.h)
273 obj_bounds_builder.Add(gpu_bounds);
276 m_objbounds_vbo.UnMap();
277 m_buffer_dirty = false;
280 void View::PrepareRender()
282 // TODO: Error check here.
283 m_rect_outline_shader.AttachGeometryProgram(RECT_OUTLINE_GEOM);
284 m_rect_outline_shader.AttachVertexProgram(RECT_VERT);
285 m_rect_outline_shader.AttachFragmentProgram(RECT_FRAG);
286 m_rect_outline_shader.Link();
287 m_rect_outline_shader.Use();
288 glUniform4f(m_rect_outline_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a);
290 m_rect_filled_shader.AttachGeometryProgram(RECT_FILLED_GEOM);
291 m_rect_filled_shader.AttachVertexProgram(RECT_VERT);
292 m_rect_filled_shader.AttachFragmentProgram(RECT_FRAG);
293 m_rect_filled_shader.Link();
294 m_rect_filled_shader.Use();
295 glUniform4f(m_rect_filled_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a);
297 m_bounds_ubo.SetType(GraphicsBuffer::BufferTypeUniform);
298 m_bounds_ubo.SetUsage(GraphicsBuffer::BufferUsageStreamDraw);
300 m_outline_ibo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
301 m_outline_ibo.SetType(GraphicsBuffer::BufferTypeIndex);
302 m_outline_ibo.Resize(m_document.ObjectCount() * 2 * sizeof(uint32_t));
303 BufferBuilder<uint32_t> outline_builder(m_outline_ibo.Map(false, true, true), m_outline_ibo.GetSize());
305 m_filled_ibo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
306 m_filled_ibo.SetType(GraphicsBuffer::BufferTypeIndex);
307 m_filled_ibo.Resize(m_document.ObjectCount() * 2 * sizeof(uint32_t));
308 BufferBuilder<uint32_t> filled_builder(m_filled_ibo.Map(false, true, true), m_filled_ibo.GetSize());
311 m_rendered_filled = m_rendered_outline = 0;
312 uint32_t currentIndex = 0;
313 for (unsigned id = 0; id < m_document.ObjectCount(); ++id)
315 if (m_document.m_objects.types[id] != RECT_FILLED)
317 outline_builder.Add(currentIndex++);
318 outline_builder.Add(currentIndex++);
319 m_rendered_outline++;
323 filled_builder.Add(currentIndex++);
324 filled_builder.Add(currentIndex++);
329 m_outline_ibo.UnMap();
330 m_filled_ibo.UnMap();
332 m_render_inited = true;