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 #define CIRCLE_FILLED_GEOM \
90 "layout(lines) in;\n"\
91 "layout(triangle_strip, max_vertices = 4) out;\n"\
92 "out vec2 objcoords;\n"\
96 "\tgl_Position = gl_in[0].gl_Position;\n"\
97 "\tobjcoords = vec2(-1.0, -1.0);\n"\
99 "\tgl_Position = vec4(gl_in[0].gl_Position.x, gl_in[1].gl_Position.y, 0.0, 1.0);\n"\
100 "\tobjcoords = vec2(-1.0, 1.0);\n"\
102 "\tgl_Position = vec4(gl_in[1].gl_Position.x, gl_in[0].gl_Position.y, 0.0, 1.0);\n"\
103 "\tobjcoords = vec2(1.0, -1.0);\n"\
105 "\tgl_Position = gl_in[1].gl_Position;\n"\
106 "\tobjcoords = vec2(1.0, 1.0);\n"\
108 "\tEndPrimitive();\n"\
111 #define CIRCLE_FRAG \
114 "in vec2 objcoords;\n"\
115 "out vec4 output_colour;\n"\
117 "uniform vec4 colour;\n"\
121 "\tif ((objcoords.x)*(objcoords.x) + (objcoords.y)*(objcoords.y) > 1.0)\n"\
125 "\toutput_colour = colour;\n"\
128 void View::Translate(Real x, Real y)
134 Debug("View Bounds => %s", m_bounds.Str().c_str());
135 if (!m_use_gpu_transform)
137 m_buffer_dirty = true;
139 m_bounds_dirty = true;
142 void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt)
144 // x and y are coordinates in the window
145 // Convert to local coords.
151 //Debug("Mouse wheel event %f %f %f\n", Float(x), Float(y), Float(scaleAmt));
153 Real top = y - m_bounds.y;
154 Real left = x - m_bounds.x;
159 m_bounds.x = x - left;
160 m_bounds.y = y - top;
161 m_bounds.w *= scaleAmt;
162 m_bounds.h *= scaleAmt;
163 Debug("View Bounds => %s", m_bounds.Str().c_str());
164 if (!m_use_gpu_transform)
165 m_buffer_dirty = true;
166 m_bounds_dirty = true;
169 Rect View::TransformToViewCoords(const Rect& inp) const
172 out.x = (inp.x - m_bounds.x) / m_bounds.w;
173 out.y = (inp.y - m_bounds.y) / m_bounds.h;
175 out.w = inp.w / m_bounds.w;
176 out.h = inp.h / m_bounds.h;
180 void View::DrawGrid()
182 //TODO: Implement this with OpenGL 3.1+
184 // Draw some grid lines at fixed pixel positions
185 glMatrixMode(GL_PROJECTION);
187 glOrtho(0.0, 1.0, 1.0, 0.0, -1.f, 1.f);
188 glMatrixMode(GL_MODELVIEW);
191 glColor4f(0.9,0.9,0.9,0.1);
192 const float num_lines = 50.0;
193 for (float i = 0; i < num_lines; ++i)
196 glVertex2f(i*(1.0/num_lines), 0.0);
197 glVertex2f(i*(1.0/num_lines), 1.0);
200 glVertex2f(0.0,i*(1.0/num_lines));
201 glVertex2f(1.0,i*(1.0/num_lines));
208 void View::Render(int width, int height)
210 if (width != m_cached_display.GetWidth() || height != m_cached_display.GetHeight())
212 m_cached_display.Create(width, height);
213 m_bounds_dirty = true;
218 m_cached_display.UnBind();
219 m_cached_display.Blit();
222 m_cached_display.Bind();
223 m_cached_display.Clear();
225 if (!m_render_inited)
229 UpdateObjBoundsVBO();
233 if (m_use_gpu_transform)
235 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))};
236 m_bounds_ubo.Upload(sizeof(float)*4, glbounds);
240 GLfloat glbounds[] = {0.0f, 0.0f, 1.0f, 1.0f};
241 m_bounds_ubo.Upload(sizeof(float)*4, glbounds);
244 m_bounds_dirty = false;
246 if (m_colour.a < 1.0f)
249 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
251 m_objbounds_vbo.Bind();
253 glEnableVertexAttribArray(0);
254 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
257 m_circle_filled_shader.Use();
259 glDrawElements(GL_LINES, m_rendered_circle*2, GL_UNSIGNED_INT, 0);
262 m_rect_filled_shader.Use();
264 glDrawElements(GL_LINES, m_rendered_filled*2, GL_UNSIGNED_INT, 0);
266 // Rectangle Outlines
267 m_rect_outline_shader.Use();
268 m_outline_ibo.Bind();
269 glDrawElements(GL_LINES, m_rendered_outline*2, GL_UNSIGNED_INT, 0);
271 glDisableVertexAttribArray(0);
272 if (m_colour.a < 1.0f)
276 m_cached_display.UnBind();
277 m_cached_display.Blit();
287 void View::UpdateObjBoundsVBO()
289 m_objbounds_vbo.Invalidate();
290 m_objbounds_vbo.SetType(GraphicsBuffer::BufferTypeVertex);
291 if (m_use_gpu_transform)
293 m_objbounds_vbo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
297 m_objbounds_vbo.SetUsage(GraphicsBuffer::BufferUsageDynamicDraw);
299 m_objbounds_vbo.Resize(m_document.ObjectCount()*sizeof(GPUObjBounds));
301 BufferBuilder<GPUObjBounds> obj_bounds_builder(m_objbounds_vbo.Map(false, true, true), m_objbounds_vbo.GetSize());
303 for (unsigned id = 0; id < m_document.ObjectCount(); ++id)
306 if (m_use_gpu_transform)
308 obj_bounds = m_document.m_objects.bounds[id];
312 obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]);
314 GPUObjBounds gpu_bounds = {
315 (float)Float(obj_bounds.x),
316 (float)Float(obj_bounds.y),
317 (float)Float(obj_bounds.x + obj_bounds.w),
318 (float)Float(obj_bounds.y + obj_bounds.h)
320 obj_bounds_builder.Add(gpu_bounds);
323 m_objbounds_vbo.UnMap();
324 m_buffer_dirty = false;
327 void View::PrepareRender()
329 // TODO: Error check here.
330 m_rect_outline_shader.AttachGeometryProgram(RECT_OUTLINE_GEOM);
331 m_rect_outline_shader.AttachVertexProgram(RECT_VERT);
332 m_rect_outline_shader.AttachFragmentProgram(RECT_FRAG);
333 m_rect_outline_shader.Link();
334 m_rect_outline_shader.Use();
335 glUniform4f(m_rect_outline_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a);
337 m_rect_filled_shader.AttachGeometryProgram(RECT_FILLED_GEOM);
338 m_rect_filled_shader.AttachVertexProgram(RECT_VERT);
339 m_rect_filled_shader.AttachFragmentProgram(RECT_FRAG);
340 m_rect_filled_shader.Link();
341 m_rect_filled_shader.Use();
342 glUniform4f(m_rect_filled_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a);
344 m_circle_filled_shader.AttachGeometryProgram(CIRCLE_FILLED_GEOM);
345 m_circle_filled_shader.AttachVertexProgram(RECT_VERT);
346 m_circle_filled_shader.AttachFragmentProgram(CIRCLE_FRAG);
347 m_circle_filled_shader.Link();
348 m_circle_filled_shader.Use();
349 glUniform4f(m_circle_filled_shader.GetUniformLocation("colour"), m_colour.r, m_colour.g, m_colour.b, m_colour.a);
351 m_bounds_ubo.SetType(GraphicsBuffer::BufferTypeUniform);
352 m_bounds_ubo.SetUsage(GraphicsBuffer::BufferUsageStreamDraw);
354 m_outline_ibo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
355 m_outline_ibo.SetType(GraphicsBuffer::BufferTypeIndex);
356 m_outline_ibo.Resize(m_document.ObjectCount() * 2 * sizeof(uint32_t));
357 BufferBuilder<uint32_t> outline_builder(m_outline_ibo.Map(false, true, true), m_outline_ibo.GetSize());
359 m_filled_ibo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
360 m_filled_ibo.SetType(GraphicsBuffer::BufferTypeIndex);
361 m_filled_ibo.Resize(m_document.ObjectCount() * 2 * sizeof(uint32_t));
362 BufferBuilder<uint32_t> filled_builder(m_filled_ibo.Map(false, true, true), m_filled_ibo.GetSize());
364 m_circle_ibo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
365 m_circle_ibo.SetType(GraphicsBuffer::BufferTypeIndex);
366 m_circle_ibo.Resize(m_document.ObjectCount() * 2 * sizeof(uint32_t));
367 BufferBuilder<uint32_t> circle_builder(m_circle_ibo.Map(false, true, true), m_circle_ibo.GetSize());
369 m_rendered_filled = m_rendered_outline = m_rendered_circle = 0;
370 uint32_t currentIndex = 0;
371 for (unsigned id = 0; id < m_document.ObjectCount(); ++id)
373 if (m_document.m_objects.types[id] == RECT_OUTLINE)
375 outline_builder.Add(currentIndex++);
376 outline_builder.Add(currentIndex++);
377 m_rendered_outline++;
379 else if (m_document.m_objects.types[id] == RECT_FILLED)
381 filled_builder.Add(currentIndex++);
382 filled_builder.Add(currentIndex++);
387 circle_builder.Add(currentIndex++);
388 circle_builder.Add(currentIndex++);
393 m_outline_ibo.UnMap();
394 m_filled_ibo.UnMap();
395 m_circle_ibo.UnMap();
397 m_render_inited = true;