diff options
Diffstat (limited to 'shaders')
| -rw-r--r-- | shaders/lightmap.cpp | 149 | ||||
| -rw-r--r-- | shaders/lightmap.frag | 23 | ||||
| -rw-r--r-- | shaders/lightmap.hpp | 76 | ||||
| -rw-r--r-- | shaders/lightmap.vert | 12 |
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); +} |
