]> git.tdb.fi Git - libs/gl.git/blob - source/renderer.cpp
Add a rendering supervisor class
[libs/gl.git] / source / renderer.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2011  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/core/except.h>
9 #include "batch.h"
10 #include "buffer.h"
11 #include "camera.h"
12 #include "material.h"
13 #include "program.h"
14 #include "programdata.h"
15 #include "renderer.h"
16 #include "texture.h"
17 #include "texturing.h"
18 #include "vertexarray.h"
19
20 using namespace std;
21
22 namespace Msp {
23 namespace GL {
24
25 Renderer::Renderer(const Camera *c):
26         mtx_changed(false),
27         camera(c),
28         state_stack(1),
29         state(&state_stack.back()),
30         vertex_array(0),
31         vertex_array_changed(false),
32         element_buffer(0)
33 {
34         MatrixStack::modelview().push();
35         if(camera)
36         {
37                 MatrixStack::projection().push();
38                 camera->apply();
39                 mtx_stack = camera->get_matrix();
40         }
41         else
42                 mtx_stack = MatrixStack::modelview().top();
43 }
44
45 Renderer::~Renderer()
46 {
47         if(camera)
48                 MatrixStack::projection().pop();
49         MatrixStack::modelview().pop();
50
51         Texturing::unbind();
52         Texture::unbind_from(0);
53         Material::unbind();
54         Program::unbind();
55         Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
56 }
57
58 MatrixStack &Renderer::matrix_stack()
59 {
60         mtx_changed = true;
61         return mtx_stack;
62 }
63
64 void Renderer::set_texture(const Texture *t)
65 {
66         state->texture = t;
67         state->texturing = 0;
68 }
69
70 void Renderer::set_texturing(const Texturing *t)
71 {
72         state->texturing = t;
73         state->texture = 0;
74 }
75
76 void Renderer::set_material(const Material *m)
77 {
78         state->material = m;
79 }
80
81 void Renderer::set_shader(const Program *p, const ProgramData *d)
82 {
83         state->shprog = p;
84         if(d)
85                 state->shdata.assign(1, d);
86         else
87                 state->shdata.clear();
88 }
89
90 void Renderer::add_shader_data(const ProgramData *d)
91 {
92         if(!state->shprog)
93                 throw InvalidState("No shader program");
94
95         state->shdata.push_back(d);
96 }
97
98 void Renderer::set_vertex_array(const VertexArray *a)
99 {
100         vertex_array_changed = (a!=vertex_array);
101         vertex_array = a;
102 }
103
104 void Renderer::set_element_buffer(const Buffer *b)
105 {
106         element_buffer = b;
107 }
108
109 void Renderer::push_state()
110 {
111         state_stack.push_back(state_stack.back());
112         state = &state_stack.back();
113         mtx_stack.push();
114 }
115
116 void Renderer::pop_state()
117 {
118         if(state_stack.size()==1)
119                 throw InvalidState("Can't pop the last state");
120
121         state_stack.pop_back();
122         state = &state_stack.back();
123         mtx_stack.pop();
124 }
125
126 void Renderer::escape()
127 {
128         apply_state();
129         Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
130 }
131
132 void Renderer::draw(const Batch &batch)
133 {
134         if(!vertex_array)
135                 throw InvalidState("Can't draw without a vertex array");
136
137         apply_state();
138
139         // Until VertexArray acquires VAO support and becomes Bindable
140         if(vertex_array_changed)
141                 vertex_array->apply();
142
143         if(element_buffer)
144                 element_buffer->bind_to(ELEMENT_ARRAY_BUFFER);
145         else
146                 Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
147
148         batch.draw();
149 }
150
151 void Renderer::apply_state()
152 {
153         // We let the objects themselves figure out if the binding has changed
154
155         if(state->texturing)
156                 state->texturing->bind();
157         else
158         {
159                 Texturing::unbind();
160                 if(state->texture)
161                         state->texture->bind_to(0);
162                 else
163                         Texture::unbind_from(0);
164         }
165
166         if(state->material)
167                 state->material->bind();
168         else
169                 Material::unbind();
170
171         if(state->shprog)
172         {
173                 state->shprog->bind();
174                 for(vector<const ProgramData *>::const_iterator i=state->shdata.begin(); i!=state->shdata.end(); ++i)
175                         (*i)->apply();
176         }
177         else
178                 Program::unbind();
179
180         if(mtx_changed)
181         {
182                 MatrixStack::modelview() = mtx_stack.top();
183                 mtx_changed = false;
184         }
185 }
186
187
188 Renderer::State::State():
189         texture(0),
190         texturing(0),
191         material(0),
192         shprog(0)
193 { }
194
195 } // namespace GL
196 } // namespace Msp