summaryrefslogtreecommitdiffhomepage
path: root/shaders/lightmap.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-06-10 06:46:49 +0200
committerStanislaw Halik <sthalik@misaki.pl>2023-06-10 06:46:49 +0200
commitf7898053802ea38630f93034d0cd1555492fbc56 (patch)
treef81955574f7ecc24ff26ee770c45768a366d0202 /shaders/lightmap.cpp
parentdc913f11422e002059029cac8da2d6b9a725656a (diff)
wip
Diffstat (limited to 'shaders/lightmap.cpp')
-rw-r--r--shaders/lightmap.cpp149
1 files changed, 141 insertions, 8 deletions
diff --git a/shaders/lightmap.cpp b/shaders/lightmap.cpp
index 3575e424..8e8e1884 100644
--- a/shaders/lightmap.cpp
+++ b/shaders/lightmap.cpp
@@ -1,20 +1,153 @@
-#include "lightmap.hpp"
-#include "src/local-coords.hpp"
+#include "shaders/lightmap.hpp"
+#include "compat/assert.hpp"
+#include "src/tile-defs.hpp"
+#include "loader/loader.hpp"
+#include <Corrade/Containers/Iterable.h>
+#include <Magnum/Magnum.h>
+#include <Magnum/GL/MeshView.h>
+#include <Magnum/GL/Shader.h>
+#include <Magnum/GL/Version.h>
+//#include "src/tile-bbox.hpp"
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wfloat-equal"
+#if defined __CLION_IDE__ || defined __clang__
+#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
namespace floormat {
-lightmap_shader::~lightmap_shader() = default;
-bool lightmap_shader::light_s::operator==(const light_s&) const noexcept = default;
+namespace {
+
+constexpr auto chunk_size = TILE_SIZE2 * TILE_MAX_DIM;
+constexpr auto chunk_offset = TILE_SIZE2/2;
+constexpr auto image_size = iTILE_SIZE2 * TILE_MAX_DIM;
+constexpr auto buffer_size = 256uz;
-static constexpr Vector2 output_size = TILE_MAX_DIM * TILE_SIZE2 * 3;
+} // namespace
-lightmap_shader::lightmap_shader()
+auto lightmap_shader::make_framebuffer() -> Framebuffer
{
+ Framebuffer framebuffer;
+
+ framebuffer.fb = GL::Framebuffer{{ {}, image_size }};
+
+ framebuffer.color = GL::Texture2D{};
+ framebuffer.color.setStorage(1, GL::TextureFormat::RGBA8, image_size);
+ //framebuffer.depth = GL::Renderbuffer{};
+ //framebuffer.depth.setStorage(GL::RenderbufferFormat::DepthComponent32F, fb_size);
+
+ framebuffer.fb.attachTexture(GL::Framebuffer::ColorAttachment{0}, framebuffer.color, 0);
+ //framebuffer.fb.attachRenderbuffer(GL::Framebuffer::BufferAttachment::Depth, framebuffer.depth);
+ framebuffer.fb.clearColor(0, Color4{0.f, 0.f, 0.f, 1.f});
+ //framebuffer.fb.clearDepth(0);
+
+ return framebuffer;
+}
+GL::Mesh lightmap_shader::make_mesh()
+{
+ GL::Mesh mesh{GL::MeshPrimitive::Triangles};
+ mesh.addVertexBuffer(_vertex_buf, 0, Position{})
+ .setIndexBuffer(_index_buf, 0, GL::MeshIndexType::UnsignedShort)
+ .setCount(int32_t(6 * buffer_size));
+ return mesh;
}
+lightmap_shader::lightmap_shader() :
+ framebuffer { make_framebuffer() },
+ _quads { ValueInit, buffer_size },
+ _indexes { ValueInit, buffer_size },
+ _vertex_buf { _quads },
+ _index_buf { _indexes },
+ _mesh { make_mesh() }
+{
+ constexpr auto min_version = GL::Version::GL330;
+ const auto version = GL::Context::current().version();
+
+ if (version < min_version)
+ fm_abort("floormat requires OpenGL version %d, only %d is supported", (int)min_version, (int)version);
+
+ GL::Shader vert{version, GL::Shader::Type::Vertex};
+ GL::Shader frag{version, GL::Shader::Type::Fragment};
+
+ vert.addSource(loader.shader("shaders/lightmap.vert"));
+ frag.addSource(loader.shader("shaders/lightmap.frag"));
+
+ CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
+ CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
+ attachShaders({vert, frag});
+ CORRADE_INTERNAL_ASSERT_OUTPUT(link());
+}
+
+void lightmap_shader::flush_vertexes()
+{
+ // todo
+}
+
+void lightmap_shader::clear()
+{
+ framebuffer.fb.clearColor(0, Color4{1.f, 0.f, 1.f, 1.f});
+ //framebuffer.fb.clearDepth(0);
+}
+
+void lightmap_shader::bind()
+{
+ framebuffer.fb.bind();
+}
+
+std::array<UnsignedShort, 6> lightmap_shader::quad_indexes(size_t N)
+{
+ using u16 = UnsignedShort;
+ return { /* 3--1 1 */
+ (u16)(0+N*4), (u16)(1+N*4), (u16)(2+N*4), /* | / /| */
+ (u16)(2+N*4), (u16)(1+N*4), (u16)(3+N*4), /* |/ / | */
+ }; /* 2 2--0 */
+}
+
+void lightmap_shader::add_light(Vector2i neighbor_offset, const light_s& light)
+{
+ fm_debug_assert(_count == 0);
+
+ constexpr auto tile_size = TILE_SIZE2.sum()/2;
+ constexpr auto scale = 2/chunk_size;
+ auto dist = std::fmax(0.f, light.dist * tile_size);
+ auto center = light.center + chunk_offset + Vector2(neighbor_offset)*chunk_size;
+ auto center_clip = Vector2{center} * scale; // clip coordinate
+ constexpr auto image_size_factor = Vector2(image_size) / Vector2(chunk_size);
+ auto center_fragcoord = center * image_size_factor; // window-relative coordinates
+
+ _indexes[0] = quad_indexes(0);
+ _quads[0] = std::array<Vector2, 4>{{
+ { dist + center_clip.x(), -dist + center_clip.y() },
+ { dist + center_clip.x(), dist + center_clip.y() },
+ { -dist + center_clip.x(), -dist + center_clip.y() },
+ { -dist + center_clip.x(), dist + center_clip.y() },
+ }};
+
+ _index_buf.setSubData(0, ArrayView<std::array<UnsignedShort, 6>>{_indexes, 1});
+ _vertex_buf.setSubData(0, ArrayView<std::array<Vector2, 4>>{_quads, 1});
+
+ setUniform(ColorIntensityUniform, Vector4{Vector3{light.color}, dist});
+ setUniform(CenterUniform, center_fragcoord);
+ setUniform(FalloffUniform, (uint32_t)light.falloff);
+ setUniform(SizeUniform, chunk_size);
+
+
+}
+
+lightmap_shader::~lightmap_shader() = default;
+
+void lightmap_shader::begin(Vector2i neighbor_offset, const light_s& light)
+{
+ fm_assert(_count == 0);
+ clear();
+ add_light(neighbor_offset, light);
+}
+
+void lightmap_shader::end()
+{
+ flush_vertexes();
+}
+
+bool light_s::operator==(const light_s&) const noexcept = default;
+
} // namespace floormat