2014-01-24 18:13:50 +01:00
|
|
|
#include "graphics/pipeline.h"
|
|
|
|
#include <Windows.h>
|
2014-03-12 23:00:16 +01:00
|
|
|
#include <gl/GL.h>
|
|
|
|
#include <gl/GLU.h>
|
2014-01-24 18:13:50 +01:00
|
|
|
#include "core/array.h"
|
|
|
|
#include "core/crc32.h"
|
|
|
|
#include "core/file_system.h"
|
|
|
|
#include "core/iserializer.h"
|
|
|
|
#include "core/json_serializer.h"
|
2014-03-16 12:29:34 +01:00
|
|
|
#include "core/resource_manager.h"
|
|
|
|
#include "core/resource_manager_base.h"
|
2014-01-24 18:13:50 +01:00
|
|
|
#include "core/string.h"
|
2014-02-22 13:31:16 +01:00
|
|
|
#include "engine/engine.h"
|
2014-03-12 23:00:16 +01:00
|
|
|
#include "graphics/frame_buffer.h"
|
2014-01-25 14:56:39 +01:00
|
|
|
#include "graphics/geometry.h"
|
2014-03-12 23:00:16 +01:00
|
|
|
#include "graphics/gl_ext.h"
|
2014-01-25 14:56:39 +01:00
|
|
|
#include "graphics/material.h"
|
|
|
|
#include "graphics/model.h"
|
|
|
|
#include "graphics/model_instance.h"
|
|
|
|
#include "graphics/renderer.h"
|
2014-02-22 13:31:16 +01:00
|
|
|
#include "graphics/shader.h"
|
2014-01-24 18:13:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
namespace Lux
|
|
|
|
{
|
|
|
|
|
2014-03-14 22:45:39 +01:00
|
|
|
struct PipelineImpl;
|
2014-03-30 11:11:50 +02:00
|
|
|
struct PipelineInstanceImpl;
|
2014-03-14 22:45:39 +01:00
|
|
|
|
2014-01-24 18:13:50 +01:00
|
|
|
struct Command
|
|
|
|
{
|
2014-03-14 22:45:39 +01:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) = 0;
|
2014-03-30 11:11:50 +02:00
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) = 0;
|
2014-03-14 22:45:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct ClearCommand : public Command
|
|
|
|
{
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) override;
|
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-03-14 22:45:39 +01:00
|
|
|
uint32_t m_buffers;
|
|
|
|
};
|
|
|
|
|
2014-01-24 18:13:50 +01:00
|
|
|
|
2014-03-14 22:45:39 +01:00
|
|
|
struct RenderModelsCommand : public Command
|
|
|
|
{
|
2014-04-04 01:03:15 +02:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) override;
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-04-04 01:03:15 +02:00
|
|
|
|
|
|
|
int64_t m_layer_mask;
|
2014-03-14 22:45:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct ApplyCameraCommand : public Command
|
|
|
|
{
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) override;
|
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-03-14 22:45:39 +01:00
|
|
|
uint32_t m_camera_idx;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct BindFramebufferCommand : public Command
|
|
|
|
{
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) override;
|
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-03-14 22:45:39 +01:00
|
|
|
uint32_t m_buffer_index;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct UnbindFramebufferCommand : public Command
|
|
|
|
{
|
2014-04-09 23:59:39 +02:00
|
|
|
virtual void deserialize(PipelineImpl&, ISerializer&) override {}
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-03-14 22:45:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct DrawFullscreenQuadCommand : public Command
|
|
|
|
{
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) override;
|
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-03-12 23:00:16 +01:00
|
|
|
Material* m_material;
|
2014-01-24 18:13:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-03-14 22:45:39 +01:00
|
|
|
struct BindFramebufferTextureCommand : public Command
|
|
|
|
{
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) override;
|
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-03-14 22:45:39 +01:00
|
|
|
uint32_t m_framebuffer_index;
|
|
|
|
uint32_t m_renderbuffer_index;
|
|
|
|
uint32_t m_texture_uint;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct RenderShadowmapCommand : public Command
|
|
|
|
{
|
2014-04-04 01:03:15 +02:00
|
|
|
virtual void deserialize(PipelineImpl& pipeline, ISerializer& serializer) override;
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-04-04 01:03:15 +02:00
|
|
|
|
|
|
|
int64_t m_layer_mask;
|
2014-03-14 22:45:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct BindShadowmapCommand : public Command
|
|
|
|
{
|
2014-04-09 23:59:39 +02:00
|
|
|
virtual void deserialize(PipelineImpl&, ISerializer&) override {}
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void execute(PipelineInstanceImpl& pipeline) override;
|
2014-03-14 22:45:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-24 18:13:50 +01:00
|
|
|
struct PipelineImpl : public Pipeline
|
|
|
|
{
|
2014-03-30 11:11:50 +02:00
|
|
|
struct FrameBufferDeclaration
|
|
|
|
{
|
|
|
|
int32_t m_width;
|
|
|
|
int32_t m_height;
|
|
|
|
int32_t m_mask;
|
|
|
|
};
|
|
|
|
|
2014-03-14 22:45:39 +01:00
|
|
|
struct CommandCreator
|
|
|
|
{
|
|
|
|
typedef Delegate<Command*> Creator;
|
|
|
|
Creator m_creator;
|
|
|
|
uint32_t m_type_hash;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static Command* CreateCommand()
|
|
|
|
{
|
|
|
|
return LUX_NEW(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-05 22:54:29 +02:00
|
|
|
PipelineImpl(const Path& path, ResourceManager& resource_manager)
|
|
|
|
: Pipeline(path, resource_manager)
|
2014-01-25 14:56:39 +01:00
|
|
|
{
|
2014-03-14 22:45:39 +01:00
|
|
|
addCommandCreator("clear").bind<&CreateCommand<ClearCommand> >();
|
|
|
|
addCommandCreator("render_models").bind<&CreateCommand<RenderModelsCommand> >();
|
|
|
|
addCommandCreator("apply_camera").bind<&CreateCommand<ApplyCameraCommand> >();
|
|
|
|
addCommandCreator("bind_framebuffer").bind<&CreateCommand<BindFramebufferCommand> >();
|
|
|
|
addCommandCreator("unbind_framebuffer").bind<&CreateCommand<UnbindFramebufferCommand> >();
|
|
|
|
addCommandCreator("draw_fullscreen_quad").bind<&CreateCommand<DrawFullscreenQuadCommand> >();
|
|
|
|
addCommandCreator("bind_framebuffer_texture").bind<&CreateCommand<BindFramebufferTextureCommand> >();
|
|
|
|
addCommandCreator("render_shadowmap").bind<&CreateCommand<RenderShadowmapCommand> >();
|
|
|
|
addCommandCreator("bind_shadowmap").bind<&CreateCommand<BindShadowmapCommand> >();
|
2014-01-25 14:56:39 +01:00
|
|
|
}
|
|
|
|
|
2014-02-07 23:07:42 +01:00
|
|
|
|
2014-03-12 23:00:16 +01:00
|
|
|
~PipelineImpl()
|
|
|
|
{
|
2014-03-14 22:45:39 +01:00
|
|
|
for (int i = 0; i < m_commands.size(); ++i)
|
|
|
|
{
|
|
|
|
LUX_DELETE(m_commands[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-07 21:18:16 +02:00
|
|
|
virtual void doUnload(void) override
|
2014-04-05 22:54:29 +02:00
|
|
|
{
|
2014-04-07 21:36:24 +02:00
|
|
|
for (int i = 0; i < m_commands.size(); ++i)
|
|
|
|
{
|
|
|
|
LUX_DELETE(m_commands[i]);
|
|
|
|
}
|
|
|
|
m_commands.clear();
|
|
|
|
onEmpty();
|
2014-03-12 23:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-07 21:18:16 +02:00
|
|
|
virtual FS::ReadCallback getReadCallback() override
|
2014-03-12 23:00:16 +01:00
|
|
|
{
|
2014-04-07 21:18:16 +02:00
|
|
|
FS::ReadCallback cb;
|
|
|
|
cb.bind<PipelineImpl, &PipelineImpl::loaded>(this);
|
|
|
|
return cb;
|
2014-03-12 23:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-07 21:18:16 +02:00
|
|
|
CommandCreator::Creator& addCommandCreator(const char* type)
|
2014-01-24 18:13:50 +01:00
|
|
|
{
|
2014-04-07 21:18:16 +02:00
|
|
|
CommandCreator& creator = m_command_creators.pushEmpty();
|
|
|
|
creator.m_type_hash = crc32(type);
|
|
|
|
return creator.m_creator;
|
2014-03-14 22:45:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Command* createCommand(uint32_t type_hash)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_command_creators.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_command_creators[i].m_type_hash == type_hash)
|
|
|
|
{
|
|
|
|
return m_command_creators[i].m_creator.invoke();
|
|
|
|
}
|
2014-01-24 18:13:50 +01:00
|
|
|
}
|
2014-03-14 22:45:39 +01:00
|
|
|
return NULL;
|
2014-01-24 18:13:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual bool deserialize(ISerializer& serializer) override
|
2014-01-24 18:13:50 +01:00
|
|
|
{
|
|
|
|
int32_t count;
|
2014-03-12 23:00:16 +01:00
|
|
|
serializer.deserialize("frame_buffer_count", count);
|
|
|
|
serializer.deserializeArrayBegin("frame_buffers");
|
|
|
|
m_framebuffers.resize(count);
|
|
|
|
for(int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
int32_t render_buffer_count;
|
|
|
|
serializer.deserializeArrayItem(render_buffer_count);
|
|
|
|
int mask = 0;
|
|
|
|
char rb_name[30];
|
|
|
|
for(int j = 0; j < render_buffer_count; ++j)
|
|
|
|
{
|
|
|
|
serializer.deserializeArrayItem(rb_name, 30);
|
|
|
|
if(strcmp(rb_name, "depth") == 0)
|
|
|
|
{
|
|
|
|
mask |= FrameBuffer::DEPTH_BIT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ASSERT(false);
|
|
|
|
}
|
|
|
|
}
|
2014-03-30 11:11:50 +02:00
|
|
|
serializer.deserializeArrayItem(m_framebuffers[i].m_width);
|
|
|
|
serializer.deserializeArrayItem(m_framebuffers[i].m_height);
|
|
|
|
m_framebuffers[i].m_mask = mask;
|
2014-03-12 23:00:16 +01:00
|
|
|
}
|
2014-03-14 22:45:39 +01:00
|
|
|
serializer.deserializeArrayEnd();
|
2014-03-30 11:11:50 +02:00
|
|
|
serializer.deserialize("shadowmap_width", m_shadowmap_framebuffer.m_width);
|
|
|
|
serializer.deserialize("shadowmap_height", m_shadowmap_framebuffer.m_height);
|
|
|
|
m_shadowmap_framebuffer.m_mask = FrameBuffer::DEPTH_BIT;
|
|
|
|
|
2014-01-24 18:13:50 +01:00
|
|
|
serializer.deserialize("command_count", count);
|
|
|
|
serializer.deserializeArrayBegin("commands");
|
|
|
|
for(int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
char tmp[255];
|
|
|
|
serializer.deserializeArrayItem(tmp, 255);
|
2014-03-14 22:45:39 +01:00
|
|
|
uint32_t command_type_hash = crc32(tmp);
|
|
|
|
Command* cmd = createCommand(command_type_hash);
|
|
|
|
cmd->deserialize(*this, serializer);
|
|
|
|
m_commands.push(cmd);
|
2014-01-24 18:13:50 +01:00
|
|
|
}
|
|
|
|
serializer.deserializeArrayEnd();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-04 22:23:53 +01:00
|
|
|
void loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
2014-01-24 18:13:50 +01:00
|
|
|
{
|
|
|
|
if(success)
|
|
|
|
{
|
|
|
|
JsonSerializer serializer(*file, JsonSerializer::READ);
|
|
|
|
deserialize(serializer);
|
2014-04-07 21:36:24 +02:00
|
|
|
onReady();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
onFailure();
|
2014-01-24 18:13:50 +01:00
|
|
|
}
|
2014-03-04 22:23:53 +01:00
|
|
|
|
|
|
|
fs.close(file);
|
2014-03-30 11:36:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
Array<Command*> m_commands;
|
|
|
|
Array<CommandCreator> m_command_creators;
|
|
|
|
Array<FrameBufferDeclaration> m_framebuffers;
|
|
|
|
FrameBufferDeclaration m_shadowmap_framebuffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct PipelineInstanceImpl : public PipelineInstance
|
|
|
|
{
|
|
|
|
PipelineInstanceImpl(Pipeline& pipeline)
|
|
|
|
: m_source(static_cast<PipelineImpl&>(pipeline))
|
|
|
|
{
|
2014-03-30 11:36:36 +02:00
|
|
|
m_shadowmap_framebuffer = NULL;
|
|
|
|
if(pipeline.isReady())
|
|
|
|
{
|
2014-04-07 21:36:24 +02:00
|
|
|
sourceLoaded(Resource::State::READY);
|
2014-03-30 11:36:36 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-07 21:36:24 +02:00
|
|
|
pipeline.getObserverCb().bind<PipelineInstanceImpl, &PipelineInstanceImpl::sourceLoaded>(this);
|
2014-03-30 11:36:36 +02:00
|
|
|
}
|
2014-03-30 11:11:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
~PipelineInstanceImpl()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_framebuffers.size(); ++i)
|
|
|
|
{
|
|
|
|
LUX_DELETE(m_framebuffers[i]);
|
|
|
|
}
|
|
|
|
if (m_shadowmap_framebuffer)
|
|
|
|
{
|
|
|
|
LUX_DELETE(m_shadowmap_framebuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-07 21:18:16 +02:00
|
|
|
void setRenderer(Renderer& renderer)
|
|
|
|
{
|
|
|
|
m_renderer = &renderer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:39:16 +02:00
|
|
|
void sourceLoaded(Resource::State status)
|
2014-03-30 11:11:50 +02:00
|
|
|
{
|
2014-04-07 21:36:24 +02:00
|
|
|
if (status == Resource::State::READY)
|
2014-03-30 11:11:50 +02:00
|
|
|
{
|
2014-04-07 21:36:24 +02:00
|
|
|
PipelineImpl::FrameBufferDeclaration fb = m_source.m_shadowmap_framebuffer;
|
|
|
|
m_shadowmap_framebuffer = LUX_NEW(FrameBuffer)(fb.m_width, fb.m_height, fb.m_mask);
|
|
|
|
m_framebuffers.reserve(m_source.m_framebuffers.size());
|
|
|
|
for (int i = 0; i < m_source.m_framebuffers.size(); ++i)
|
|
|
|
{
|
|
|
|
fb = m_source.m_framebuffers[i];
|
|
|
|
m_framebuffers.push(LUX_NEW(FrameBuffer)(fb.m_width, fb.m_height, fb.m_mask));
|
|
|
|
}
|
2014-03-30 11:11:50 +02:00
|
|
|
}
|
2014-01-24 18:13:50 +01:00
|
|
|
}
|
|
|
|
|
2014-03-12 23:00:16 +01:00
|
|
|
|
|
|
|
void getOrthoMatrix(float left, float right, float bottom, float top, float z_near, float z_far, Matrix* mtx)
|
|
|
|
{
|
|
|
|
*mtx = Matrix::IDENTITY;
|
|
|
|
mtx->m11 = 2 / (right - left);
|
|
|
|
mtx->m22 = 2 / (top - bottom);
|
|
|
|
mtx->m33 = -2 / (z_far - z_near);
|
|
|
|
mtx->m41 = -(right + left) / (right - left);
|
|
|
|
mtx->m42 = -(top + bottom) / (top - bottom);
|
|
|
|
mtx->m43 = -(z_far + z_near) / (z_far - z_near);
|
2014-03-30 11:11:50 +02:00
|
|
|
/* glOrtho(left, right, bottom, top, z_near, z_far);
|
2014-03-12 23:00:16 +01:00
|
|
|
glGetFloatv(GL_PROJECTION_MATRIX, &mtx->m11);
|
2014-03-30 11:11:50 +02:00
|
|
|
*/
|
2014-03-12 23:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void getLookAtMatrix(const Vec3& pos, const Vec3& center, const Vec3& up, Matrix* mtx)
|
|
|
|
{
|
|
|
|
*mtx = Matrix::IDENTITY;
|
|
|
|
Vec3 f = center - pos;
|
|
|
|
f.normalize();
|
|
|
|
Vec3 r = crossProduct(f, up);
|
|
|
|
r.normalize();
|
|
|
|
Vec3 u = crossProduct(r, f);
|
|
|
|
mtx->setXVector(r);
|
|
|
|
mtx->setYVector(u);
|
|
|
|
mtx->setZVector(-f);
|
2014-03-27 23:43:55 +01:00
|
|
|
mtx->transpose();
|
|
|
|
mtx->setTranslation(Vec3(-dotProduct(r, pos), -dotProduct(u, pos), dotProduct(f, pos)));
|
|
|
|
/*glPushMatrix();
|
|
|
|
float m[16];
|
|
|
|
gluLookAt(pos.x, pos.y, pos.z, center.x, center.y, center.z, up.x, up.y, up.z);
|
|
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, m);
|
|
|
|
glPopMatrix();*/
|
2014-03-12 23:00:16 +01:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:03:15 +02:00
|
|
|
void renderShadowmap(int64_t layer_mask)
|
2014-03-12 23:00:16 +01:00
|
|
|
{
|
2014-04-06 16:59:18 +02:00
|
|
|
ASSERT(m_renderer != NULL);
|
2014-04-09 23:39:16 +02:00
|
|
|
glViewport(0, 0, m_shadowmap_framebuffer->getWidth(), m_shadowmap_framebuffer->getHeight());
|
2014-04-07 21:18:16 +02:00
|
|
|
Component light_cmp = m_renderer->getLight(0);
|
2014-03-16 13:11:23 +01:00
|
|
|
if (!light_cmp.isValid())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2014-03-12 23:00:16 +01:00
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
m_shadowmap_framebuffer->bind();
|
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
Matrix projection_matrix;
|
|
|
|
getOrthoMatrix(-10, 10, -10, 10, 0, 100, &projection_matrix);
|
|
|
|
glMultMatrixf(&projection_matrix.m11);
|
2014-03-30 11:11:50 +02:00
|
|
|
|
2014-03-12 23:00:16 +01:00
|
|
|
Matrix mtx = light_cmp.entity.getMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
Matrix modelview_matrix;
|
|
|
|
getLookAtMatrix(mtx.getTranslation(), mtx.getTranslation() + mtx.getZVector(), mtx.getYVector(), &modelview_matrix);
|
|
|
|
glMultMatrixf(&modelview_matrix.m11);
|
|
|
|
static const Matrix biasMatrix(
|
|
|
|
0.5, 0.0, 0.0, 0.0,
|
|
|
|
0.0, 0.5, 0.0, 0.0,
|
|
|
|
0.0, 0.0, 0.5, 0.0,
|
|
|
|
0.5, 0.5, 0.5, 1.0
|
2014-03-30 11:11:50 +02:00
|
|
|
);
|
2014-03-12 23:00:16 +01:00
|
|
|
m_shadow_modelviewprojection = biasMatrix * (projection_matrix * modelview_matrix);
|
|
|
|
|
2014-04-04 01:03:15 +02:00
|
|
|
renderModels(layer_mask);
|
2014-03-12 23:00:16 +01:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
FrameBuffer::unbind();
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void drawFullscreenQuad(Material* material)
|
|
|
|
{
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
2014-03-30 11:11:50 +02:00
|
|
|
glOrtho(-1, 1, -1, 1, 0, 30);
|
2014-03-12 23:00:16 +01:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
|
2014-04-07 21:18:16 +02:00
|
|
|
ASSERT(m_renderer != NULL);
|
|
|
|
material->apply(*m_renderer);
|
2014-03-12 23:00:16 +01:00
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glBegin(GL_QUADS);
|
2014-03-30 11:11:50 +02:00
|
|
|
glTexCoord2f(0, 0);
|
|
|
|
glVertex3f(-1, -1, -1);
|
|
|
|
glTexCoord2f(0, 1);
|
|
|
|
glVertex3f(-1, 1, -1);
|
|
|
|
glTexCoord2f(1, 1);
|
|
|
|
glVertex3f(1, 1, -1);
|
|
|
|
glTexCoord2f(1, 0);
|
|
|
|
glVertex3f(1, -1, -1);
|
2014-03-12 23:00:16 +01:00
|
|
|
glEnd();
|
|
|
|
glPopMatrix();
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-04 01:03:15 +02:00
|
|
|
void renderModels(int64_t layer_mask)
|
2014-01-25 14:56:39 +01:00
|
|
|
{
|
2014-04-06 16:59:18 +02:00
|
|
|
ASSERT(m_renderer != NULL);
|
2014-03-16 14:33:45 +01:00
|
|
|
static Array<RenderableInfo> infos;
|
2014-01-25 14:56:39 +01:00
|
|
|
infos.clear();
|
2014-04-07 21:18:16 +02:00
|
|
|
m_renderer->getRenderableInfos(infos, layer_mask);
|
2014-01-25 14:56:39 +01:00
|
|
|
int count = infos.size();
|
2014-03-30 11:11:50 +02:00
|
|
|
for (int i = 0; i < count; ++i)
|
2014-01-25 14:56:39 +01:00
|
|
|
{
|
2014-02-25 23:05:13 +01:00
|
|
|
glPushMatrix();
|
2014-02-22 13:31:16 +01:00
|
|
|
Model& model = infos[i].m_model_instance->getModel();
|
2014-04-03 23:59:36 +02:00
|
|
|
Matrix mtx = infos[i].m_model_instance->getMatrix();
|
|
|
|
mtx.multiply3x3(infos[i].m_scale);
|
|
|
|
glMultMatrixf(&mtx.m11);
|
2014-02-22 13:31:16 +01:00
|
|
|
Geometry* geom = model.getGeometry();
|
2014-03-30 11:11:50 +02:00
|
|
|
for (int j = 0; j < model.getMeshCount(); ++j)
|
2014-01-25 14:56:39 +01:00
|
|
|
{
|
2014-02-22 13:31:16 +01:00
|
|
|
Mesh& mesh = model.getMesh(j);
|
2014-03-30 11:11:50 +02:00
|
|
|
if (mesh.getMaterial()->isReady())
|
2014-02-09 23:43:10 +01:00
|
|
|
{
|
2014-04-07 21:18:16 +02:00
|
|
|
mesh.getMaterial()->apply(*m_renderer);
|
2014-03-12 23:00:16 +01:00
|
|
|
|
2014-02-22 13:31:16 +01:00
|
|
|
static Matrix bone_mtx[64];
|
|
|
|
Pose& pose = infos[i].m_model_instance->getPose();
|
|
|
|
Vec3* poss = pose.getPositions();
|
|
|
|
Quat* rots = pose.getRotations();
|
2014-03-30 11:11:50 +02:00
|
|
|
for (int bone_index = 0, bone_count = pose.getCount(); bone_index < bone_count; ++bone_index)
|
2014-02-22 13:31:16 +01:00
|
|
|
{
|
|
|
|
rots[bone_index].toMatrix(bone_mtx[bone_index]);
|
|
|
|
bone_mtx[bone_index].translate(poss[bone_index]);
|
|
|
|
bone_mtx[bone_index] = bone_mtx[bone_index] * model.getBone(bone_index).inv_bind_matrix;
|
|
|
|
}
|
|
|
|
mesh.getMaterial()->getShader()->setUniform("bone_matrices", bone_mtx, pose.getCount());
|
2014-03-12 23:00:16 +01:00
|
|
|
mesh.getMaterial()->getShader()->setUniform("shadowmap", 1);
|
|
|
|
mesh.getMaterial()->getShader()->setUniform("shadowmap_matrix", m_shadow_modelviewprojection);
|
|
|
|
mesh.getMaterial()->getShader()->setUniform("world_matrix", infos[i].m_model_instance->getMatrix());
|
2014-02-09 23:43:10 +01:00
|
|
|
geom->draw(mesh.getStart(), mesh.getCount(), *mesh.getMaterial()->getShader());
|
|
|
|
}
|
2014-01-25 14:56:39 +01:00
|
|
|
}
|
2014-02-25 23:05:13 +01:00
|
|
|
glPopMatrix();
|
2014-01-25 14:56:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual int getCameraCount() const override
|
2014-03-30 11:11:50 +02:00
|
|
|
{
|
|
|
|
return m_cameras.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void resize(int w, int h) override
|
2014-03-30 11:11:50 +02:00
|
|
|
{
|
2014-04-07 21:18:16 +02:00
|
|
|
ASSERT(m_renderer != NULL);
|
2014-03-30 11:11:50 +02:00
|
|
|
for (int i = 0; i < m_cameras.size(); ++i)
|
|
|
|
{
|
2014-04-07 21:18:16 +02:00
|
|
|
m_renderer->setCameraSize(m_cameras[i], w, h);
|
2014-03-30 11:11:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void setCamera(int index, const Component& camera) override
|
2014-03-30 11:11:50 +02:00
|
|
|
{
|
|
|
|
if (m_cameras.size() <= index)
|
|
|
|
{
|
|
|
|
m_cameras.resize(index + 1);
|
|
|
|
}
|
|
|
|
m_cameras[index] = camera;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual const Component& getCamera(int index) override
|
2014-03-30 11:11:50 +02:00
|
|
|
{
|
|
|
|
return m_cameras[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-03 23:59:36 +02:00
|
|
|
virtual void render() override
|
2014-03-30 11:11:50 +02:00
|
|
|
{
|
|
|
|
for (int i = 0; i < m_source.m_commands.size(); ++i)
|
|
|
|
{
|
|
|
|
m_source.m_commands[i]->execute(*this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PipelineImpl& m_source;
|
2014-03-16 14:33:45 +01:00
|
|
|
Array<FrameBuffer*> m_framebuffers;
|
2014-03-12 23:00:16 +01:00
|
|
|
FrameBuffer* m_shadowmap_framebuffer;
|
|
|
|
Matrix m_shadow_modelviewprojection;
|
2014-03-30 11:11:50 +02:00
|
|
|
Array<Component> m_cameras;
|
2014-04-07 21:18:16 +02:00
|
|
|
Renderer* m_renderer;
|
2014-04-09 23:59:39 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
void operator=(const PipelineInstanceImpl&);
|
2014-01-24 18:13:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-04-05 22:54:29 +02:00
|
|
|
Pipeline::Pipeline(const Path& path, ResourceManager& resource_manager)
|
|
|
|
: Resource(path, resource_manager)
|
2014-01-24 18:13:50 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-07 21:18:16 +02:00
|
|
|
PipelineInstance* PipelineInstance::create(Pipeline& pipeline)
|
|
|
|
{
|
|
|
|
return LUX_NEW(PipelineInstanceImpl)(pipeline);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PipelineInstance::destroy(PipelineInstance* pipeline)
|
|
|
|
{
|
|
|
|
LUX_DELETE(pipeline);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void ClearCommand::deserialize(PipelineImpl&, ISerializer& serializer)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
2014-04-04 01:03:15 +02:00
|
|
|
char tmp[256];
|
|
|
|
serializer.deserializeArrayItem(tmp, 255);
|
|
|
|
if (strcmp(tmp, "all") == 0)
|
|
|
|
{
|
|
|
|
m_buffers = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
|
|
|
}
|
|
|
|
else if (strcmp(tmp, "depth") == 0)
|
|
|
|
{
|
|
|
|
m_buffers = GL_DEPTH_BUFFER_BIT;
|
|
|
|
}
|
2014-03-14 22:45:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void ClearCommand::execute(PipelineInstanceImpl&)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
glClear(m_buffers);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void RenderModelsCommand::deserialize(PipelineImpl&, ISerializer& serializer)
|
2014-04-04 01:03:15 +02:00
|
|
|
{
|
|
|
|
serializer.deserializeArrayItem(m_layer_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
void RenderModelsCommand::execute(PipelineInstanceImpl& pipeline)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
2014-04-04 01:03:15 +02:00
|
|
|
pipeline.renderModels(m_layer_mask);
|
2014-03-14 22:45:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void ApplyCameraCommand::deserialize(PipelineImpl&, ISerializer& serializer)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
serializer.deserializeArrayItem(m_camera_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
void ApplyCameraCommand::execute(PipelineInstanceImpl& pipeline)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
2014-04-07 21:18:16 +02:00
|
|
|
ASSERT(pipeline.m_renderer != NULL);
|
|
|
|
pipeline.m_renderer->applyCamera(pipeline.m_cameras[m_camera_idx]);
|
2014-03-14 22:45:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void BindFramebufferCommand::deserialize(PipelineImpl&, ISerializer& serializer)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
serializer.deserializeArrayItem(m_buffer_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
void BindFramebufferCommand::execute(PipelineInstanceImpl& pipeline)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
pipeline.m_framebuffers[m_buffer_index]->bind();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void UnbindFramebufferCommand::execute(PipelineInstanceImpl&)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
FrameBuffer::unbind();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DrawFullscreenQuadCommand::deserialize(PipelineImpl& pipeline, ISerializer& serializer)
|
|
|
|
{
|
2014-03-16 13:11:23 +01:00
|
|
|
const int MATERIAL_NAME_MAX_LENGTH = 100;
|
|
|
|
char material[MATERIAL_NAME_MAX_LENGTH];
|
|
|
|
serializer.deserializeArrayItem(material, MATERIAL_NAME_MAX_LENGTH);
|
2014-03-14 22:45:39 +01:00
|
|
|
char material_path[MAX_PATH];
|
|
|
|
strcpy(material_path, "materials/");
|
|
|
|
strcat(material_path, material);
|
|
|
|
strcat(material_path, ".mat");
|
2014-04-07 21:18:16 +02:00
|
|
|
m_material = static_cast<Material*>(pipeline.getResourceManager().get(ResourceManager::MATERIAL)->load(material_path));
|
2014-03-14 22:45:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
void DrawFullscreenQuadCommand::execute(PipelineInstanceImpl& pipeline)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
pipeline.drawFullscreenQuad(m_material);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void BindFramebufferTextureCommand::deserialize(PipelineImpl&, ISerializer& serializer)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
/// TODO map names to indices
|
|
|
|
serializer.deserializeArrayItem(m_framebuffer_index);
|
|
|
|
serializer.deserializeArrayItem(m_renderbuffer_index);
|
|
|
|
serializer.deserializeArrayItem(m_texture_uint);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
void BindFramebufferTextureCommand::execute(PipelineInstanceImpl& pipeline)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
glActiveTexture(GL_TEXTURE0 + m_texture_uint);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, pipeline.m_framebuffers[m_framebuffer_index]->getTexture((FrameBuffer::RenderBuffers)m_renderbuffer_index));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-09 23:59:39 +02:00
|
|
|
void RenderShadowmapCommand::deserialize(PipelineImpl&, ISerializer& serializer)
|
2014-04-04 01:03:15 +02:00
|
|
|
{
|
|
|
|
serializer.deserializeArrayItem(m_layer_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
void RenderShadowmapCommand::execute(PipelineInstanceImpl& pipeline)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
2014-04-04 01:03:15 +02:00
|
|
|
pipeline.renderShadowmap(m_layer_mask);
|
2014-03-14 22:45:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-30 11:11:50 +02:00
|
|
|
void BindShadowmapCommand::execute(PipelineInstanceImpl& pipeline)
|
2014-03-14 22:45:39 +01:00
|
|
|
{
|
|
|
|
glActiveTexture(GL_TEXTURE0 + 1);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, pipeline.m_shadowmap_framebuffer->getDepthTexture());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-05 22:54:29 +02:00
|
|
|
Resource* PipelineManager::createResource(const Path& path)
|
|
|
|
{
|
|
|
|
return LUX_NEW(PipelineImpl)(path, getOwner());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PipelineManager::destroyResource(Resource& resource)
|
|
|
|
{
|
|
|
|
LUX_DELETE(static_cast<PipelineImpl*>(&resource));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-01-24 18:13:50 +01:00
|
|
|
} // ~namespace Lux
|