summaryrefslogtreecommitdiffhomepage
path: root/shaders/lightmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'shaders/lightmap.cpp')
-rw-r--r--shaders/lightmap.cpp268
1 files changed, 186 insertions, 82 deletions
diff --git a/shaders/lightmap.cpp b/shaders/lightmap.cpp
index ce841509..d857f3ba 100644
--- a/shaders/lightmap.cpp
+++ b/shaders/lightmap.cpp
@@ -3,6 +3,7 @@
#include "src/tile-defs.hpp"
#include "loader/loader.hpp"
#include "src/chunk.hpp"
+#include <Corrade/Utility/Move.h>
#include <Corrade/Containers/PairStl.h>
#include <Corrade/Containers/Iterable.h>
#include <cmath>
@@ -33,10 +34,24 @@ constexpr auto buffer_size = 256uz;
constexpr auto clip_start = Vector2{-1, -1};
constexpr auto clip_scale = 2/(chunk_size * max_neighbors);
-constexpr auto shadow_length = chunk_size * 2 * max_neighbors;
+//constexpr auto shadow_length = chunk_size * 2 * max_neighbors;
constexpr auto shadow_color = Vector4{0, 0, 0, 1};
constexpr auto shadow_wall_depth = 4.f;
+constexpr auto half_neighbors = Vector2(max_neighbors)/2;
+
+using Utility::forward;
+
+template<typename T>
+GL::Mesh make_light_mesh(T&& vert, T&& index)
+{
+ GL::Mesh mesh{GL::MeshPrimitive::Triangles};
+ mesh.addVertexBuffer(forward<T>(vert), 0, lightmap_shader::Position{})
+ .setIndexBuffer(forward<T>(index), 0, GL::MeshIndexType::UnsignedShort)
+ .setCount(6);
+ return mesh;
+}
+
} // namespace
auto lightmap_shader::make_framebuffer(Vector2i size) -> Framebuffer
@@ -68,25 +83,89 @@ auto lightmap_shader::make_framebuffer(Vector2i size) -> Framebuffer
.clearColor(1, Color4{0, 0, 0, 1});
framebuffer.fb.mapForDraw(GL::Framebuffer::ColorAttachment{0});
+ using BF = Magnum::GL::Renderer::BlendFunction;
+ GL::Renderer::setBlendFunction(0, BF::One, BF::Zero, BF::One, BF::Zero);
+ GL::Renderer::setBlendFunction(1, BF::One, BF::One, BF::One, BF::One);
+
return framebuffer;
}
-GL::Mesh lightmap_shader::make_mesh()
+auto lightmap_shader::output() -> struct output
+{
+ return { framebuffer.scratch, framebuffer.accum };
+}
+
+GL::Mesh lightmap_shader::make_occlusion_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));
+ mesh.addVertexBuffer(vertex_buf, 0, Position{})
+ .setIndexBuffer(index_buf, 0, GL::MeshIndexType::UnsignedShort)
+ .setCount(int32_t(6 * capacity));
return mesh;
}
-lightmap_shader::lightmap_shader() :
- framebuffer { make_framebuffer(image_size) },
- _quads { ValueInit, buffer_size },
- _indexes { ValueInit, buffer_size },
- _vertex_buf { _quads },
- _index_buf { _indexes },
- _mesh { make_mesh() }
+void lightmap_shader::begin_occlusion()
+{
+ count = 0;
+}
+
+void lightmap_shader::end_occlusion()
+{
+ bool create_mesh = !vertex_buf.id();
+
+ if (create_mesh)
+ {
+ occlusion_mesh = GL::Mesh{NoCreate};
+ vertex_buf = GL::Buffer{vertexes.prefix(capacity), GL::BufferUsage::DynamicDraw};
+ index_buf = GL::Buffer{indexes.prefix(capacity)};
+ occlusion_mesh = make_occlusion_mesh();
+ }
+ else
+ {
+ if (!occlusion_mesh.id())
+ occlusion_mesh = make_occlusion_mesh();
+ vertex_buf.setSubData(0, vertexes.prefix(count));
+ index_buf.setSubData(0, indexes.prefix(count));
+ }
+}
+
+std::array<Vector3, 4>& lightmap_shader::alloc_rect()
+{
+ if (count == capacity)
+ {
+ if (capacity == 0)
+ capacity = starting_capacity;
+ else
+ capacity <<= 1;
+ fm_debug_assert(count < capacity);
+
+ occlusion_mesh = GL::Mesh{NoCreate};
+ vertex_buf = GL::Buffer{NoCreate};
+ index_buf = GL::Buffer{NoCreate};
+ auto vertexes_ = std::move(vertexes);
+ auto indexes_ = std::move(indexes);
+ vertexes = Array<std::array<Vector3, 4>>{ValueInit, capacity};
+ indexes = Array<std::array<UnsignedShort, 6>>{ValueInit, capacity};
+ for (auto i = 0uz; i < count; i++)
+ vertexes[i] = vertexes_[i];
+ for (auto i = 0uz; i < count; i++)
+ indexes[i] = indexes_[i];
+ indexes[count] = quad_indexes(count);
+ auto& ret = vertexes[count];
+ count++;
+ return ret;
+ }
+ else
+ {
+ fm_debug_assert(count < capacity);
+ auto& ret = vertexes[count];
+ indexes[count] = quad_indexes(count);
+ count++;
+ return ret;
+ }
+}
+
+lightmap_shader::lightmap_shader()
{
constexpr auto min_version = GL::Version::GL330;
const auto version = GL::Context::current().version();
@@ -105,11 +184,33 @@ lightmap_shader::lightmap_shader() :
attachShaders({vert, frag});
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
+ framebuffer = make_framebuffer(image_size);
+
+ auto blend_vertexes = std::array<Vector3, 4>{{
+ { 1, -1, 0 }, /* 3--1 1 */
+ { 1, 1, 0 }, /* | / /| */
+ { -1, -1, 0 }, /* |/ / | */
+ { -1, 1, 0 }, /* 2 2--0 */
+ }};
+ blend_mesh = make_light_mesh<GL::Buffer&&>(GL::Buffer{blend_vertexes}, GL::Buffer{quad_indexes(0)});
+
+ light_vertex_buf = GL::Buffer{std::array<Vector3, 4>{}};
+ light_mesh = GL::Mesh{GL::MeshPrimitive::Triangles};
+ light_mesh.addVertexBuffer(light_vertex_buf, 0, lightmap_shader::Position{})
+ .setIndexBuffer(GL::Buffer{quad_indexes(0)}, 0, GL::MeshIndexType::UnsignedShort)
+ .setCount(6);
+
+ setUniform(SamplerUniform, TextureSampler);
+ setUniform(LightColorUniform, Color3{1, 1, 1});
+ setUniform(SizeUniform, Vector2(1 / (chunk_size * max_neighbors)));
+ setUniform(CenterFragcoordUniform, Vector2(0, 0));
+ setUniform(CenterClipUniform, Vector2(-1, 1));
+ setUniform(IntensityUniform, 1.f);
setUniform(ModeUniform, DrawLightmapMode);
- clear_scratch();
- clear_accum();
+ setUniform(FalloffUniform, (uint32_t)light_falloff::constant);
}
+#if 0
void lightmap_shader::flush_vertexes(ShaderMode mode)
{
fm_assert(_count != (size_t)-1);
@@ -128,6 +229,7 @@ void lightmap_shader::flush_vertexes(ShaderMode mode)
}
_count = 0;
}
+#endif
std::array<UnsignedShort, 6> lightmap_shader::quad_indexes(size_t N)
{
@@ -138,83 +240,77 @@ std::array<UnsignedShort, 6> lightmap_shader::quad_indexes(size_t N)
}; /* 2 2--0 */
}
-void lightmap_shader::add_light(Vector2b neighbor_offset, const light_s& light)
+void lightmap_shader::add_light(Vector2 neighbor_offset, const light_s& light)
{
- fm_debug_assert(_count == 0);
- fm_debug_assert(_quads.size() > 0);
- fm_assert(!_light_center);
+ Vector2 I;
- constexpr auto tile_size = TILE_SIZE2.sum()/2;
- float I;
switch (light.falloff)
{
default:
- I = 1;
break;
case light_falloff::linear:
case light_falloff::quadratic:
- I = light.dist * tile_size;
+ I = light.dist * TILE_SIZE2;
break;
}
- I = std::fmax(1.f, I);
+ I = { std::fmax(1.f, I.x()), std::fmax(1.f, I.y()) };
- auto I_clip = I * tile_size;
- auto center = light.center + chunk_offset + Vector2(neighbor_offset)*chunk_size;
- auto center_clip = clip_start + Vector2{center} * clip_scale; // clip coordinates
- auto center_fragcoord = center; // window-relative coordinates
-
- _indexes[0] = quad_indexes(0);
- _quads[0] = std::array<Vector2, 4>{{
- { I_clip + center_clip.x(), -I_clip + center_clip.y() },
- { I_clip + center_clip.x(), I_clip + center_clip.y() },
- { -I_clip + center_clip.x(), -I_clip + center_clip.y() },
- { -I_clip + center_clip.x(), I_clip + center_clip.y() },
- }};
- _count = 1;
+ auto I_clip = I * TILE_SIZE2;
+ // window-relative coordinates
+ auto center_fragcoord = light.center + chunk_offset + (neighbor_offset+half_neighbors)*chunk_size;
+ auto center_clip = clip_start + center_fragcoord * clip_scale; // clip coordinates
float alpha = light.color.a() / 255.f;
auto color = Vector3{light.color.rgb()} / 255.f;
- setUniform(ColorIntensityUniform, Vector4{Vector3{color} * alpha, I });
- setUniform(CenterUniform, center_fragcoord);
- setUniform(FalloffUniform, (uint32_t)light.falloff);
+ setUniform(SamplerUniform, TextureSampler);
+ setUniform(LightColorUniform, color);
setUniform(SizeUniform, 1 / (chunk_size * max_neighbors));
+ setUniform(CenterFragcoordUniform, center_fragcoord);
+ setUniform(CenterClipUniform, center_clip);
+ setUniform(IntensityUniform, alpha);
+ setUniform(FalloffUniform, (uint32_t)light.falloff);
- _light_center = center;
- flush_vertexes(DrawLightmapMode);
+ framebuffer.fb.mapForDraw(GL::Framebuffer::ColorAttachment{0});
+ framebuffer.fb.clearColor(0, Color4{0, 0, 0, 1});
- setUniform(FalloffUniform, (uint32_t)light_falloff::constant);
- setUniform(ColorIntensityUniform, shadow_color);
- setUniform(SamplerUniform, TextureSampler);
-}
+ fm_debug_assert(light_vertex_buf.id());
+ fm_debug_assert(light_mesh.id());
+ setUniform(ModeUniform, DrawLightmapMode);
+ auto quad = std::array<Vector3, 4>{{
+ { I_clip.x() + center_clip.x(), -I_clip.y() + center_clip.y(), 0 },
+ { I_clip.x() + center_clip.x(), I_clip.y() + center_clip.y(), 0 },
+ { -I_clip.x() + center_clip.x(), -I_clip.y() + center_clip.y(), 0 },
+ { -I_clip.x() + center_clip.x(), I_clip.y() + center_clip.y(), 0 },
+ }};
+ light_vertex_buf.setSubData(0, quad);
+ draw(light_mesh);
-Vector2 lightmap_shader::project_vertex(Vector2 light, Vector2 vertex, Vector2 length)
-{
- auto dir = vertex - light;
- auto len = dir.length();
- if (std::fabs(len) < 1e-4f)
- return vertex;
- auto dir_norm = dir * (1/len);
- auto ret = vertex + dir_norm * length;
- return ret;
-}
+ setUniform(ModeUniform, DrawShadowsMode);
-void lightmap_shader::add_rect(Vector2b neighbor_offset, Vector2 min, Vector2 max)
-{
- fm_assert(_light_center && _count != (size_t)-1);
+ fm_assert(occlusion_mesh.id());
+ auto mesh_view = GL::MeshView{occlusion_mesh};
+ mesh_view.setCount((int32_t)count);
+ draw(mesh_view);
+ //mesh_view.setIndexRange(0, 0, uint32_t(count*6 - 1));
- auto li = *_light_center;
+ setUniform(ModeUniform, BlendLightmapMode);
+ framebuffer.fb.mapForDraw(GL::Framebuffer::ColorAttachment{1});
+ draw(blend_mesh);
+}
- auto off = Vector2(neighbor_offset)*chunk_size + chunk_offset;
+void lightmap_shader::add_rect(Vector2 neighbor_offset, Vector2 min, Vector2 max)
+{
+ auto off = (neighbor_offset+half_neighbors)*chunk_size + chunk_offset;
min += off;
max += off;
- const auto vertexes = std::array<Vector2, 4>{{
- { max.x(), min.y() },
- { max.x(), max.y() },
- { min.x(), min.y() },
- { min.x(), max.y() },
+ const auto vertexes = std::array<Vector3, 4>{{
+ { max.x(), min.y(), 0 },
+ { max.x(), max.y(), 0 },
+ { min.x(), min.y(), 0 },
+ { min.x(), max.y(), 0 },
}};
struct pair { uint8_t first, second; };
constexpr std::array<pair, 4> from = {{
@@ -234,32 +330,32 @@ void lightmap_shader::add_rect(Vector2b neighbor_offset, Vector2 min, Vector2 ma
auto [src1, src2] = from[i];
auto [dest1, dest2] = to[i];
auto verts = vertexes;
- verts[dest1] = project_vertex(li, vertexes[src1], shadow_length);
- verts[dest2] = project_vertex(li, vertexes[src2], shadow_length);
+ auto s1 = vertexes[src1], s2 = vertexes[src2];
+ verts[dest1] = Vector3(s1.x(), s1.y(), 1);
+ verts[dest2] = Vector3(s2.x(), s2.y(), 1);
+ constexpr auto scale = Vector3(clip_scale, 1);
+ constexpr auto start = Vector3(clip_start, 0);
for (auto& x : verts)
- x = clip_start + x * clip_scale;
- add_quad(verts);
+ x = start + x * scale;
+ for (auto i = 0uz; i < 4; i++)
+ alloc_rect() = verts;
}
}
-void lightmap_shader::add_rect(Vector2b neighbor_offset, Pair<Vector2, Vector2> minmax)
+void lightmap_shader::add_rect(Vector2 neighbor_offset, Pair<Vector2, Vector2> minmax)
{
- fm_assert(_light_center && _count != (size_t)-1);
-
auto [min, max] = minmax;
add_rect(neighbor_offset, min, max);
}
-void lightmap_shader::add_chunk(Vector2b neighbor_offset, chunk& c)
+void lightmap_shader::add_chunk(Vector2 neighbor_offset, chunk& c)
{
add_geometry(neighbor_offset, c);
add_entities(neighbor_offset, c);
}
-void lightmap_shader::add_geometry(Vector2b neighbor_offset, chunk& c)
+void lightmap_shader::add_geometry(Vector2 neighbor_offset, chunk& c)
{
- fm_assert(_light_center && _count != (size_t)-1);
-
for (auto i = 0uz; i < TILE_COUNT; i++)
{
auto t = c[i];
@@ -287,10 +383,8 @@ void lightmap_shader::add_geometry(Vector2b neighbor_offset, chunk& c)
}
}
-void lightmap_shader::add_entities(Vector2b neighbor_offset, chunk& c)
+void lightmap_shader::add_entities(Vector2 neighbor_offset, chunk& c)
{
- fm_assert(_light_center && _count != (size_t)-1);
-
for (const auto& e_ : c.entities())
{
const auto& e = *e_;
@@ -307,6 +401,7 @@ void lightmap_shader::add_entities(Vector2b neighbor_offset, chunk& c)
}
}
+#if 0
void lightmap_shader::add_quad(const std::array<Vector2, 4>& quad)
{
fm_debug_assert(_count < buffer_size);
@@ -316,7 +411,9 @@ void lightmap_shader::add_quad(const std::array<Vector2, 4>& quad)
if (i+1 == buffer_size) [[unlikely]]
flush_vertexes(DrawLightmapMode);
}
+#endif
+#if 0
void lightmap_shader::clear_scratch()
{
_light_center = {};
@@ -329,6 +426,7 @@ void lightmap_shader::clear_accum()
_count = (size_t)-1;
//framebuffer.fb.clearColor(1, Color4{0, 0, 0, 0});
}
+#endif
void lightmap_shader::bind()
{
@@ -337,6 +435,7 @@ void lightmap_shader::bind()
framebuffer.fb.bind();
}
+#if 0
void lightmap_shader::begin_accum()
{
fm_assert(!_light_center);
@@ -350,15 +449,16 @@ void lightmap_shader::begin_accum()
//framebuffer.fb.mapForDraw(GL::Framebuffer::ColorAttachment{0});
//framebuffer.fb.clearColor(1, Color4{0, 0, 0, 0});
}
-
void lightmap_shader::end_accum()
{
fm_assert(!_light_center);
fm_assert(_count == 0);
_count = (size_t)-1;
}
+#endif
-void lightmap_shader::begin_light(Vector2b neighbor_offset, const light_s& light)
+#if 0
+void lightmap_shader::begin_light(Vector2 neighbor_offset, const light_s& light)
{
fm_assert(_count == 0 && !_light_center);
clear_scratch();
@@ -391,15 +491,18 @@ void lightmap_shader::finish_and_blend_light()
{ -1, 1 }, /* 2 2--0 */
}};
- using BF = Magnum::GL::Renderer::BlendFunction;
+ using BF = Magnum::GL::Renderer::BF;
+ //GL::Renderer::setBlendColor(0x000000ff_rgbf);
GL::Renderer::setBlendFunction(BF::One, BF::One);
framebuffer.fb.mapForDraw(GL::Framebuffer::ColorAttachment{1});
_count = 1; flush_vertexes(BlendLightmapMode);
framebuffer.fb.mapForDraw(GL::Framebuffer::ColorAttachment{0});
GL::Renderer::setBlendFunction(BF::SourceAlpha, BF::OneMinusSourceAlpha);
}
+#endif
+#if 0
GL::Texture2D& lightmap_shader::scratch_texture()
{
fm_assert(_count == (size_t)-1);
@@ -413,6 +516,7 @@ GL::Texture2D& lightmap_shader::accum_texture()
fm_debug_assert(framebuffer.accum.id());
return framebuffer.accum;
}
+#endif
bool light_s::operator==(const light_s&) const noexcept = default;