summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--main/draw.cpp27
-rw-r--r--shaders/lightmap.cpp268
-rw-r--r--shaders/lightmap.frag37
-rw-r--r--shaders/lightmap.hpp125
-rw-r--r--shaders/lightmap.vert29
5 files changed, 333 insertions, 153 deletions
diff --git a/main/draw.cpp b/main/draw.cpp
index 449c1c70..78cd1906 100644
--- a/main/draw.cpp
+++ b/main/draw.cpp
@@ -1,4 +1,3 @@
-#include "Magnum/GL/Context.h"
#include "main-impl.hpp"
#include "floormat/app.hpp"
#include "src/camera-offset.hpp"
@@ -49,18 +48,22 @@ void main_impl::recalc_viewport(Vector2i fb_size, Vector2i win_size) noexcept
#endif
// -- state ---
- using R = GL::Renderer;
glEnable(GL_LINE_SMOOTH);
- GL::Renderer::setBlendEquation(R::BlendEquation::Add, R::BlendEquation::Add);
- GL::Renderer::setBlendFunction(R::BlendFunction::SourceAlpha, R::BlendFunction::OneMinusSourceAlpha);
- GL::Renderer::disable(R::Feature::FaceCulling);
- GL::Renderer::disable(R::Feature::DepthTest);
- GL::Renderer::enable(R::Feature::Blending);
- GL::Renderer::enable(R::Feature::ScissorTest);
- GL::Renderer::enable(R::Feature::DepthClamp);
- GL::Renderer::setDepthFunction(R::DepthFunction::Greater);
+ using BlendEquation = GL::Renderer::BlendEquation;
+ using BF = GL::Renderer::BlendFunction;
+ using DepthFunction = GL::Renderer::DepthFunction;
+ using ProvokingVertex = GL::Renderer::ProvokingVertex;
+ using Feature = GL::Renderer::Feature;
+ GL::Renderer::setBlendEquation(BlendEquation::Add, BlendEquation::Add);
+ GL::Renderer::setBlendFunction(BF::SourceAlpha, BF::OneMinusSourceAlpha);
+ GL::Renderer::disable(Feature::FaceCulling);
+ GL::Renderer::disable(Feature::DepthTest);
+ GL::Renderer::enable(Feature::Blending);
+ GL::Renderer::enable(Feature::ScissorTest);
+ GL::Renderer::enable(Feature::DepthClamp);
+ GL::Renderer::setDepthFunction(DepthFunction::Greater);
GL::Renderer::setScissor({{}, fb_size});
- GL::Renderer::setProvokingVertex(R::ProvokingVertex::FirstVertexConvention);
+ GL::Renderer::setProvokingVertex(ProvokingVertex::FirstVertexConvention);
// -- user--
app.on_viewport_event(fb_size);
@@ -197,6 +200,7 @@ void main_impl::draw_world() noexcept
if (!c_)
continue;
auto& c = *c_;
+#if 0
{
std::array<chunk*, 8> ns = {};
for (auto i = 0uz; i < 8; i++)
@@ -210,6 +214,7 @@ void main_impl::draw_world() noexcept
(void)_lightmap_shader.accum_texture();
}
}
+#endif
bind();
const with_shifted_camera_offset o{_shader, ch, {minx, miny}, {maxx, maxy}};
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;
diff --git a/shaders/lightmap.frag b/shaders/lightmap.frag
index bbf04326..5e380596 100644
--- a/shaders/lightmap.frag
+++ b/shaders/lightmap.frag
@@ -1,36 +1,37 @@
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 = 4) uniform uint mode;
-layout (location = 5) uniform sampler2D sampler;
+layout (location = 0) uniform sampler2D sampler;
+layout (location = 1) uniform vec3 light_color;
+layout (location = 2) uniform vec2 size;
+layout (location = 3) uniform vec2 center_fragcoord;
+layout (location = 4) uniform vec2 center_clip;
+layout (location = 5) uniform float intensity;
+layout (location = 6) uniform uint mode;
+layout (location = 7) uniform uint falloff;
out vec4 color;
//layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;
void main() {
- if (mode == 1) // draw
+ if (mode == 0)
{
+ color = vec4(0, 0, 0, 1);
+ }
+ else if (mode == 1) // draw
+ {
+ float L = intensity;
vec2 pos = gl_FragCoord.xy;
- float L = color_intensity.w;
- float dist = distance(pos, center);
- //float dist = sqrt(tmp.x*tmp.x + tmp.y*tmp.y);
+ float dist = distance(pos, center_fragcoord);
float A = 1;
- //attenuation = ((light_dist - dist)**exponent) / (light_dist**exponent)
- if (falloff == 0) // linear
+ if (frag_falloff == 0) // linear
A = max(0, (L - dist) / L);
- else if (falloff == 2) // quadratic
+ else if (frag_falloff == 2) // quadratic
{
float tmp = max(0, L - dist);
- A = max(0, tmp*tmp / (L*L));
+ A = tmp*tmp / (L*L);
}
- //I = sqrt(color_intensity.w*1.5)*16;
- //dist = sqrt(tmp.x*tmp.x + tmp.y*tmp.y);
- //float alpha = 1 - min(1, dist / I);
- color = vec4(color_intensity.xyz, A);
+ color = vec4(light_color, A);
}
else if (mode == 2) // blend
{
diff --git a/shaders/lightmap.hpp b/shaders/lightmap.hpp
index f5c7d8c1..e48d4b5d 100644
--- a/shaders/lightmap.hpp
+++ b/shaders/lightmap.hpp
@@ -31,8 +31,6 @@ struct chunk;
struct lightmap_shader final : GL::AbstractShaderProgram
{
- using Position = GL::Attribute<0, Vector2>;
-
explicit lightmap_shader();
~lightmap_shader() override;
@@ -42,58 +40,115 @@ struct lightmap_shader final : GL::AbstractShaderProgram
GL::Texture2D scratch{NoCreate}, accum{NoCreate};
};
- void begin_light(Vector2b neighbor_offset, const light_s& light);
- void add_chunk(Vector2b neighbor_offset, chunk& c);
- void add_entities(Vector2b neighbor_offset, chunk& c);
- void add_geometry(Vector2b neighbor_offset, chunk& c);
- void add_rect(Vector2b neighbor_offset, Vector2 min, Vector2 max);
- void add_rect(Vector2b neighbor_offset, Pair<Vector2, Vector2> minmax);
- void finish_light_only();
- void finish_and_blend_light();
- GL::Texture2D& scratch_texture();
- GL::Texture2D& accum_texture();
- void begin_accum();
- void end_accum();
+ struct output final {
+ GL::Texture2D &scratch, &accum;
+ };
+
+#if 0
+const blend_light = {
+ equation: {color: gl.FUNC_ADD, alpha: gl.FUNC_ADD},
+ function: {color_src:gl.DST_ALPHA, alpha_src:gl.ONE,
+ color_dst:gl.ONE, alpha_dst:gl.ZERO},
+};
+
+// Shadows should only be drawn into the alpha channel and should leave color untouched.
+// You could also do this with a write mask if that's supported.
+const blend_shadow = {
+ equation: {color: gl.FUNC_ADD, alpha: gl.FUNC_ADD},
+ function: {color_src:gl.ZERO, alpha_src:gl.ZERO,
+ color_dst:gl.ONE_MINUS_SRC_COLOR, alpha_dst:GL_ONE},
+};
+#endif
+
+ //void begin_light(Vector2 neighbor_offset, const light_s& light);
+
+ void begin_occlusion();
+ void end_occlusion();
+ void add_chunk(Vector2 neighbor_offset, chunk& c);
+ void add_entities(Vector2 neighbor_offset, chunk& c);
+ void add_geometry(Vector2 neighbor_offset, chunk& c);
+ void add_rect(Vector2 neighbor_offset, Vector2 min, Vector2 max);
+ void add_rect(Vector2 neighbor_offset, Pair<Vector2, Vector2> minmax);
+ //void finish_light_only();
+ //void finish_and_blend_light();
+ struct output output();
+
+ //GL::Texture2D& scratch_texture();
+ //GL::Texture2D& accum_texture();
+ //void begin_accum();
+ //void end_accum();
void bind();
static constexpr auto max_chunks = Vector2s(8, 8);
+#if 0
+layout (location = 0) uniform sampler2D sampler;
+layout (location = 1) uniform vec3 light_color;
+layout (location = 2) uniform vec2 size;
+layout (location = 3) uniform vec2 center_fragcoord;
+layout (location = 4) uniform vec2 center_clip;
+layout (location = 5) uniform float intensity;
+layout (location = 6) uniform uint mode;
+layout (location = 7) uniform uint falloff;
+#endif
+
+ using Position = GL::Attribute<0, Vector2>;
+
private:
- enum {
- ColorIntensityUniform = 0,
- CenterUniform = 1,
- FalloffUniform = 2,
- SizeUniform = 3,
- ModeUniform = 4,
- SamplerUniform = 5,
+ enum : Int {
+ SamplerUniform = 0,
+ LightColorUniform = 1,
+ SizeUniform = 2,
+ CenterFragcoordUniform = 3,
+ CenterClipUniform = 4,
+ IntensityUniform = 5,
+ ModeUniform = 6,
+ FalloffUniform = 7,
};
enum : Int {
TextureSampler = 1,
};
- enum ShaderMode : uint32_t {
+ enum ShaderMode : uint32_t
+ {
+ DrawShadowsMode = 0,
DrawLightmapMode = 1,
BlendLightmapMode = 2,
};
+#if 0
+ _mesh.setCount(6)
+ .addVertexBuffer(_vertex_buffer, 0, tile_shader::Position{},
+ tile_shader::TextureCoordinates{}, tile_shader::Depth{})
+ .setIndexBuffer(_index_buffer, 0, GL::MeshIndexType::UnsignedShort);
+ CORRADE_INTERNAL_ASSERT(_mesh.isIndexed());
+#endif
+
static Framebuffer make_framebuffer(Vector2i size);
- GL::Mesh make_mesh();
- void add_light(Vector2b neighbor_offset, const light_s& light);
- void flush_vertexes(ShaderMode mode);
- void add_quad(const std::array<Vector2, 4>& quad);
- void clear_scratch();
- void clear_accum();
+ GL::Mesh make_occlusion_mesh();
+ void add_light(Vector2 neighbor_offset, const light_s& light);
+ //void flush_vertexes(ShaderMode mode);
+ //void add_quad(const std::array<Vector2, 4>& quad);
+ //void clear_scratch();
+ //void clear_accum();
static std::array<UnsignedShort, 6> quad_indexes(size_t N);
- static Vector2 project_vertex(Vector2 light, Vector2 vertex, Vector2 length);
+ GL::Buffer vertex_buf{NoCreate}, index_buf{NoCreate}; // set to {NoCreate} on capacity change
+ Array<std::array<Vector3, 4>> vertexes; // todo make a contiguous allocation
+ Array<std::array<UnsignedShort, 6>> indexes;
+ size_t count = 0, capacity = 0;
Framebuffer framebuffer;
- Array<std::array<Vector2, 4>> _quads;
- Array<std::array<UnsignedShort, 6>> _indexes;
- size_t _count = (size_t)-1;
- GL::Buffer _vertex_buf{NoCreate}, _index_buf{NoCreate};
- GL::Mesh _mesh{NoCreate};
- Optional<Vector2> _light_center;
+ GL::Mesh occlusion_mesh{NoCreate};
+ static constexpr auto starting_capacity = 1; // todo
+
+ std::array<Vector3, 4> light_vertexes;
+ GL::Buffer light_vertex_buf{NoCreate};
+ GL::Mesh light_mesh{NoCreate};
+
+ GL::Mesh blend_mesh{NoCreate};
+
+ [[nodiscard]] std::array<Vector3, 4>& alloc_rect();
};
} // namespace floormat
diff --git a/shaders/lightmap.vert b/shaders/lightmap.vert
index 21a4d7a9..479add5c 100644
--- a/shaders/lightmap.vert
+++ b/shaders/lightmap.vert
@@ -1,14 +1,29 @@
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 = 4) uniform uint mode;
-layout (location = 5) uniform sampler2D sampler;
+layout (location = 0) uniform sampler2D sampler;
+layout (location = 1) uniform vec3 light_color;
+layout (location = 2) uniform vec2 size;
+layout (location = 3) uniform vec2 center_fragcoord;
+layout (location = 4) uniform vec2 center_clip;
+layout (location = 5) uniform float intensity;
+layout (location = 6) uniform uint mode;
+layout (location = 7) uniform uint falloff;
+
+layout (location = 0) flat out vec3 frag_color;
+layout (location = 1) flat out float frag_intensity;
layout (location = 0) in vec2 position;
void main() {
- gl_Position = vec4(position.x, position.y, 0, 1);
+ vec2 pos = position.xy;
+ vec2 dir = pos - center_clip;
+ float len = length(dir);
+ if (len > 1e-6)
+ {
+ vec2 dir_norm = dir * (1/len);
+ pos += dir_norm * position.z * 4;
+ }
+ gl_Position = vec4(pos, 0, 1);
+ frag_intensity = color_intensity.a;
+ frag_falloff = uint(position_falloff.w);
}