2020-08-26 15:38:01 +08:00
|
|
|
#pragma once
|
|
|
|
#include <blah/containers/str.h>
|
2021-12-13 12:41:23 +08:00
|
|
|
#include <blah/numerics/spatial.h>
|
2021-05-10 08:23:02 +08:00
|
|
|
#include <blah/numerics/color.h>
|
2021-03-23 07:53:27 +08:00
|
|
|
#include <blah/graphics/subtexture.h>
|
|
|
|
#include <blah/graphics/spritefont.h>
|
2020-10-25 06:21:36 +08:00
|
|
|
#include <blah/containers/vector.h>
|
2020-12-27 06:44:48 +08:00
|
|
|
#include <blah/graphics/blend.h>
|
2020-12-31 06:03:50 +08:00
|
|
|
#include <blah/graphics/sampler.h>
|
2020-12-27 06:44:48 +08:00
|
|
|
#include <blah/graphics/renderpass.h>
|
2021-05-10 08:23:02 +08:00
|
|
|
#include <blah/app.h>
|
2020-08-26 15:38:01 +08:00
|
|
|
|
|
|
|
namespace Blah
|
|
|
|
{
|
2021-03-23 07:53:27 +08:00
|
|
|
// Spritebatcher Color Mode
|
2020-08-26 15:38:01 +08:00
|
|
|
enum class ColorMode
|
|
|
|
{
|
2021-03-23 07:53:27 +08:00
|
|
|
// Draws textures and shapes normally
|
2020-08-26 15:38:01 +08:00
|
|
|
Normal,
|
2021-03-23 07:53:27 +08:00
|
|
|
|
|
|
|
// Ignores the texture color but still uses transparency, essentially
|
|
|
|
// drawing the "shape" of the texture a solid color
|
2020-08-26 15:38:01 +08:00
|
|
|
Wash
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class TextAlign : char
|
|
|
|
{
|
|
|
|
Center = 0,
|
|
|
|
Left = 1 << 1,
|
|
|
|
Right = 1 << 2,
|
|
|
|
Top = 1 << 3,
|
|
|
|
Bottom = 1 << 4,
|
|
|
|
|
|
|
|
TopLeft = Top | Left,
|
|
|
|
TopRight = Top | Right,
|
|
|
|
BottomLeft = Bottom | Left,
|
|
|
|
BottomRight = Bottom | Right
|
|
|
|
};
|
|
|
|
|
|
|
|
inline TextAlign operator|(TextAlign lhs, TextAlign rhs) { return static_cast<TextAlign>(static_cast<char>(lhs) | static_cast<char>(rhs)); }
|
|
|
|
inline TextAlign operator&(TextAlign lhs, TextAlign rhs) { return static_cast<TextAlign>(static_cast<char>(lhs) & static_cast<char>(rhs)); }
|
|
|
|
|
2021-03-23 07:53:27 +08:00
|
|
|
// A 2D sprite batcher, used for drawing shapes and textures
|
2020-08-26 15:38:01 +08:00
|
|
|
class Batch
|
|
|
|
{
|
|
|
|
public:
|
2020-12-24 08:57:49 +08:00
|
|
|
|
2021-08-07 07:03:44 +08:00
|
|
|
// The name of the default uniforms to set
|
2022-02-10 17:13:20 +08:00
|
|
|
String texture_uniform = "u_texture";
|
|
|
|
String sampler_uniform = "u_texture_sampler";
|
|
|
|
String matrix_uniform = "u_matrix";
|
2020-12-24 08:57:49 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
// Snaps all drawing coordinates to integer values
|
|
|
|
// This is useful for drawing Pixel Art stuff
|
|
|
|
bool integerize = false;
|
|
|
|
|
2020-12-31 06:03:50 +08:00
|
|
|
// Default Sampler, set on clear
|
|
|
|
TextureSampler default_sampler;
|
|
|
|
|
2020-12-24 08:57:49 +08:00
|
|
|
// Pushes a new matrix onto the stack, and uses it for transforming all drawing.
|
|
|
|
// `absolute` means the matrix provided will not be transformed by the current stack.
|
2021-12-13 12:41:23 +08:00
|
|
|
void push_matrix(const Mat3x2f& matrix, bool absolute = false);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pops the matrix from the stack
|
2021-12-13 12:41:23 +08:00
|
|
|
Mat3x2f pop_matrix();
|
2020-12-24 08:57:49 +08:00
|
|
|
|
2020-12-24 16:19:58 +08:00
|
|
|
// Gets the current matrix from the top of the stackKO
|
2021-12-13 12:41:23 +08:00
|
|
|
Mat3x2f peek_matrix() const;
|
2020-12-24 16:19:58 +08:00
|
|
|
|
2020-12-24 08:57:49 +08:00
|
|
|
// Pushes a Scissor rectangle. Note this is not transformed by the matrix stack
|
|
|
|
// or other scissors. Each push is screen-space.
|
2021-12-13 12:41:23 +08:00
|
|
|
void push_scissor(const Rectf& scissor);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pops a Scissor rectangle from the stack
|
2021-12-13 12:41:23 +08:00
|
|
|
Rectf pop_scissor();
|
2020-12-24 16:19:58 +08:00
|
|
|
|
|
|
|
// Gets the current Scissor rectangle from the top of the stack
|
2021-12-13 12:41:23 +08:00
|
|
|
Rectf peek_scissor() const;
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pushes a blend mode
|
2020-08-26 15:38:01 +08:00
|
|
|
void push_blend(const BlendMode& blend);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pops a blend mode
|
2020-12-24 16:19:58 +08:00
|
|
|
BlendMode pop_blend();
|
|
|
|
|
|
|
|
// Gets the current BlendMode from the top of the stack
|
|
|
|
BlendMode peek_blend() const;
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pushes a Material to use for all drawing. Note that the state of the Material
|
|
|
|
// is not copied - it will be drawn with the values of the Material at render.
|
2020-08-26 15:38:01 +08:00
|
|
|
void push_material(const MaterialRef& material);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pops a Material
|
2020-12-24 16:19:58 +08:00
|
|
|
MaterialRef pop_material();
|
|
|
|
|
|
|
|
// Gets the current Material from the top of the stack
|
|
|
|
MaterialRef peek_material() const;
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pushes a render layer. Lower values are rendered first. This is not super optimized
|
|
|
|
// and should generally be avoided.
|
2020-08-26 15:38:01 +08:00
|
|
|
void push_layer(int layer);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pops a Layer
|
2020-12-24 16:19:58 +08:00
|
|
|
int pop_layer();
|
|
|
|
|
|
|
|
// Gets the current Layer from the top of the stack
|
|
|
|
int peek_layer() const;
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pushes a Color Mode for drawing Textures
|
2020-08-26 15:38:01 +08:00
|
|
|
void push_color_mode(ColorMode mode);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Pops a Color MOde
|
2020-12-24 16:19:58 +08:00
|
|
|
ColorMode pop_color_mode();
|
|
|
|
|
|
|
|
// Gets the current ColorMode from the top of the stack
|
|
|
|
ColorMode peek_color_mode() const;
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2020-12-24 08:57:49 +08:00
|
|
|
// Sets the current texture used for drawing. Note that certain functions will override
|
|
|
|
// this (ex the `str` and `tex` methods)
|
2020-08-26 15:38:01 +08:00
|
|
|
void set_texture(const TextureRef& texture);
|
|
|
|
|
2020-12-31 06:03:50 +08:00
|
|
|
// Sets the current texture sampler for drawing.
|
|
|
|
void set_sampler(const TextureSampler& sampler);
|
|
|
|
|
2020-12-24 08:57:49 +08:00
|
|
|
// Draws the batch to the given target
|
2022-02-10 10:49:47 +08:00
|
|
|
void render(const TargetRef& target = nullptr);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Draws the batch to the given target, with the provided matrix
|
2021-12-13 12:41:23 +08:00
|
|
|
void render(const TargetRef& target, const Mat4x4f& matrix);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2020-12-24 08:57:49 +08:00
|
|
|
// Clears the batch
|
2020-08-26 15:38:01 +08:00
|
|
|
void clear();
|
2020-12-24 08:57:49 +08:00
|
|
|
|
|
|
|
// Clears and disposes all resources that the batch is using
|
2020-08-26 15:38:01 +08:00
|
|
|
void dispose();
|
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void line(const Vec2f& from, const Vec2f& to, float t, Color color);
|
|
|
|
void line(const Vec2f& from, const Vec2f& to, float t, Color fromColor, Color toColor);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void bezier_line(const Vec2f& from, const Vec2f& b, const Vec2f& to, int steps, float t, Color color);
|
|
|
|
void bezier_line(const Vec2f& from, const Vec2f& b, const Vec2f& c, const Vec2f& to, int steps, float t, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, Color color);
|
|
|
|
void tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, Color col0, Color col1, Color col2);
|
|
|
|
void tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, Color color);
|
|
|
|
void tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, Color col0, Color col1, Color col2);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void tri_line(const Vec2f& a, const Vec2f& b, const Vec2f& c, float t, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void rect(const Rectf& rect, Color color);
|
|
|
|
void rect_line(const Rectf& rect, float t, Color color);
|
|
|
|
void rect_rounded(const Rectf& rect, float radius, int steps, Color color);
|
|
|
|
void rect_rounded(const Rectf& rect, float rtl, int rtl_steps, float rtr, int rtr_steps, float rbr, int rbr_steps, float rbl, int rbl_steps, Color color);
|
|
|
|
void rect_rounded_line(const Rectf& rect, float radius, int steps, float t, Color color);
|
|
|
|
void rect_rounded_line(const Rectf& rect, float rtl, int rtl_steps, float rtr, int rtr_steps, float rbr, int rbr_steps, float rbl, int rbl_steps, float t, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void semi_circle(const Vec2f& center, float start_radians, float end_radians, float radius, int steps, Color centerColor, Color edgeColor);
|
|
|
|
void semi_circle(const Vec2f& center, float start_radians, float end_radians, float radius, int steps, Color color);
|
|
|
|
void semi_circle_line(const Vec2f& center, float start_radians, float end_radians, float radius, int steps, float t, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void circle(const Vec2f& center, float radius, int steps, Color color);
|
|
|
|
void circle(const Vec2f& center, float radius, int steps, Color center_color, Color outer_color);
|
|
|
|
void circle_line(const Vec2f& center, float radius, float t, int steps, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, Color color);
|
|
|
|
void quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, Color col0, Color col1, Color col2, Color col3);
|
|
|
|
void quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, const Vec2f& tex3, Color color);
|
|
|
|
void quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, const Vec2f& tex3, Color col0, Color col1, Color col2, Color col3);
|
|
|
|
void quad_line(const Vec2f& a, const Vec2f& b, const Vec2f& c, const Vec2f& d, float t, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void arrow_head(const Vec2f& point_pos, float radians, float side_len, Color color);
|
|
|
|
void arrow_head(const Vec2f& point_pos, const Vec2f& from_pos, float side_len, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void tex(const TextureRef& texture, const Vec2f& position = Vec2f::zero, Color color = Color::white);
|
|
|
|
void tex(const TextureRef& texture, const Vec2f& position, const Vec2f& origin, const Vec2f& scale, float rotation, Color color);
|
|
|
|
void tex(const TextureRef& texture, const Rectf& clip, const Vec2f& position, const Vec2f& origin, const Vec2f& scale, float rotation, Color color);
|
2020-12-24 16:19:58 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void tex(const Subtexture& subtexture, const Vec2f& position = Vec2f::zero, Color color = Color::white);
|
|
|
|
void tex(const Subtexture& subtexture, const Vec2f& pos, const Vec2f& origin, const Vec2f& scale, float rotation, Color color);
|
|
|
|
void tex(const Subtexture& subtexture, const Rectf& clip, const Vec2f& pos, const Vec2f& origin, const Vec2f& scale, float rotation, Color color);
|
2020-12-24 08:57:49 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void str(const SpriteFont& font, const String& text, const Vec2f& pos, Color color);
|
|
|
|
void str(const SpriteFont& font, const String& text, const Vec2f& pos, TextAlign align, float size, Color color);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
struct Vertex
|
|
|
|
{
|
2021-12-13 12:41:23 +08:00
|
|
|
Vec2f pos;
|
|
|
|
Vec2f tex;
|
2020-08-26 15:38:01 +08:00
|
|
|
Color col;
|
|
|
|
|
2021-03-21 08:33:04 +08:00
|
|
|
u8 mult;
|
|
|
|
u8 wash;
|
|
|
|
u8 fill;
|
|
|
|
u8 pad;
|
2020-08-26 15:38:01 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct DrawBatch
|
|
|
|
{
|
|
|
|
int layer;
|
|
|
|
int offset;
|
|
|
|
int elements;
|
|
|
|
MaterialRef material;
|
|
|
|
BlendMode blend;
|
|
|
|
TextureRef texture;
|
2020-12-31 06:03:50 +08:00
|
|
|
TextureSampler sampler;
|
2020-08-26 15:38:01 +08:00
|
|
|
bool flip_vertically;
|
2021-12-13 12:41:23 +08:00
|
|
|
Rectf scissor;
|
2020-08-26 15:38:01 +08:00
|
|
|
|
|
|
|
DrawBatch() :
|
|
|
|
layer(0),
|
|
|
|
offset(0),
|
|
|
|
elements(0),
|
|
|
|
blend(BlendMode::Normal),
|
|
|
|
flip_vertically(false),
|
|
|
|
scissor(0, 0, -1, -1) {}
|
|
|
|
};
|
|
|
|
|
2021-03-21 14:24:18 +08:00
|
|
|
MaterialRef m_default_material;
|
|
|
|
MeshRef m_mesh;
|
2022-02-10 17:13:20 +08:00
|
|
|
Mat3x2f m_matrix = Mat3x2f::identity;
|
|
|
|
ColorMode m_color_mode = ColorMode::Normal;
|
|
|
|
u8 m_tex_mult = 255;
|
|
|
|
u8 m_tex_wash = 0;
|
2021-03-21 14:24:18 +08:00
|
|
|
DrawBatch m_batch;
|
|
|
|
Vector<Vertex> m_vertices;
|
|
|
|
Vector<u32> m_indices;
|
2021-12-13 12:41:23 +08:00
|
|
|
Vector<Mat3x2f> m_matrix_stack;
|
|
|
|
Vector<Rectf> m_scissor_stack;
|
2021-03-21 14:24:18 +08:00
|
|
|
Vector<BlendMode> m_blend_stack;
|
|
|
|
Vector<MaterialRef> m_material_stack;
|
|
|
|
Vector<ColorMode> m_color_mode_stack;
|
|
|
|
Vector<int> m_layer_stack;
|
|
|
|
Vector<DrawBatch> m_batches;
|
2022-02-10 17:13:20 +08:00
|
|
|
int m_batch_insert = 0;
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
void render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4x4f& matrix);
|
2020-08-26 15:38:01 +08:00
|
|
|
};
|
|
|
|
}
|