/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "gpu/gpu_renderer.h" #include "core/camera.h" #include "core/light.h" using namespace GS; using namespace GS::GPU; //------------------------------------------------------------------------------ void Renderer::RenderFullscreenLight(Shader &p, Core::Light &l) { SetDepthFunc(DepthAlways); const float h = 1.f, k = 100.f; const float vtx[] = { -k, -k, h, k, -k, h, k, k, h, -k, k, h }; const size_t stride = sizeof(float) * 3; helper_vtx_vbo->Update(vtx, 0, stride * 4); SetShaderProgram(&p); SetIndexSource(helper_idx_vbo); SetVertexSource(helper_vtx_vbo, stride); ShaderInput *vtx_parm = p.GetInput(Core::ShaderInput::Position); if (vtx_parm) p.Set(*vtx_parm->location, 3, Types::ValueFloat, false, stride, 0); p.SetTransformInputs(Matrix4::IdentityMatrix(), Matrix4::IdentityMatrix(), Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix()); p.SetLightInputs(*this, *view_item, l); p.SetRendererInputs(*this); p.CommitInputs(); DrawElements(Types::PrimitiveTriangle, 3 * 2, Types::ValueUShort); if (vtx_parm) p.Set(*vtx_parm->location, 0, Types::ValueLast, false, 0, NULL); SetDepthFunc(DepthLess); } void Renderer::RenderSpotLight(Core::Light &l, const DrawContext &dc) { if (!view_item) return; Shader &p = (l.shadow == Core::Light::Shadow_Map) && gpu_config.enable_shadow ? *spotlight_shadow_program : *spotlight_program; if (!l.volume_range) RenderFullscreenLight(p, l); else { const Vector4 *vtx = l.frustum.GetVertices(); const size_t stride = sizeof(float) * 4; helper_vtx_vbo->Update(vtx, 0, stride * 8); SetShaderProgram(&p); SetIndexSource(box_idx_vbo); SetVertexSource(helper_vtx_vbo, stride); ShaderInput *vtx_parm = p.GetInput(Core::ShaderInput::Position); if (vtx_parm) p.Set(*vtx_parm->location, 3, Types::ValueFloat, false, stride, 0); p.SetTransformInputs(m_projection, m_view, m_iview, &Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix()); p.SetLightInputs(*this, *view_item, l); p.SetRendererInputs(*this); p.CommitInputs(); // TODO Boolean operation on light frustum and clipping planes. Vector4 row = view_item->GetMatrix().GetRow(3); Frustum::Visibility viscode = l.frustum.ClassifySet(1, &row, Units::Cm(50.f)); if (viscode != Frustum::Outside) { SetDepthFunc(DepthGreater); SetCullFunc(CullBack); } DrawElements(Types::PrimitiveTriangle, 3 * 2 * 6, Types::ValueUShort); if (vtx_parm) p.Set(*vtx_parm->location, 0, Types::ValueLast, false, 0, NULL); if (viscode != Frustum::Outside) { SetDepthFunc(DepthLess); SetCullFunc(CullFront); } } } void Renderer::RenderPointLight(Core::Light &l, const DrawContext &dc) { if (!view_item) return; Shader &p = (l.shadow == Core::Light::Shadow_Map) && gpu_config.enable_shadow ? *pointlight_shadow_program : *pointlight_program; if (!l.volume_range) RenderFullscreenLight(p, l); else { float k = l.volume_range; float pointlight_vtx[] = { -k, k, -k, k, k, -k, k, -k, -k, -k, -k, -k, -k, k, k, k, k, k, k, -k, k, -k, -k, k }; const size_t stride = sizeof(float) * 3; helper_vtx_vbo->Update(pointlight_vtx, 0, stride * 8); SetShaderProgram(&p); SetIndexSource(box_idx_vbo); SetVertexSource(helper_vtx_vbo, stride); ShaderInput *vtx_parm = p.GetInput(Core::ShaderInput::Position); if (vtx_parm) p.Set(*vtx_parm->location, 3, Types::ValueFloat, false, stride, 0); p.SetTransformInputs(m_projection, m_view, m_iview, &l.GetMatrix(), &l.GetInverseMatrix()); p.SetLightInputs(*this, *view_item, l); p.SetRendererInputs(*this); p.CommitInputs(); // MinMax vminmax; vminmax.SetFromPositionSize(l.GetMatrix().GetRow(3), Vector4(l.volume_range, l.volume_range, l.volume_range) * 2.1f); bool inside = vminmax.IsInside(view_item->GetMatrix().GetRow(3)); if (inside) { SetDepthFunc(DepthGreater); SetCullFunc(CullBack); } else { SetDepthFunc(DepthLess); SetCullFunc(CullFront); } DrawElements(Types::PrimitiveTriangle, 3 * 12, Types::ValueUShort); if (vtx_parm) p.Set(*vtx_parm->location, 0, Types::ValueLast, false, 0, NULL); SetDepthFunc(DepthLess); SetCullFunc(CullFront); } } void Renderer::RenderLinearLight(Core::Light &l, const DrawContext &dc) { RenderFullscreenQuad((l.shadow == Core::Light::Shadow_Map) && gpu_config.enable_shadow ? *linearlight_shadow_program : *linearlight_program, viewport.GetWidth() / (float)dimensions.x, viewport.GetHeight() / (float)dimensions.y, NULL, &l); } //------------------------------------------------------------------------------