2 * @file objectrenderer.cpp
3 * @brief Implements ObjectRenderer and derived classes
6 #include "objectrenderer.h"
15 * ObjectRenderer constructor
16 * Note the ShaderProgram constructor which compiles the shaders for GPU rendering (if they exist)
18 ObjectRenderer::ObjectRenderer(const ObjectType & type,
19 const char * vert_glsl_file, const char * frag_glsl_file, const char * geom_glsl_file)
20 : m_type(type), m_shader_program(), m_indexes(), m_buffer_builder(NULL)
22 m_shader_program.InitialiseShaders(vert_glsl_file, frag_glsl_file, geom_glsl_file);
23 m_shader_program.Use();
24 glUniform4f(m_shader_program.GetUniformLocation("colour"), 0,0,0,1); //TODO: Allow different colours
30 void ObjectRenderer::RenderUsingGPU()
32 if (!m_shader_program.Valid())
33 Warn("Shader is invalid (objects are of type %d)", m_type);
34 m_shader_program.Use();
36 glDrawElements(GL_LINES, m_indexes.size()*2, GL_UNSIGNED_INT, 0);
40 * Helper structuretransforms coordinates to pixels
43 ObjectRenderer::CPURenderBounds::CPURenderBounds(const Rect & bounds, const View & view, const CPURenderTarget & target)
45 Rect view_bounds = view.TransformToViewCoords(bounds);
46 x = view_bounds.x * target.w;
47 y = view_bounds.y * target.h;
48 w = view_bounds.w * target.w;
49 h = view_bounds.h * target.h;
53 * Default implementation for rendering using CPU
55 void ObjectRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
57 Error("Cannot render objects of type %d on CPU", m_type);
61 * Prepare index buffers for both CPU and GPU rendering to receive indexes (but don't add any yet!)
63 void ObjectRenderer::PrepareBuffers(unsigned max_objects)
65 if (m_buffer_builder != NULL) // We already have a BufferBuilder
67 Fatal("Has been called before, without FinaliseBuffers being called since!");
69 // Empty and reserve the indexes vector (for CPU rendering)
71 m_indexes.reserve(max_objects); //TODO: Can probably make this smaller? Or leave it out? Do we care?
73 // Initialise and resize the ibo (for GPU rendering)
74 m_ibo.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
75 m_ibo.SetType(GraphicsBuffer::BufferTypeIndex);
76 m_ibo.Resize(max_objects * 2 * sizeof(uint32_t));
77 // BufferBuilder is used to construct the ibo
78 m_buffer_builder = new BufferBuilder<uint32_t>(m_ibo.Map(false, true, true), m_ibo.GetSize()); // new matches delete in ObjectRenderer::FinaliseBuffers
83 * Add object index to the buffers for CPU and GPU rendering
85 void ObjectRenderer::AddObjectToBuffers(unsigned index)
87 if (m_buffer_builder == NULL) // No BufferBuilder!
89 Fatal("Called without calling PrepareBuffers");
91 m_buffer_builder->Add(2*index); // ibo for GPU rendering
92 m_buffer_builder->Add(2*index+1);
93 m_indexes.push_back(index); // std::vector of indices for CPU rendering
97 * Finalise the index buffers for CPU and GPU rendering
99 void ObjectRenderer::FinaliseBuffers()
101 if (m_buffer_builder == NULL) // No BufferBuilder!
103 Fatal("Called without calling PrepareBuffers");
105 // For GPU rendering, UnMap the ibo
107 // ... and delete the BufferBuilder used to create it
108 delete m_buffer_builder; // delete matches new in ObjectRenderer::PrepareBuffers
109 m_buffer_builder = NULL;
111 // Nothing is necessary for CPU rendering
118 void RectFilledRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
120 for (unsigned i = 0; i < m_indexes.size(); ++i)
122 CPURenderBounds bounds(objects.bounds[m_indexes[i]], view, target);
123 for (int x = max(0, bounds.x); x < min(bounds.x+bounds.w, target.w); ++x)
125 for (int y = max(0, bounds.y); y < min(bounds.y+bounds.h, target.h); ++y)
127 int index = (x+target.w*y)*4;
128 target.pixels[index+0] = 0;
129 target.pixels[index+1] = 0;
130 target.pixels[index+2] = 0;
131 target.pixels[index+3] = 255;
140 void RectOutlineRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
142 for (unsigned i = 0; i < m_indexes.size(); ++i)
144 CPURenderBounds bounds(objects.bounds[m_indexes[i]], view, target);
145 for (int x = max(0, bounds.x); x < min(bounds.x+bounds.w, target.w); ++x)
147 int top = (x+target.w*max(0, bounds.y))*4;
148 int bottom = (x+target.w*min(bounds.y+bounds.h, target.h))*4;
149 for (int j = 0; j < 3; ++j)
151 target.pixels[top+j] = 0;
152 target.pixels[bottom+j] = 0;
154 target.pixels[top+3] = 255;
155 target.pixels[bottom+3] = 255;
158 for (int y = max(0, bounds.y); y < min(bounds.y+bounds.h, target.h); ++y)
160 int left = (max(0, bounds.x)+target.w*y)*4;
161 int right = (min(bounds.x+bounds.w, target.w)+target.w*y)*4;
162 for (int j = 0; j < 3; ++j)
164 target.pixels[left+j] = 0;
165 target.pixels[right+j] = 0;
167 target.pixels[left+3] = 255;
168 target.pixels[right+3] = 255;
177 void CircleFilledRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
179 for (unsigned i = 0; i < m_indexes.size(); ++i)
181 CPURenderBounds bounds(objects.bounds[m_indexes[i]], view, target);
182 int centre_x = bounds.x + bounds.w / 2;
183 int centre_y = bounds.y + bounds.h / 2;
185 Debug("Centre is %d, %d", centre_x, centre_y);
186 Debug("Bounds are %d,%d,%d,%d", bounds.x, bounds.y, bounds.w, bounds.h);
187 Debug("Windos is %d,%d", target.w, target.h);
188 for (int x = max(0, bounds.x); x < min(bounds.x+bounds.w, target.w); ++x)
190 for (int y = max(0, bounds.y); y < min(bounds.y + bounds.h, target.h); ++y)
192 double dx = 2.0*(double)(x - centre_x)/(double)(bounds.w);
193 double dy = 2.0*(double)(y - centre_y)/(double)(bounds.h);
194 int index = (x+target.w*y)*4;
196 if (dx*dx + dy*dy <= 1.0)
198 target.pixels[index+0] = 0;
199 target.pixels[index+1] = 0;
200 target.pixels[index+2] = 0;
201 target.pixels[index+3] = 255;
211 * For debug, save pixels to bitmap
213 void ObjectRenderer::SaveBMP(const CPURenderTarget & target, const char * filename)
215 SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(target.pixels, target.w, target.h, 8*4, target.w*4,
216 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
217 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
219 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
220 #endif //SDL_BYTEORDER
223 Fatal("SDL_CreateRGBSurfaceFrom(pixels...) failed - %s", SDL_GetError());
224 if (SDL_SaveBMP(surf, filename) != 0)
225 Fatal("SDL_SaveBMP failed - %s", SDL_GetError());
228 SDL_FreeSurface(surf);