mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
lots of small rendering & batcher cleanup
This commit is contained in:
parent
46c900756e
commit
8c0ef3e769
|
@ -151,16 +151,28 @@ Mat3x2 Batch::pop_matrix()
|
||||||
return was;
|
return was;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mat3x2 Batch::peek_matrix() const
|
||||||
|
{
|
||||||
|
return m_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
void Batch::push_scissor(const Rect& scissor)
|
void Batch::push_scissor(const Rect& scissor)
|
||||||
{
|
{
|
||||||
m_scissor_stack.push_back(m_batch.scissor);
|
m_scissor_stack.push_back(m_batch.scissor);
|
||||||
SET_BATCH_VAR(scissor);
|
SET_BATCH_VAR(scissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::pop_scissor()
|
Rect Batch::pop_scissor()
|
||||||
{
|
{
|
||||||
|
Rect was = m_batch.scissor;
|
||||||
Rect scissor = m_scissor_stack.pop();
|
Rect scissor = m_scissor_stack.pop();
|
||||||
SET_BATCH_VAR(scissor);
|
SET_BATCH_VAR(scissor);
|
||||||
|
return was;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect Batch::peek_scissor() const
|
||||||
|
{
|
||||||
|
return m_batch.scissor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::push_blend(const BlendMode& blend)
|
void Batch::push_blend(const BlendMode& blend)
|
||||||
|
@ -169,10 +181,17 @@ void Batch::push_blend(const BlendMode& blend)
|
||||||
SET_BATCH_VAR(blend);
|
SET_BATCH_VAR(blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::pop_blend()
|
BlendMode Batch::pop_blend()
|
||||||
{
|
{
|
||||||
|
BlendMode was = m_batch.blend;
|
||||||
BlendMode blend = m_blend_stack.pop();
|
BlendMode blend = m_blend_stack.pop();
|
||||||
SET_BATCH_VAR(blend);
|
SET_BATCH_VAR(blend);
|
||||||
|
return was;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlendMode Batch::peek_blend() const
|
||||||
|
{
|
||||||
|
return m_batch.blend;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::push_material(const MaterialRef& material)
|
void Batch::push_material(const MaterialRef& material)
|
||||||
|
@ -181,10 +200,17 @@ void Batch::push_material(const MaterialRef& material)
|
||||||
SET_BATCH_VAR(material);
|
SET_BATCH_VAR(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::pop_material()
|
MaterialRef Batch::pop_material()
|
||||||
{
|
{
|
||||||
|
MaterialRef was = m_batch.material;
|
||||||
MaterialRef material = m_material_stack.pop();
|
MaterialRef material = m_material_stack.pop();
|
||||||
SET_BATCH_VAR(material);
|
SET_BATCH_VAR(material);
|
||||||
|
return was;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialRef Batch::peek_material() const
|
||||||
|
{
|
||||||
|
return m_batch.material;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::push_layer(int layer)
|
void Batch::push_layer(int layer)
|
||||||
|
@ -193,10 +219,17 @@ void Batch::push_layer(int layer)
|
||||||
SET_BATCH_VAR(layer);
|
SET_BATCH_VAR(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::pop_layer()
|
int Batch::pop_layer()
|
||||||
{
|
{
|
||||||
|
int was = m_batch.layer;
|
||||||
int layer = m_layer_stack.pop();
|
int layer = m_layer_stack.pop();
|
||||||
SET_BATCH_VAR(layer);
|
SET_BATCH_VAR(layer);
|
||||||
|
return was;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Batch::peek_layer() const
|
||||||
|
{
|
||||||
|
return m_batch.layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::push_color_mode(ColorMode mode)
|
void Batch::push_color_mode(ColorMode mode)
|
||||||
|
@ -208,11 +241,18 @@ void Batch::push_color_mode(ColorMode mode)
|
||||||
m_tex_wash = (m_color_mode == ColorMode::Wash ? 255 : 0);
|
m_tex_wash = (m_color_mode == ColorMode::Wash ? 255 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::pop_color_mode()
|
ColorMode Batch::pop_color_mode()
|
||||||
{
|
{
|
||||||
|
ColorMode was = m_color_mode;
|
||||||
m_color_mode = m_color_mode_stack.pop();
|
m_color_mode = m_color_mode_stack.pop();
|
||||||
m_tex_mult = (m_color_mode == ColorMode::Normal ? 255 : 0);
|
m_tex_mult = (m_color_mode == ColorMode::Normal ? 255 : 0);
|
||||||
m_tex_wash = (m_color_mode == ColorMode::Wash ? 255 : 0);
|
m_tex_wash = (m_color_mode == ColorMode::Wash ? 255 : 0);
|
||||||
|
return was;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorMode Batch::peek_color_mode() const
|
||||||
|
{
|
||||||
|
return m_color_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::set_texture(const TextureRef& texture)
|
void Batch::set_texture(const TextureRef& texture)
|
||||||
|
@ -764,9 +804,58 @@ void Batch::arrow_head(const Vec2& point_pos, const Vec2& from_pos, float side_l
|
||||||
tri(point_pos, base + perp * side_len / 2, base - perp * side_len / 2, color);
|
tri(point_pos, base + perp * side_len / 2, base - perp * side_len / 2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::tex()
|
void Batch::tex(const TextureRef& texture, const Vec2& pos, Color color)
|
||||||
{
|
{
|
||||||
|
set_texture(texture);
|
||||||
|
|
||||||
|
const auto w = texture->width();
|
||||||
|
const auto h = texture->height();
|
||||||
|
|
||||||
|
PUSH_QUAD(
|
||||||
|
pos.x, pos.y, pos.x + w, pos.y, pos.x + w, pos.y + h, pos.x, pos.y + h,
|
||||||
|
0, 0, 1, 0, 1, 1, 0, 1,
|
||||||
|
color, color, color, color,
|
||||||
|
m_tex_mult, m_tex_wash, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Batch::tex(const TextureRef& texture, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color)
|
||||||
|
{
|
||||||
|
push_matrix(Mat3x2::create_transform(pos, origin, scale, rotation));
|
||||||
|
|
||||||
|
set_texture(texture);
|
||||||
|
|
||||||
|
const auto w = texture->width();
|
||||||
|
const auto h = texture->height();
|
||||||
|
|
||||||
|
PUSH_QUAD(
|
||||||
|
0, 0, w, 0, w, h, 0, h,
|
||||||
|
0, 0, 1, 0, 1, 1, 0, 1,
|
||||||
|
color, color, color, color,
|
||||||
|
m_tex_mult, m_tex_wash, 0);
|
||||||
|
|
||||||
|
pop_matrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Batch::tex(const TextureRef& texture, const Rect& clip, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color)
|
||||||
|
{
|
||||||
|
push_matrix(Mat3x2::create_transform(pos, origin, scale, rotation));
|
||||||
|
|
||||||
|
set_texture(texture);
|
||||||
|
|
||||||
|
const auto tw = texture->width();
|
||||||
|
const auto th = texture->height();
|
||||||
|
const auto tx0 = clip.x / tw;
|
||||||
|
const auto tx1 = (clip.x + clip.w) / tw;
|
||||||
|
const auto ty0 = clip.y / th;
|
||||||
|
const auto ty1 = (clip.y + clip.h) / th;
|
||||||
|
|
||||||
|
PUSH_QUAD(
|
||||||
|
0, 0, clip.w, 0, clip.w, clip.h, 0, clip.h,
|
||||||
|
tx0, ty0, tx1, ty0, tx1, ty1, tx0, ty1,
|
||||||
|
color, color, color, color,
|
||||||
|
m_tex_mult, m_tex_wash, 0);
|
||||||
|
|
||||||
|
pop_matrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::tex(const Subtexture& sub, const Vec2& pos, Color color)
|
void Batch::tex(const Subtexture& sub, const Vec2& pos, Color color)
|
||||||
|
@ -835,6 +924,11 @@ void Batch::tex(const Subtexture& sub, const Vec2& pos, const Vec2& origin, cons
|
||||||
pop_matrix();
|
pop_matrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::tex(const Subtexture& sub, const Rect& clip, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color)
|
||||||
|
{
|
||||||
|
tex(sub.crop(clip), pos, origin, scale, rotation, color);
|
||||||
|
}
|
||||||
|
|
||||||
void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, Color color)
|
void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, Color color)
|
||||||
{
|
{
|
||||||
str(font, text, pos, TextAlign::TopLeft, font.size, color);
|
str(font, text, pos, TextAlign::TopLeft, font.size, color);
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace Blah
|
||||||
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)); }
|
||||||
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)); }
|
||||||
|
|
||||||
|
// A simple 2D sprite batcher, used for drawing shapes and textures
|
||||||
class Batch
|
class Batch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -57,38 +58,56 @@ namespace Blah
|
||||||
// Pops the matrix from the stack
|
// Pops the matrix from the stack
|
||||||
Mat3x2 pop_matrix();
|
Mat3x2 pop_matrix();
|
||||||
|
|
||||||
|
// Gets the current matrix from the top of the stackKO
|
||||||
|
Mat3x2 peek_matrix() const;
|
||||||
|
|
||||||
// Pushes a Scissor rectangle. Note this is not transformed by the matrix stack
|
// Pushes a Scissor rectangle. Note this is not transformed by the matrix stack
|
||||||
// or other scissors. Each push is screen-space.
|
// or other scissors. Each push is screen-space.
|
||||||
void push_scissor(const Rect& scissor);
|
void push_scissor(const Rect& scissor);
|
||||||
|
|
||||||
// Pops a Scissor rectangle from the stack
|
// Pops a Scissor rectangle from the stack
|
||||||
void pop_scissor();
|
Rect pop_scissor();
|
||||||
|
|
||||||
|
// Gets the current Scissor rectangle from the top of the stack
|
||||||
|
Rect peek_scissor() const;
|
||||||
|
|
||||||
// Pushes a blend mode
|
// Pushes a blend mode
|
||||||
void push_blend(const BlendMode& blend);
|
void push_blend(const BlendMode& blend);
|
||||||
|
|
||||||
// Pops a blend mode
|
// Pops a blend mode
|
||||||
void pop_blend();
|
BlendMode pop_blend();
|
||||||
|
|
||||||
|
// Gets the current BlendMode from the top of the stack
|
||||||
|
BlendMode peek_blend() const;
|
||||||
|
|
||||||
// Pushes a Material to use for all drawing. Note that the state of the Material
|
// 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.
|
// is not copied - it will be drawn with the values of the Material at render.
|
||||||
void push_material(const MaterialRef& material);
|
void push_material(const MaterialRef& material);
|
||||||
|
|
||||||
// Pops a Material
|
// Pops a Material
|
||||||
void pop_material();
|
MaterialRef pop_material();
|
||||||
|
|
||||||
|
// Gets the current Material from the top of the stack
|
||||||
|
MaterialRef peek_material() const;
|
||||||
|
|
||||||
// Pushes a render layer. Lower values are rendered first. This is not super optimized
|
// Pushes a render layer. Lower values are rendered first. This is not super optimized
|
||||||
// and should generally be avoided.
|
// and should generally be avoided.
|
||||||
void push_layer(int layer);
|
void push_layer(int layer);
|
||||||
|
|
||||||
// Pops a Layer
|
// Pops a Layer
|
||||||
void pop_layer();
|
int pop_layer();
|
||||||
|
|
||||||
|
// Gets the current Layer from the top of the stack
|
||||||
|
int peek_layer() const;
|
||||||
|
|
||||||
// Pushes a Color Mode for drawing Textures
|
// Pushes a Color Mode for drawing Textures
|
||||||
void push_color_mode(ColorMode mode);
|
void push_color_mode(ColorMode mode);
|
||||||
|
|
||||||
// Pops a Color MOde
|
// Pops a Color MOde
|
||||||
void pop_color_mode();
|
ColorMode pop_color_mode();
|
||||||
|
|
||||||
|
// Gets the current ColorMode from the top of the stack
|
||||||
|
ColorMode peek_color_mode() const;
|
||||||
|
|
||||||
// Sets the current texture used for drawing. Note that certain functions will override
|
// Sets the current texture used for drawing. Note that certain functions will override
|
||||||
// this (ex the `str` and `tex` methods)
|
// this (ex the `str` and `tex` methods)
|
||||||
|
@ -143,9 +162,13 @@ namespace Blah
|
||||||
void arrow_head(const Vec2& point_pos, float radians, float side_len, Color color);
|
void arrow_head(const Vec2& point_pos, float radians, float side_len, Color color);
|
||||||
void arrow_head(const Vec2& point_pos, const Vec2& from_pos, float side_len, Color color);
|
void arrow_head(const Vec2& point_pos, const Vec2& from_pos, float side_len, Color color);
|
||||||
|
|
||||||
void tex();
|
void tex(const TextureRef& texture, const Vec2& position = Vec2::zero, Color color = Color::white);
|
||||||
void tex(const Subtexture& subtexture, const Vec2& pos, Color color);
|
void tex(const TextureRef& texture, const Vec2& position, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||||
|
void tex(const TextureRef& texture, const Rect& clip, const Vec2& position, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||||
|
|
||||||
|
void tex(const Subtexture& subtexture, const Vec2& position = Vec2::zero, Color color = Color::white);
|
||||||
void tex(const Subtexture& subtexture, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
void tex(const Subtexture& subtexture, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||||
|
void tex(const Subtexture& subtexture, const Rect& clip, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||||
|
|
||||||
void str(const SpriteFont& font, const String& text, const Vec2& pos, Color color);
|
void str(const SpriteFont& font, const String& text, const Vec2& pos, Color color);
|
||||||
void str(const SpriteFont& font, const String& text, const Vec2& pos, TextAlign align, float size, Color color);
|
void str(const SpriteFont& font, const String& text, const Vec2& pos, TextAlign align, float size, Color color);
|
||||||
|
@ -161,8 +184,6 @@ namespace Blah
|
||||||
uint8_t mult;
|
uint8_t mult;
|
||||||
uint8_t wash;
|
uint8_t wash;
|
||||||
uint8_t fill;
|
uint8_t fill;
|
||||||
|
|
||||||
static VertexAttribute attributes[6];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawBatch
|
struct DrawBatch
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <blah/drawing/subtexture.h>
|
#include <blah/drawing/subtexture.h>
|
||||||
|
#include <blah/math/calc.h>
|
||||||
|
|
||||||
using namespace Blah;
|
using namespace Blah;
|
||||||
|
|
||||||
|
@ -42,3 +43,22 @@ void Subtexture::update()
|
||||||
tex_coords[3].y = (source.y + source.h) * uvy;
|
tex_coords[3].y = (source.y + source.h) * uvy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Subtexture::crop_info(const Rect& clip, Rect* dest_source, Rect* dest_frame) const
|
||||||
|
{
|
||||||
|
*dest_source = (clip + source.top_left() + frame.top_left()).overlap_rect(source);
|
||||||
|
|
||||||
|
dest_frame->x = Calc::min(0, frame.x + clip.x);
|
||||||
|
dest_frame->y = Calc::min(0, frame.y + clip.y);
|
||||||
|
dest_frame->w = clip.w;
|
||||||
|
dest_frame->h = clip.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subtexture Subtexture::crop(const Rect& clip) const
|
||||||
|
{
|
||||||
|
Subtexture dst;
|
||||||
|
dst.texture = texture;
|
||||||
|
crop_info(clip, &dst.source, &dst.frame);
|
||||||
|
dst.update();
|
||||||
|
return dst;
|
||||||
|
}
|
|
@ -36,5 +36,11 @@ namespace Blah
|
||||||
|
|
||||||
// updates the `draw_coords` and `tex_coords`
|
// updates the `draw_coords` and `tex_coords`
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
// returns resulting source and frame rectangles based on the provided clip rectangle
|
||||||
|
void crop_info(const Rect& clip, Rect* dest_source, Rect* dest_frame) const;
|
||||||
|
|
||||||
|
// returns a subtexture cropped to the provided rectangle
|
||||||
|
Subtexture crop(const Rect& clip) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -62,7 +62,10 @@ TextureRef Graphics::create_texture(int width, int height, TextureFormat format)
|
||||||
BLAH_ASSERT(width > 0 && height > 0, "Texture width and height must be larger than 0");
|
BLAH_ASSERT(width > 0 && height > 0, "Texture width and height must be larger than 0");
|
||||||
BLAH_ASSERT((int)format > (int)TextureFormat::None && (int)format < (int)TextureFormat::Count, "Invalid texture format");
|
BLAH_ASSERT((int)format > (int)TextureFormat::None && (int)format < (int)TextureFormat::Count, "Invalid texture format");
|
||||||
|
|
||||||
|
if (width > 0 && height > 0)
|
||||||
return GraphicsBackend::create_texture(width, height, TextureFilter::Linear, TextureWrap::Repeat, TextureWrap::Repeat, format);
|
return GraphicsBackend::create_texture(width, height, TextureFilter::Linear, TextureWrap::Repeat, TextureWrap::Repeat, format);
|
||||||
|
|
||||||
|
return TextureRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureRef Graphics::create_texture(Stream& stream)
|
TextureRef Graphics::create_texture(Stream& stream)
|
||||||
|
@ -104,10 +107,27 @@ FrameBufferRef Graphics::create_framebuffer(int width, int height, const Texture
|
||||||
BLAH_ASSERT(width > 0 && height > 0, "FrameBuffer width and height must be larger than 0");
|
BLAH_ASSERT(width > 0 && height > 0, "FrameBuffer width and height must be larger than 0");
|
||||||
BLAH_ASSERT(attachment_count <= BLAH_ATTACHMENTS, "Exceeded maximum attachment count");
|
BLAH_ASSERT(attachment_count <= BLAH_ATTACHMENTS, "Exceeded maximum attachment count");
|
||||||
BLAH_ASSERT(attachment_count > 0, "At least one attachment must be provided");
|
BLAH_ASSERT(attachment_count > 0, "At least one attachment must be provided");
|
||||||
|
|
||||||
|
int color_count = 0;
|
||||||
|
int depth_count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < attachment_count; i++)
|
for (int i = 0; i < attachment_count; i++)
|
||||||
|
{
|
||||||
BLAH_ASSERT((int)attachments[i] > (int)TextureFormat::None && (int)attachments[i] < (int)TextureFormat::Count, "Invalid texture format");
|
BLAH_ASSERT((int)attachments[i] > (int)TextureFormat::None && (int)attachments[i] < (int)TextureFormat::Count, "Invalid texture format");
|
||||||
|
|
||||||
|
if (attachments[i] == TextureFormat::DepthStencil)
|
||||||
|
depth_count++;
|
||||||
|
else
|
||||||
|
color_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLAH_ASSERT(depth_count <= 1, "FrameBuffer can only have 1 Depth/Stencil Texture");
|
||||||
|
BLAH_ASSERT(color_count <= BLAH_ATTACHMENTS - 1, "Exceeded maximum Color attachment count");
|
||||||
|
|
||||||
|
if (color_count <= BLAH_ATTACHMENTS - 1 && depth_count <= 1 && width > 0 && height > 0)
|
||||||
return GraphicsBackend::create_framebuffer(width, height, attachments, attachment_count);
|
return GraphicsBackend::create_framebuffer(width, height, attachments, attachment_count);
|
||||||
|
|
||||||
|
return FrameBufferRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderRef Graphics::create_shader(const ShaderData* data)
|
ShaderRef Graphics::create_shader(const ShaderData* data)
|
||||||
|
@ -119,9 +139,10 @@ MaterialRef Graphics::create_material(const ShaderRef& shader)
|
||||||
{
|
{
|
||||||
BLAH_ASSERT(shader, "The provided shader is invalid");
|
BLAH_ASSERT(shader, "The provided shader is invalid");
|
||||||
|
|
||||||
// TODO:
|
if (shader)
|
||||||
// use a pool for Materials?
|
|
||||||
return MaterialRef(new Material(shader));
|
return MaterialRef(new Material(shader));
|
||||||
|
|
||||||
|
return MaterialRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshRef Graphics::create_mesh()
|
MeshRef Graphics::create_mesh()
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
#include <blah/containers/str.h>
|
#include <blah/containers/str.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#define BLAH_ATTACHMENTS 16
|
#define BLAH_ATTACHMENTS 5 // 4 color attachments + 1 depth/stencil
|
||||||
#define BLAH_UNIFORMS 16
|
#define BLAH_UNIFORMS 16 // 16 shader uniforms
|
||||||
#define BLAH_ATTRIBUTES 16
|
#define BLAH_ATTRIBUTES 16 // 16 shader attributes
|
||||||
#define BLAH_ATTRIBUTE_NAME 32
|
#define BLAH_ATTRIBUTE_NAME 32 // max shader attribute name length
|
||||||
#define BLAH_UNIFORM_NAME 32
|
#define BLAH_UNIFORM_NAME 32 // max shader uniform name length
|
||||||
|
|
||||||
namespace Blah
|
namespace Blah
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
using namespace Blah;
|
using namespace Blah;
|
||||||
|
|
||||||
Packer::Packer()
|
Packer::Packer()
|
||||||
: max_size(8192), power_of_two(true), spacing(1), padding(1), dirty(false) { }
|
: max_size(8192), power_of_two(true), spacing(1), padding(1), m_dirty(false) { }
|
||||||
|
|
||||||
Packer::Packer(int max_size, int spacing, bool power_of_two)
|
Packer::Packer(int max_size, int spacing, bool power_of_two)
|
||||||
: max_size(max_size), power_of_two(power_of_two), spacing(spacing), padding(1), dirty(false) { }
|
: max_size(max_size), power_of_two(power_of_two), spacing(spacing), padding(1), m_dirty(false) { }
|
||||||
|
|
||||||
Packer::Packer(Packer&& src) noexcept
|
Packer::Packer(Packer&& src) noexcept
|
||||||
{
|
{
|
||||||
|
@ -17,10 +17,10 @@ Packer::Packer(Packer&& src) noexcept
|
||||||
power_of_two = src.power_of_two;
|
power_of_two = src.power_of_two;
|
||||||
spacing = src.spacing;
|
spacing = src.spacing;
|
||||||
padding = src.padding;
|
padding = src.padding;
|
||||||
dirty = src.dirty;
|
m_dirty = src.m_dirty;
|
||||||
pages = std::move(src.pages);
|
pages = std::move(src.pages);
|
||||||
entries = std::move(src.entries);
|
entries = std::move(src.entries);
|
||||||
buffer = std::move(src.buffer);
|
m_buffer = std::move(src.m_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Packer& Packer::operator=(Packer&& src) noexcept
|
Packer& Packer::operator=(Packer&& src) noexcept
|
||||||
|
@ -29,10 +29,10 @@ Packer& Packer::operator=(Packer&& src) noexcept
|
||||||
power_of_two = src.power_of_two;
|
power_of_two = src.power_of_two;
|
||||||
spacing = src.spacing;
|
spacing = src.spacing;
|
||||||
padding = src.padding;
|
padding = src.padding;
|
||||||
dirty = src.dirty;
|
m_dirty = src.m_dirty;
|
||||||
pages = std::move(src.pages);
|
pages = std::move(src.pages);
|
||||||
entries = std::move(src.entries);
|
entries = std::move(src.entries);
|
||||||
buffer = std::move(src.buffer);
|
m_buffer = std::move(src.m_buffer);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ void Packer::add(uint64_t id, const String& path)
|
||||||
|
|
||||||
void Packer::add_entry(uint64_t id, int w, int h, const Color* pixels)
|
void Packer::add_entry(uint64_t id, int w, int h, const Color* pixels)
|
||||||
{
|
{
|
||||||
dirty = true;
|
m_dirty = true;
|
||||||
|
|
||||||
Entry entry(id, RectI(0, 0, w, h));
|
Entry entry(id, RectI(0, 0, w, h));
|
||||||
|
|
||||||
|
@ -111,17 +111,17 @@ void Packer::add_entry(uint64_t id, int w, int h, const Color* pixels)
|
||||||
entry.packed.h = (bottom - top);
|
entry.packed.h = (bottom - top);
|
||||||
|
|
||||||
// create pixel data
|
// create pixel data
|
||||||
entry.memory_index = buffer.position();
|
entry.memory_index = m_buffer.position();
|
||||||
|
|
||||||
// copy pixels over
|
// copy pixels over
|
||||||
if (entry.packed.w == w && entry.packed.h == h)
|
if (entry.packed.w == w && entry.packed.h == h)
|
||||||
{
|
{
|
||||||
buffer.write((char*)pixels, sizeof(Color) * w * h);
|
m_buffer.write((char*)pixels, sizeof(Color) * w * h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < entry.packed.h; i++)
|
for (int i = 0; i < entry.packed.h; i++)
|
||||||
buffer.write((char*)(pixels + left + (top + i) * entry.frame.w), sizeof(Color) * entry.packed.w);
|
m_buffer.write((char*)(pixels + left + (top + i) * entry.frame.w), sizeof(Color) * entry.packed.w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,10 +130,10 @@ void Packer::add_entry(uint64_t id, int w, int h, const Color* pixels)
|
||||||
|
|
||||||
void Packer::pack()
|
void Packer::pack()
|
||||||
{
|
{
|
||||||
if (!dirty)
|
if (!m_dirty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dirty = false;
|
m_dirty = false;
|
||||||
pages.clear();
|
pages.clear();
|
||||||
|
|
||||||
// only if we have stuff to pack
|
// only if we have stuff to pack
|
||||||
|
@ -266,7 +266,7 @@ void Packer::pack()
|
||||||
if (!sources[i]->empty)
|
if (!sources[i]->empty)
|
||||||
{
|
{
|
||||||
RectI dst = sources[i]->packed;
|
RectI dst = sources[i]->packed;
|
||||||
Color* src = (Color*)(buffer.data() + sources[i]->memory_index);
|
Color* src = (Color*)(m_buffer.data() + sources[i]->memory_index);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// Optimize this?
|
// Optimize this?
|
||||||
|
@ -293,18 +293,18 @@ void Packer::clear()
|
||||||
{
|
{
|
||||||
pages.clear();
|
pages.clear();
|
||||||
entries.clear();
|
entries.clear();
|
||||||
dirty = false;
|
m_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packer::dispose()
|
void Packer::dispose()
|
||||||
{
|
{
|
||||||
pages.clear();
|
pages.clear();
|
||||||
entries.clear();
|
entries.clear();
|
||||||
buffer.close();
|
m_buffer.close();
|
||||||
max_size = 0;
|
max_size = 0;
|
||||||
power_of_two = 0;
|
power_of_two = 0;
|
||||||
spacing = 0;
|
spacing = 0;
|
||||||
dirty = false;
|
m_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packer::Node::Node()
|
Packer::Node::Node()
|
||||||
|
|
|
@ -66,8 +66,8 @@ namespace Blah
|
||||||
Node* Reset(const RectI& rect);
|
Node* Reset(const RectI& rect);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool dirty;
|
bool m_dirty;
|
||||||
BufferStream buffer;
|
BufferStream m_buffer;
|
||||||
|
|
||||||
void add_entry(uint64_t id, int w, int h, const Color* pixels);
|
void add_entry(uint64_t id, int w, int h, const Color* pixels);
|
||||||
};
|
};
|
||||||
|
|
|
@ -162,7 +162,7 @@ Mat3x2 Mat3x2::add(const Mat3x2& a, const Mat3x2& b)
|
||||||
a.m21 + b.m21,
|
a.m21 + b.m21,
|
||||||
a.m22 + b.m22,
|
a.m22 + b.m22,
|
||||||
a.m31 + b.m31,
|
a.m31 + b.m31,
|
||||||
a.m21 + b.m32);
|
a.m32 + b.m32);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat3x2 Mat3x2::subtract(const Mat3x2& a, const Mat3x2& b)
|
Mat3x2 Mat3x2::subtract(const Mat3x2& a, const Mat3x2& b)
|
||||||
|
@ -173,7 +173,7 @@ Mat3x2 Mat3x2::subtract(const Mat3x2& a, const Mat3x2& b)
|
||||||
a.m21 - b.m21,
|
a.m21 - b.m21,
|
||||||
a.m22 - b.m22,
|
a.m22 - b.m22,
|
||||||
a.m31 - b.m31,
|
a.m31 - b.m31,
|
||||||
a.m21 - b.m32);
|
a.m32 - b.m32);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat3x2 Mat3x2::multiply(const Mat3x2& a, const Mat3x2& b)
|
Mat3x2 Mat3x2::multiply(const Mat3x2& a, const Mat3x2& b)
|
||||||
|
|
|
@ -54,10 +54,169 @@ Rect Rect::scale(float sx, float sy)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Line Rect::left_line() const { return Line(left(), top(), left(), bottom()); }
|
float Rect::left() const
|
||||||
Line Rect::right_line() const { return Line(right(), top(), right(), bottom()); }
|
{
|
||||||
Line Rect::top_line() const { return Line(left(), top(), right(), top()); }
|
return x;
|
||||||
Line Rect::bottom_line() const { return Line(left(), bottom(), right(), bottom()); }
|
}
|
||||||
|
|
||||||
|
float Rect::right() const
|
||||||
|
{
|
||||||
|
return x + w;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Rect::top() const
|
||||||
|
{
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Rect::bottom() const
|
||||||
|
{
|
||||||
|
return y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::center() const
|
||||||
|
{
|
||||||
|
return Vec2(x + w / 2, y + h / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Rect::center_x() const
|
||||||
|
{
|
||||||
|
return x + w / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Rect::center_y() const
|
||||||
|
{
|
||||||
|
return y + h / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::top_left() const
|
||||||
|
{
|
||||||
|
return Vec2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::top_right() const
|
||||||
|
{
|
||||||
|
return Vec2(x + w, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::bottom_right() const
|
||||||
|
{
|
||||||
|
return Vec2(x + w, y + h);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::bottom_left() const
|
||||||
|
{
|
||||||
|
return Vec2(x, y + h);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::center_left() const
|
||||||
|
{
|
||||||
|
return Vec2(x, y + h / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::center_right() const
|
||||||
|
{
|
||||||
|
return Vec2(x + w, y + h / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::middle_top() const
|
||||||
|
{
|
||||||
|
return Vec2(x + w / 2, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::middle_bottom() const
|
||||||
|
{
|
||||||
|
return Vec2(x + w / 2, y + h);
|
||||||
|
}
|
||||||
|
|
||||||
|
Line Rect::left_line() const
|
||||||
|
{
|
||||||
|
return Line(left(), top(), left(), bottom());
|
||||||
|
}
|
||||||
|
Line Rect::right_line() const
|
||||||
|
{
|
||||||
|
return Line(right(), top(), right(), bottom());
|
||||||
|
}
|
||||||
|
Line Rect::top_line() const
|
||||||
|
{
|
||||||
|
return Line(left(), top(), right(), top());
|
||||||
|
}
|
||||||
|
Line Rect::bottom_line() const
|
||||||
|
{
|
||||||
|
return Line(left(), bottom(), right(), bottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rect::contains(const Point& pt) const
|
||||||
|
{
|
||||||
|
return pt.x >= x && pt.x < x + w && pt.y >= y && pt.y < y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rect::contains(const Vec2& pt) const
|
||||||
|
{
|
||||||
|
return pt.x >= x && pt.x < x + w && pt.y >= y && pt.y < y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect Rect::overlap_rect(const Rect& against) const
|
||||||
|
{
|
||||||
|
Rect result(0, 0, 0, 0);
|
||||||
|
|
||||||
|
if (x + w >= against.x && x < against.x + against.w)
|
||||||
|
{
|
||||||
|
result.x = Calc::max(x, against.x);
|
||||||
|
result.w = Calc::min(x + w, against.x + against.w) - result.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y + h >= against.y && y < against.y + against.h)
|
||||||
|
{
|
||||||
|
result.y = Calc::max(y, against.y);
|
||||||
|
result.h = Calc::min(y + h, against.y + against.h) - result.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rect::intersects(const Line& line) const
|
||||||
|
{
|
||||||
|
return line.intersects(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rect::intersects(const Line& line, Vec2* out_intersection_point) const
|
||||||
|
{
|
||||||
|
return line.intersects(*this, out_intersection_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rect::intersects(const Vec2& line_from, const Vec2& line_to) const
|
||||||
|
{
|
||||||
|
return intersects(Line(line_from, line_to));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rect::intersects(const Vec2& line_from, const Vec2& line_to, Vec2* out_intersection_point) const
|
||||||
|
{
|
||||||
|
return intersects(Line(line_from, line_to), out_intersection_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::intersection_point(const Line& line) const
|
||||||
|
{
|
||||||
|
Vec2 ret;
|
||||||
|
if (line.intersects(*this, &ret))
|
||||||
|
return ret;
|
||||||
|
else
|
||||||
|
return Vec2::zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 Rect::intersection_point(const Vec2& line_from, const Vec2& line_to) const
|
||||||
|
{
|
||||||
|
Vec2 ret;
|
||||||
|
if (Line(line_from, line_to).intersects(*this, &ret))
|
||||||
|
return ret;
|
||||||
|
else
|
||||||
|
return Vec2::zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect Rect::inflate(float amount) const
|
||||||
|
{
|
||||||
|
return Rect(x - amount, y - amount, w + amount * 2, h + amount * 2);
|
||||||
|
}
|
||||||
|
|
||||||
Rect Rect::operator+(const Vec2& rhs) const { return Rect(x + rhs.x, y + rhs.y, w, h); }
|
Rect Rect::operator+(const Vec2& rhs) const { return Rect(x + rhs.x, y + rhs.y, w, h); }
|
||||||
Rect Rect::operator-(const Vec2& rhs) const { return Rect(x - rhs.x, y - rhs.y, w, h); }
|
Rect Rect::operator-(const Vec2& rhs) const { return Rect(x - rhs.x, y - rhs.y, w, h); }
|
||||||
|
|
|
@ -23,59 +23,45 @@ namespace Blah
|
||||||
Rect scale(float s);
|
Rect scale(float s);
|
||||||
Rect scale(float sx, float sy);
|
Rect scale(float sx, float sy);
|
||||||
|
|
||||||
float left() const { return x; }
|
float left() const;
|
||||||
float right() const { return x + w; }
|
float right() const;
|
||||||
float top() const { return y; }
|
float top() const;
|
||||||
float bottom() const { return y + h; }
|
float bottom() const;
|
||||||
|
|
||||||
Vec2 center() const { return Vec2(x + w / 2, y + h / 2); }
|
Vec2 center() const;
|
||||||
float center_x() const { return x + w / 2; }
|
float center_x() const;
|
||||||
float center_y() const { return y + h / 2; }
|
float center_y() const;
|
||||||
|
|
||||||
Vec2 top_left() const { return Vec2(x, y); }
|
Vec2 top_left() const;
|
||||||
Vec2 top_right() const { return Vec2(x + w, y); }
|
Vec2 top_right() const;
|
||||||
Vec2 bottom_right() const { return Vec2(x + w, y + h); }
|
Vec2 bottom_right() const;
|
||||||
Vec2 bottom_left() const { return Vec2(x, y + h); }
|
Vec2 bottom_left() const;
|
||||||
|
|
||||||
Vec2 center_left() const { return Vec2(x, y + h / 2); }
|
Vec2 center_left() const;
|
||||||
Vec2 center_right() const { return Vec2(x + w, y + h / 2); }
|
Vec2 center_right() const;
|
||||||
Vec2 middle_top() const { return Vec2(x + w / 2, y); }
|
Vec2 middle_top() const;
|
||||||
Vec2 middle_bottom() const { return Vec2(x + w / 2, y + h); }
|
Vec2 middle_bottom() const;
|
||||||
|
|
||||||
Line left_line() const;
|
Line left_line() const;
|
||||||
Line right_line() const;
|
Line right_line() const;
|
||||||
Line top_line() const;
|
Line top_line() const;
|
||||||
Line bottom_line() const;
|
Line bottom_line() const;
|
||||||
|
|
||||||
bool contains(const Point& pt) const { return pt.x >= x && pt.x < x + w && pt.y >= y && pt.y < y + h; }
|
bool contains(const Point& pt) const;
|
||||||
bool contains(const Vec2& pt) const { return pt.x >= x && pt.x < x + w && pt.y >= y && pt.y < y + h; }
|
bool contains(const Vec2& pt) const;
|
||||||
|
|
||||||
bool overlaps(const Rect& rect) const { return x + w >= rect.x && y + h >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h; }
|
bool overlaps(const Rect& rect) const { return x + w >= rect.x && y + h >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h; }
|
||||||
|
Rect overlap_rect(const Rect& other) const;
|
||||||
|
|
||||||
bool intersects(const Line& line) const { return line.intersects(*this); }
|
bool intersects(const Line& line) const;
|
||||||
bool intersects(const Line& line, Vec2* out_intersection_point) const { return line.intersects(*this, out_intersection_point); }
|
bool intersects(const Line& line, Vec2* out_intersection_point) const;
|
||||||
bool intersects(const Vec2& line_from, const Vec2& line_to) const { return intersects(Line(line_from, line_to)); }
|
bool intersects(const Vec2& line_from, const Vec2& line_to) const;
|
||||||
bool intersects(const Vec2& line_from, const Vec2& line_to, Vec2* out_intersection_point) const { return intersects(Line(line_from, line_to), out_intersection_point); }
|
bool intersects(const Vec2& line_from, const Vec2& line_to, Vec2* out_intersection_point) const;
|
||||||
|
|
||||||
Vec2 intersection_point(const Line& line) const
|
Vec2 intersection_point(const Line& line) const;
|
||||||
{
|
Vec2 intersection_point(const Vec2& line_from, const Vec2& line_to) const;
|
||||||
Vec2 ret;
|
|
||||||
if (line.intersects(*this, &ret))
|
|
||||||
return ret;
|
|
||||||
else
|
|
||||||
return Vec2::zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2 intersection_point(const Vec2& line_from, const Vec2& line_to) const
|
Rect inflate(float amount) const;
|
||||||
{
|
|
||||||
Vec2 ret;
|
|
||||||
if (Line(line_from, line_to).intersects(*this, &ret))
|
|
||||||
return ret;
|
|
||||||
else
|
|
||||||
return Vec2::zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect inflate(float amount) const { return Rect(x - amount, y - amount, w + amount * 2, h + amount * 2); }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Rect Sectors:
|
Rect Sectors:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user