]> git.tdb.fi Git - libs/gl.git/blob - source/renderpass.cpp
Make RenderPass use a Texturing for textures
[libs/gl.git] / source / renderpass.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/core/refptr.h>
9 #include <msp/datafile/collection.h>
10 #include <msp/strings/formatter.h>
11 #include "material.h"
12 #include "renderpass.h"
13 #include "program.h"
14 #include "programdata.h"
15 #include "texenv.h"
16 #include "texture.h"
17 #include "texture2d.h"
18 #include "texturing.h"
19
20 using namespace std;
21
22 namespace Msp {
23 namespace GL {
24
25 RenderPass::RenderPass():
26         shprog(0),
27         shdata(0),
28         material(0),
29         texturing(0)
30 { }
31
32 RenderPass::RenderPass(const RenderPass &other):
33         Bindable<RenderPass>(other),
34         shprog(other.shprog),
35         shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
36         material(other.material),
37         texturing(other.texturing ? new Texturing(*other.texturing) : 0)
38 { }
39
40 RenderPass::~RenderPass()
41 {
42         delete shdata;
43         delete texturing;
44 }
45
46 void RenderPass::set_material(const Material *mat)
47 {
48         material = mat;
49         material.keep();
50 }
51
52 void RenderPass::set_texture(unsigned index, const Texture *tex)
53 {
54         if(!texturing)
55                 texturing = new Texturing;
56
57         texturing->attach(index, *tex);
58 }
59
60 void RenderPass::bind() const
61 {
62         const RenderPass *old = current();
63         if(!set_current(this))
64                 return;
65
66         if(shprog)
67         {
68                 shprog->bind();
69                 shdata->apply();
70         }
71         else if(old && old->shprog)
72                 Program::unbind();
73
74         if(material)
75                 material->bind();
76         else if(old && old->material)
77                 Material::unbind();
78
79         if(texturing)
80                 texturing->bind();
81         else if(old && old->texturing)
82                 Texturing::unbind();
83 }
84
85 void RenderPass::unbind()
86 {
87         const RenderPass *old = current();
88         if(!set_current(0))
89                 return;
90
91         if(old->shprog)
92                 Program::unbind();
93
94         if(old->material)
95                 Material::unbind();
96
97         if(old->texturing)
98                 Texturing::unbind();
99 }
100
101
102 RenderPass::Loader::Loader(RenderPass &p):
103         DataFile::CollectionObjectLoader<RenderPass>(p, 0)
104 {
105         init();
106 }
107
108 RenderPass::Loader::Loader(RenderPass &p, Collection &c):
109         DataFile::CollectionObjectLoader<RenderPass>(p, &c)
110 {
111         init();
112 }
113
114 void RenderPass::Loader::init()
115 {
116         allow_pointer_reload = false;
117
118         add("shader",   &RenderPass::shprog);
119         add("material", static_cast<void (Loader::*)()>(&Loader::material));
120         add("material", static_cast<void (Loader::*)(const string &)>(&Loader::material));
121         add("texunit",  &Loader::texunit);
122         add("uniforms", &Loader::uniforms);
123 }
124
125 void RenderPass::Loader::finish()
126 {
127         // XXX Make shdata optional
128         if(obj.shprog && !obj.shdata)
129                 obj.shdata = new ProgramData;
130 }
131
132 void RenderPass::Loader::material()
133 {
134         RefPtr<Material> mat = new Material;
135         load_sub(*mat);
136         obj.material = mat;
137 }
138
139 void RenderPass::Loader::material(const string &name)
140 {
141         obj.material = get_collection().get<Material>(name);
142         obj.material.keep();
143 }
144
145 void RenderPass::Loader::texunit(unsigned i)
146 {
147         if(!obj.texturing)
148                 obj.texturing = new Texturing;
149         TextureLoader ldr(*obj.texturing, i, coll);
150         load_sub_with(ldr);
151 }
152
153 void RenderPass::Loader::uniforms()
154 {
155         if(!obj.shprog)
156                 throw InvalidState("Can't load uniforms without a shader program");
157         if(!obj.shdata)
158                 obj.shdata = new ProgramData;
159         load_sub(*obj.shdata, *obj.shprog);
160 }
161
162
163 RenderPass::TextureLoader::TextureLoader(Texturing &t, unsigned i, Collection *c):
164         DataFile::CollectionObjectLoader<Texturing>(t, c),
165         index(i)
166 {
167         add("texture",   &TextureLoader::texture);
168         add("texture2d", &TextureLoader::texture2d);
169 }
170
171 void RenderPass::TextureLoader::finish()
172 {
173         if(tex)
174         {
175                 if(env)
176                         obj.attach(index, *tex, *env);
177                 else
178                         obj.attach(index, *tex);
179                 tex.release();
180                 env.release();
181         }
182 }
183
184 void RenderPass::TextureLoader::texenv()
185 {
186         throw Exception("TexEnvs can't be loaded yet");
187         /*env = new TexEnv;
188         load_sub(*env);*/
189 }
190
191 void RenderPass::TextureLoader::texture(const string &name)
192 {
193         tex = get_collection().get<Texture>(name);
194         tex.keep();
195 }
196
197 void RenderPass::TextureLoader::texture2d()
198 {
199         tex = new Texture2D;
200         load_sub(static_cast<Texture2D &>(*tex));
201 }
202
203 } // namespace GL
204 } // namespace Msp