summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-06-17 07:29:02 +0200
committerStanislaw Halik <sthalik@misaki.pl>2023-06-17 07:29:02 +0200
commit0c9383d5944a53b9b6fcc60fc56450a5418f0963 (patch)
treeb5b83af37c1ea08b71c5eb644c76dcdb75bc76c7
parent1c8f175159520518f05da9b287c783b692bd453f (diff)
shaders: wip
-rw-r--r--editor/imgui.cpp8
-rw-r--r--shaders/lightmap.cpp125
-rw-r--r--shaders/lightmap.frag39
-rw-r--r--shaders/lightmap.hpp45
-rw-r--r--shaders/lightmap.vert5
5 files changed, 162 insertions, 60 deletions
diff --git a/editor/imgui.cpp b/editor/imgui.cpp
index c22c6ebf..d8377033 100644
--- a/editor/imgui.cpp
+++ b/editor/imgui.cpp
@@ -227,11 +227,13 @@ void app::draw_lightmap_test()
.falloff = li.falloff,
};
auto& shader = M->lightmap_shader();
- shader.begin({0, 0}, L);
+ shader.begin_accum();
+ shader.begin_light({ 0, 0 }, L);
shader.add_chunk({}, e_->chunk());
- shader.end();
+ shader.finish_light_only();
+ ImGui::Image(&shader.scratch_texture(), {1024, 1024});
+ shader.end_accum();
M->bind();
- ImGui::Image(&shader.texture(), {1024, 1024});
}
ImGui::End();
if (!is_open)
diff --git a/shaders/lightmap.cpp b/shaders/lightmap.cpp
index 1174241a..72aed74c 100644
--- a/shaders/lightmap.cpp
+++ b/shaders/lightmap.cpp
@@ -12,6 +12,7 @@
#include <Magnum/GL/Version.h>
#include "src/tile-bbox.hpp"
#include "src/tile-atlas.hpp"
+#include <Magnum/GL/Renderer.h>
#if defined __CLION_IDE__ || defined __clang__
#pragma GCC diagnostic ignored "-Wfloat-equal"
@@ -40,11 +41,17 @@ auto lightmap_shader::make_framebuffer(Vector2i size) -> Framebuffer
{
Framebuffer framebuffer;
- framebuffer.color = GL::Texture2D{};
- framebuffer.color
- .setStorage(1, GL::TextureFormat::RGB8, size)
+ framebuffer.scratch = GL::Texture2D{};
+ framebuffer.scratch
.setWrapping(GL::SamplerWrapping::ClampToBorder)
- .setBorderColor(Color4{0.f, 0.f, 0.f, 1.f});
+ .setBorderColor(Color4{0, 0, 0, 1})
+ .setStorage(1, GL::TextureFormat::RGBA8, size);
+
+ framebuffer.accum = GL::Texture2D{};
+ framebuffer.accum
+ .setWrapping(GL::SamplerWrapping::ClampToBorder)
+ .setBorderColor(Color4{0, 0, 0, 1})
+ .setStorage(1, GL::TextureFormat::RGBA8, size);
//framebuffer.depth = GL::Renderbuffer{};
//framebuffer.depth.setStorage(GL::RenderbufferFormat::DepthComponent32F, size);
@@ -52,7 +59,7 @@ auto lightmap_shader::make_framebuffer(Vector2i size) -> Framebuffer
framebuffer.fb = GL::Framebuffer{{ {}, size }};
framebuffer.fb
//.attachRenderbuffer(GL::Framebuffer::BufferAttachment::Depth, framebuffer.depth);
- .attachTexture(GL::Framebuffer::ColorAttachment{0}, framebuffer.color, 0)
+ .attachTexture(GL::Framebuffer::ColorAttachment{0}, framebuffer.scratch, 0)
//.clearDepth(0);
.clearColor(0, Color4{0.f, 0.f, 0.f, 1.f});
@@ -70,7 +77,6 @@ GL::Mesh lightmap_shader::make_mesh()
lightmap_shader::lightmap_shader() :
framebuffer { make_framebuffer(image_size) },
- accum { make_framebuffer(image_size) },
_quads { ValueInit, buffer_size },
_indexes { ValueInit, buffer_size },
_vertex_buf { _quads },
@@ -93,12 +99,19 @@ lightmap_shader::lightmap_shader() :
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShaders({vert, frag});
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
+
+ setUniform(ModeUniform, DrawLightmapMode);
+ clear();
}
-void lightmap_shader::flush_vertexes()
+void lightmap_shader::flush_vertexes(ShaderMode mode)
{
+ fm_assert(_count != (size_t)-1);
+
if (_count > 0)
{
+ setUniform(ModeUniform, mode);
+
_index_buf.setSubData(0, ArrayView<std::array<UnsignedShort, 6>>{_indexes, _count});
_vertex_buf.setSubData(0, ArrayView<std::array<Vector2, 4>>{_quads, _count});
@@ -106,8 +119,8 @@ void lightmap_shader::flush_vertexes()
mesh.setCount((int)(6 * _count));
mesh.setIndexRange(0, 0, (uint32_t)(_count * 6 - 1));
AbstractShaderProgram::draw(mesh);
- _count = 0;
}
+ _count = 0;
}
std::array<UnsignedShort, 6> lightmap_shader::quad_indexes(size_t N)
@@ -123,6 +136,7 @@ void lightmap_shader::add_light(Vector2i neighbor_offset, const light_s& light)
{
fm_debug_assert(_count == 0);
fm_debug_assert(_quads.size() > 0);
+ fm_assert(!_light_center);
constexpr auto tile_size = TILE_SIZE2.sum()/2;
float I;
@@ -145,6 +159,7 @@ void lightmap_shader::add_light(Vector2i neighbor_offset, const light_s& light)
constexpr auto image_size_factor = Vector2(image_size) / Vector2(chunk_size);
auto center_fragcoord = center * image_size_factor; // window-relative coordinates
+ _count = 0;
_indexes[_count] = quad_indexes(0);
_quads[_count] = std::array<Vector2, 4>{{
{ I_clip + center_clip.x(), -I_clip + center_clip.y() },
@@ -153,7 +168,7 @@ void lightmap_shader::add_light(Vector2i neighbor_offset, const light_s& light)
{ -I_clip + center_clip.x(), I_clip + center_clip.y() },
}};
- _count++;
+ _count = 1;
float alpha = light.color.a() / 255.f;
auto color = Vector3{light.color.rgb()} / 255.f;
@@ -164,10 +179,11 @@ void lightmap_shader::add_light(Vector2i neighbor_offset, const light_s& light)
setUniform(SizeUniform, 1.f/image_size_factor);
_light_center = center;
- flush_vertexes();
+ flush_vertexes(DrawLightmapMode);
setUniform(FalloffUniform, (uint32_t)light_falloff::constant);
setUniform(ColorIntensityUniform, shadow_color);
+ setUniform(SamplerUniform, 1);
}
Vector2 lightmap_shader::project_vertex(Vector2 light, Vector2 vertex, Vector2 length)
@@ -183,7 +199,8 @@ Vector2 lightmap_shader::project_vertex(Vector2 light, Vector2 vertex, Vector2 l
void lightmap_shader::add_rect(Vector2i neighbor_offset, Vector2 min, Vector2 max)
{
- fm_assert(_light_center);
+ fm_assert(_light_center && _count != (size_t)-1);
+
auto li = *_light_center;
auto off = Vector2(neighbor_offset)*chunk_size + chunk_offset;
@@ -224,20 +241,22 @@ void lightmap_shader::add_rect(Vector2i neighbor_offset, Vector2 min, Vector2 ma
void lightmap_shader::add_rect(Vector2i 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(Vector2i neighbor_offset, chunk& c)
{
- fm_assert(_light_center);
-
add_geometry(neighbor_offset, c);
add_entities(neighbor_offset, c);
}
void lightmap_shader::add_geometry(Vector2i neighbor_offset, chunk& c)
{
+ fm_assert(_light_center && _count != (size_t)-1);
+
for (auto i = 0uz; i < TILE_COUNT; i++)
{
auto t = c[i];
@@ -267,6 +286,8 @@ void lightmap_shader::add_geometry(Vector2i neighbor_offset, chunk& c)
void lightmap_shader::add_entities(Vector2i neighbor_offset, chunk& c)
{
+ fm_assert(_light_center && _count != (size_t)-1);
+
for (const auto& e_ : c.entities())
{
const auto& e = *e_;
@@ -290,47 +311,101 @@ void lightmap_shader::add_quad(const std::array<Vector2, 4>& quad)
_quads[i] = quad;
_indexes[i] = quad_indexes(i);
if (i+1 == buffer_size) [[unlikely]]
- flush_vertexes();
+ flush_vertexes(DrawLightmapMode);
}
-void lightmap_shader::clear()
+void lightmap_shader::clear_scratch()
{
_light_center = {};
framebuffer.fb.clearColor(0, Vector4ui{0});
- accum.fb.clearColor(0, Vector4ui{0});
+}
+
+void lightmap_shader::clear()
+{
+ clear_scratch();
+ _count = (size_t)-1;
+ framebuffer.fb.clearColor(1, Vector4ui{0});
//framebuffer.fb.clearDepth(0);
}
void lightmap_shader::bind()
{
+ //fm_assert(_count == 0 && !_light_center);
+ using BF = Magnum::GL::Renderer::BlendFunction;
+ framebuffer.scratch.bind(TextureSampler);
framebuffer.fb.bind();
}
-void lightmap_shader::begin(Vector2i neighbor_offset, const light_s& light)
+void lightmap_shader::begin_accum()
{
- fm_assert(_count == 0 && !_light_center);
+ fm_assert(!_light_center);
+ fm_assert(_count == (size_t)-1);
+
clear();
bind();
+ _count = 0;
+}
+
+void lightmap_shader::end_accum()
+{
+ fm_assert(!_light_center);
+ fm_assert(_count == 0);
+ _count = (size_t)-1;
+}
+
+void lightmap_shader::begin_light(Vector2i neighbor_offset, const light_s& light)
+{
+ fm_assert(_count == 0 && !_light_center);
+ clear_scratch();
+ _count = 0;
add_light(neighbor_offset, light);
- flush_vertexes();
+ flush_vertexes(DrawLightmapMode);
+}
+
+void lightmap_shader::finish_light_only()
+{
+ fm_assert(_light_center && _count != (size_t)-1);
+ flush_vertexes(DrawLightmapMode);
+ _light_center = {};
}
-void lightmap_shader::end()
+void lightmap_shader::finish_and_blend_light()
{
- fm_assert(_light_center);
- flush_vertexes();
+ fm_assert(_light_center && _count != (size_t)-1);
+ flush_vertexes(DrawLightmapMode);
_light_center = {};
+ _indexes[0] = quad_indexes(0);
+ _quads[0] = {{
+ { 1, -1 }, /* 3--1 1 */
+ { 1, 1 }, /* | / /| */
+ { -1, -1 }, /* |/ / | */
+ { -1, 1 }, /* 2 2--0 */
+ }};
+
+ using BF = Magnum::GL::Renderer::BlendFunction;
+ GL::Renderer::setBlendFunction(BF::One, BF::One);
+ _count = 1;
+ flush_vertexes(BlendLightmapMode);
+ GL::Renderer::setBlendFunction(BF::SourceAlpha, BF::OneMinusSourceAlpha);
}
-GL::Texture2D& lightmap_shader::texture()
+GL::Texture2D& lightmap_shader::scratch_texture()
{
fm_assert(_count == 0);
- fm_debug_assert(framebuffer.color.id());
- return framebuffer.color;
+ fm_debug_assert(framebuffer.scratch.id());
+ return framebuffer.scratch;
+}
+
+GL::Texture2D& lightmap_shader::accum_texture()
+{
+ fm_assert(_count == 0);
+ fm_debug_assert(framebuffer.accum.id());
+ return framebuffer.accum;
}
bool light_s::operator==(const light_s&) const noexcept = default;
lightmap_shader::~lightmap_shader() = default;
+
} // namespace floormat
diff --git a/shaders/lightmap.frag b/shaders/lightmap.frag
index 61bf10ff..1f017fb6 100644
--- a/shaders/lightmap.frag
+++ b/shaders/lightmap.frag
@@ -4,25 +4,34 @@ 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;
out vec4 color;
void main() {
- 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 A = 1;
- //attenuation = ((light_dist - dist)**exponent) / (light_dist**exponent)
- if (falloff == 0) // linear
- A = max(0, (L - dist) / L);
- else if (falloff == 2) // quadratic
+ if (mode == 1) // draw
{
- float tmp = max(0, L - dist);
- A = max(0, tmp*tmp / (L*L));
+ 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 A = 1;
+ //attenuation = ((light_dist - dist)**exponent) / (light_dist**exponent)
+ if (falloff == 0) // linear
+ A = max(0, (L - dist) / L);
+ else if (falloff == 2) // quadratic
+ {
+ float tmp = max(0, L - dist);
+ A = max(0, 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);
+ }
+ else if (mode == 2) // blend
+ {
+ color = texture(sampler, gl_FragCoord.xy );
}
- //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);
}
diff --git a/shaders/lightmap.hpp b/shaders/lightmap.hpp
index 655534ff..f9f29156 100644
--- a/shaders/lightmap.hpp
+++ b/shaders/lightmap.hpp
@@ -39,41 +39,56 @@ struct lightmap_shader final : GL::AbstractShaderProgram
struct Framebuffer final {
GL::Framebuffer fb{NoCreate};
//GL::Renderbuffer depth{NoCreate};
- GL::Texture2D color{NoCreate};
+ GL::Texture2D scratch{NoCreate}, accum{NoCreate};
};
- void begin(Vector2i neighbor_offset, const light_s& light);
+ void begin_light(Vector2i neighbor_offset, const light_s& light);
void add_chunk(Vector2i neighbor_offset, chunk& c);
void add_entities(Vector2i neighbor_offset, chunk& c);
void add_geometry(Vector2i neighbor_offset, chunk& c);
void add_rect(Vector2i neighbor_offset, Vector2 min, Vector2 max);
void add_rect(Vector2i neighbor_offset, Pair<Vector2, Vector2> minmax);
- void end();
- GL::Texture2D& texture();
+ void finish_light_only();
+ void finish_and_blend_light();
+ GL::Texture2D& scratch_texture();
+ GL::Texture2D& accum_texture();
+ void begin_accum();
+ void end_accum();
private:
+ enum {
+ ColorIntensityUniform = 0,
+ CenterUniform = 1,
+ FalloffUniform = 2,
+ SizeUniform = 3,
+ ModeUniform = 4,
+ SamplerUniform = 5,
+ };
+
+ enum : Int {
+ TextureSampler = 1,
+ };
+
+ enum ShaderMode : uint32_t {
+ DrawLightmapMode = 1,
+ BlendLightmapMode = 2,
+ };
+
static Framebuffer make_framebuffer(Vector2i size);
GL::Mesh make_mesh();
void add_light(Vector2i neighbor_offset, const light_s& light);
- void flush_vertexes();
+ void flush_vertexes(ShaderMode mode);
void add_quad(const std::array<Vector2, 4>& quad);
void bind();
+ void clear_scratch();
void clear();
static std::array<UnsignedShort, 6> quad_indexes(size_t N);
static Vector2 project_vertex(Vector2 light, Vector2 vertex, Vector2 length);
- enum : int {
- ColorIntensityUniform = 0,
- CenterUniform = 1,
- FalloffUniform = 2,
- SizeUniform = 3,
- //DepthUniform = 4,
- };
-
- Framebuffer framebuffer, accum;
+ Framebuffer framebuffer;
Array<std::array<Vector2, 4>> _quads;
Array<std::array<UnsignedShort, 6>> _indexes;
- size_t _count = 0;
+ size_t _count = (size_t)-1;
GL::Buffer _vertex_buf{NoCreate}, _index_buf{NoCreate};
GL::Mesh _mesh{NoCreate};
Optional<Vector2> _light_center;
diff --git a/shaders/lightmap.vert b/shaders/lightmap.vert
index 8cda9926..21a4d7a9 100644
--- a/shaders/lightmap.vert
+++ b/shaders/lightmap.vert
@@ -4,9 +4,10 @@ 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 bool enable_lightmap;
+layout (location = 4) uniform uint mode;
+layout (location = 5) uniform sampler2D sampler;
-layout (location = 0) in vec4 position;
+layout (location = 0) in vec2 position;
void main() {
gl_Position = vec4(position.x, position.y, 0, 1);