summaryrefslogtreecommitdiffhomepage
path: root/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'shaders')
-rw-r--r--shaders/lightmap.cpp149
-rw-r--r--shaders/lightmap.frag23
-rw-r--r--shaders/lightmap.hpp76
-rw-r--r--shaders/lightmap.vert12
4 files changed, 214 insertions, 46 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
diff --git a/shaders/lightmap.frag b/shaders/lightmap.frag
index 2179160c..8690ffcb 100644
--- a/shaders/lightmap.frag
+++ b/shaders/lightmap.frag
@@ -1,18 +1,13 @@
precision mediump float;
-struct light_u
-{
- vec4 color_and_intensity;
- vec2 center;
- uint mode;
-};
-
-#define TILE_MAX_DIM 16
-#define TILE_SIZE_X 64
-#define TILE_SIZE_Y 64
+layout (location = 0) uniform vec4 color_intensity;
+layout (location = 1) uniform vec2 center;
+layout (location = 2) uniform uint falloff;
+layout (location = 3) uniform vec2 size;
-#define CHUNK_SIZE_X (TILE_SIZE_X * TILE_MAX_DIM)
-#define CHUNK_SIZE_Y (TILE_SIZE_Y * TILE_MAX_DIM)
+out vec4 color;
-layout (location = 0) uniform vec4 color_intensity;
-layout (location = 1) uniform vec2 px;
+void main() {
+ vec3 color = color_intensity.xyz;
+ float dist = color_intensity.w;
+}
diff --git a/shaders/lightmap.hpp b/shaders/lightmap.hpp
index a2d566e6..a7204723 100644
--- a/shaders/lightmap.hpp
+++ b/shaders/lightmap.hpp
@@ -1,15 +1,32 @@
#pragma once
#include "light-falloff.hpp"
-#include <Magnum/GL/AbstractShaderProgram.h>
+#include <array>
+#include <Corrade/Containers/Array.h>
#include <Magnum/Math/Vector2.h>
-#include <Magnum/Math/Vector3.h>
#include <Magnum/Math/Vector4.h>
#include <Magnum/Math/Color.h>
+#include <Magnum/GL/AbstractShaderProgram.h>
+#include <Magnum/GL/Buffer.h>
+#include <Magnum/GL/Framebuffer.h>
+#include <Magnum/GL/Mesh.h>
+//#include <Magnum/GL/Renderbuffer.h>
+#include <Magnum/GL/Texture.h>
namespace floormat {
-struct local_coords;
+struct light_s final
+{
+ Vector2 center;
+ float dist = 1;
+ //float depth = -1 + 1e-4f;
+ Math::Color3<uint8_t> color {255, 255, 255};
+ light_falloff falloff = light_falloff::linear;
+
+ bool operator==(const light_s&) const noexcept;
+};
+
+struct chunk;
struct lightmap_shader final : GL::AbstractShaderProgram
{
@@ -18,32 +35,43 @@ struct lightmap_shader final : GL::AbstractShaderProgram
explicit lightmap_shader();
~lightmap_shader() override;
- void set_light(Vector2i neighbor_offset, local_coords pos, Vector2b offset);
- struct light light() const; // is a reader accessor needed?
-
-private:
- static Vector2i get_px_pos(Vector2i neighbor_offset, local_coords pos, Vector2b offset);
-
- struct light_u final
- {
- Vector4 color_and_intensity;
- Vector2 center;
- uint32_t mode;
+ struct Framebuffer final {
+ GL::Framebuffer fb{NoCreate};
+ //GL::Renderbuffer depth{NoCreate};
+ GL::Texture2D color{NoCreate};
};
- struct light_s final
- {
- float intensity = 1;
- Color3ub color {255, 255, 255};
- Vector2i center;
- light_falloff falloff;
+ void begin(Vector2i neighbor_offset, const light_s& light);
+ void add_chunk(Vector2i neighbor_offset, const chunk& ch);
+ void add_vertex(Vector2i neighbor_offset, const std::array<Vector2, 4>& obj);
+ void end();
+ GL::Texture2D& texture();
- bool operator==(const light_s&) const noexcept;
- };
+private:
+ static Framebuffer make_framebuffer();
+ GL::Mesh make_mesh();
+ void add_light(Vector2i neighbor_offset, const light_s& light);
+ void flush_vertexes();
+ void bind();
+ void clear();
+ static std::array<UnsignedShort, 6> quad_indexes(size_t N);
- enum { ColorUniform = 0, CenterUniform = 1, FalloffUniform = 2, DepthUniform = 3, };
+ enum : int {
+ ColorIntensityUniform = 0,
+ CenterUniform = 1,
+ FalloffUniform = 2,
+ SizeUniform = 3,
+ //DepthUniform = 4,
+ };
- light_s _light;
+ Framebuffer framebuffer;
+ Array<std::array<Vector2, 4>> _quads;
+ Array<std::array<UnsignedShort, 6>> _indexes;
+ size_t _count = 0;
+ //light_u _light_uniform;
+ //light_s _light;
+ GL::Buffer _vertex_buf{NoCreate}, _index_buf{NoCreate};
+ GL::Mesh _mesh{NoCreate};
};
} // namespace floormat
diff --git a/shaders/lightmap.vert b/shaders/lightmap.vert
index e69de29b..a044a141 100644
--- a/shaders/lightmap.vert
+++ b/shaders/lightmap.vert
@@ -0,0 +1,12 @@
+precision mediump float;
+
+layout (location = 0) uniform vec4 color_intensity;
+layout (location = 1) uniform vec2 center;
+layout (location = 2) uniform uint falloff;
+layout (location = 3) uniform vec2 size;
+
+layout (location = 0) in vec4 position;
+
+void main() {
+ gl_Position = vec4(position.x, -position.y, 0, 1);
+}