diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-06-17 07:29:02 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-06-17 07:29:02 +0200 |
commit | 0c9383d5944a53b9b6fcc60fc56450a5418f0963 (patch) | |
tree | b5b83af37c1ea08b71c5eb644c76dcdb75bc76c7 | |
parent | 1c8f175159520518f05da9b287c783b692bd453f (diff) |
shaders: wip
-rw-r--r-- | editor/imgui.cpp | 8 | ||||
-rw-r--r-- | shaders/lightmap.cpp | 125 | ||||
-rw-r--r-- | shaders/lightmap.frag | 39 | ||||
-rw-r--r-- | shaders/lightmap.hpp | 45 | ||||
-rw-r--r-- | shaders/lightmap.vert | 5 |
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); |