]> git.tdb.fi Git - libs/gl.git/commitdiff
Add an EnvironmentMap effect
authorMikko Rasa <tdb@tdb.fi>
Mon, 10 Sep 2012 21:35:23 +0000 (00:35 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 10 Sep 2012 21:35:23 +0000 (00:35 +0300)
source/environmentmap.cpp [new file with mode: 0644]
source/environmentmap.h [new file with mode: 0644]

diff --git a/source/environmentmap.cpp b/source/environmentmap.cpp
new file mode 100644 (file)
index 0000000..09a9b46
--- /dev/null
@@ -0,0 +1,99 @@
+#include <cmath>
+#include "environmentmap.h"
+#include "renderer.h"
+#include "texunit.h"
+
+namespace Msp {
+namespace GL {
+
+EnvironmentMap::EnvironmentMap(unsigned s, Renderable &r, Renderable &e):
+       Effect(r),
+       size(s),
+       environment(e),
+       rendered(false)
+{
+       env_tex.storage(RGB, size);
+       env_tex.set_wrap(CLAMP_TO_EDGE);
+       env_tex.set_min_filter(LINEAR);
+       depth_buf.storage(DEPTH_COMPONENT, size, size);
+       for(unsigned i=0; i<6; ++i)
+       {
+               fbo[i].attach(COLOR_ATTACHMENT0, env_tex, TextureCube::enumerate_faces(i), 0);
+               fbo[i].attach(DEPTH_ATTACHMENT, depth_buf);
+       }
+
+       // XXX Make the depth range configurable
+       camera.set_field_of_view(M_PI/2);
+       camera.set_aspect(1);
+       camera.set_depth_clip(0.1, 100);
+
+       shdata.uniform("environment", 4);
+}
+
+void EnvironmentMap::setup_frame() const
+{
+       if(rendered)
+               return;
+
+       rendered = true;
+       renderable.setup_frame();
+       environment.setup_frame();
+
+       const Matrix *matrix = renderable.get_matrix();
+       Vector3 position = (*matrix)*Vector3();
+       camera.set_position(position);
+       for(unsigned i=0; i<6; ++i)
+       {
+               TextureCubeFace face = TextureCube::enumerate_faces(i);
+               Bind _bind_fbo(fbo[i]);
+               fbo[i].clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT);
+               camera.set_look_direction(env_tex.get_face_direction(face));
+               camera.set_up_direction(env_tex.get_t_direction(face));
+               Renderer env_renderer(&camera);
+               env_renderer.exclude(renderable);
+               env_renderer.render(environment);
+       }
+}
+
+void EnvironmentMap::finish_frame() const
+{
+       if(rendered)
+       {
+               rendered = false;
+               renderable.finish_frame();
+               environment.finish_frame();
+       }
+}
+
+void EnvironmentMap::render(Renderer &renderer, const Tag &tag) const
+{
+       if(!enabled_passes.count(tag))
+               return renderer.render(renderable, tag);
+
+       const Matrix &view_matrix = renderer.get_camera()->get_matrix();
+       // XXX The camera should maybe have store its own object matrix
+       float env_mdata[9];
+       env_mdata[0] = view_matrix[0];
+       env_mdata[1] = view_matrix[4];
+       env_mdata[2] = view_matrix[8];
+       env_mdata[3] = view_matrix[1];
+       env_mdata[4] = view_matrix[5];
+       env_mdata[5] = view_matrix[9];
+       env_mdata[6] = view_matrix[2];
+       env_mdata[7] = view_matrix[6];
+       env_mdata[8] = view_matrix[10];
+       shdata.uniform_matrix3("env_eye_matrix", env_mdata);
+
+       env_tex.bind_to(4);
+       TexUnit::activate(0);
+
+       Renderer::Push _push_rend(renderer);
+       renderer.add_shader_data(shdata);
+       renderer.render(renderable, tag);
+
+       env_tex.unbind_from(4);
+       TexUnit::activate(0);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/environmentmap.h b/source/environmentmap.h
new file mode 100644 (file)
index 0000000..9c4c4d1
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef MSP_GL_ENVIRONMENTMAP_H_
+#define MSP_GL_ENVIRONMENTMAP_H_
+
+#include "camera.h"
+#include "effect.h"
+#include "framebuffer.h"
+#include "matrix.h"
+#include "programdata.h"
+#include "renderbuffer.h"
+#include "texturecube.h"
+#include "vector.h"
+
+namespace Msp {
+namespace GL {
+
+class Renderable;
+
+/**
+Creates a cube map texture of the surroundings of the renderable.  This texture
+can then be used to implement effects such as reflections or refractions.
+
+If the EnvironmentMap is used in a Pipeline, it's worth noting that the cube
+map will be prepared outside of any rendering pass.  It's recommended to use
+another Pipeline to define which passes should be used to render the
+environment.
+*/
+class EnvironmentMap: public Effect
+{
+private:
+       unsigned size;
+       Renderable &environment;
+       TextureCube env_tex;
+       Renderbuffer depth_buf;
+       mutable Framebuffer fbo[6];
+       mutable Camera camera;
+       mutable ProgramData shdata;
+       mutable bool rendered;
+
+public:
+       EnvironmentMap(unsigned size, Renderable &rend, Renderable &env);
+
+       virtual void setup_frame() const;
+       virtual void finish_frame() const;
+
+       virtual void render(Renderer &, const Tag &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif