diff --git a/include/blah/graphics/batch.h b/include/blah/graphics/batch.h index 050f06e..b258352 100644 --- a/include/blah/graphics/batch.h +++ b/include/blah/graphics/batch.h @@ -46,9 +46,9 @@ namespace Blah public: // The name of the default uniforms to set - const char* texture_uniform; - const char* sampler_uniform; - const char* matrix_uniform; + String texture_uniform = "u_texture"; + String sampler_uniform = "u_texture_sampler"; + String matrix_uniform = "u_matrix"; // Snaps all drawing coordinates to integer values // This is useful for drawing Pixel Art stuff @@ -57,11 +57,6 @@ namespace Blah // Default Sampler, set on clear TextureSampler default_sampler; - Batch(); - Batch(const Batch& other) = delete; - Batch& operator=(const Batch& other) = delete; - ~Batch(); - // 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. void push_matrix(const Mat3x2f& matrix, bool absolute = false); @@ -199,8 +194,6 @@ namespace Blah u8 wash; u8 fill; u8 pad; - - Vertex() = default; }; struct DrawBatch @@ -224,13 +217,12 @@ namespace Blah scissor(0, 0, -1, -1) {} }; - static ShaderRef m_default_shader; MaterialRef m_default_material; MeshRef m_mesh; - Mat3x2f m_matrix; - ColorMode m_color_mode; - u8 m_tex_mult; - u8 m_tex_wash; + Mat3x2f m_matrix = Mat3x2f::identity; + ColorMode m_color_mode = ColorMode::Normal; + u8 m_tex_mult = 255; + u8 m_tex_wash = 0; DrawBatch m_batch; Vector m_vertices; Vector m_indices; @@ -241,7 +233,7 @@ namespace Blah Vector m_color_mode_stack; Vector m_layer_stack; Vector m_batches; - int m_batch_insert; + int m_batch_insert = 0; void render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4x4f& matrix); }; diff --git a/include/blah/time.h b/include/blah/time.h index 6e9bcee..1ac8d76 100644 --- a/include/blah/time.h +++ b/include/blah/time.h @@ -3,49 +3,49 @@ namespace Blah { - struct Time + namespace Time { // ticks per second (microseconds, in this case) - static constexpr u64 ticks_per_second = 1000000; + constexpr u64 ticks_per_second = 1000000; // uptime, in ticks - static u64 ticks; + extern u64 ticks; // uptime, in seconds - static double seconds; + extern double seconds; // previous frame uptime, in ticks - static u64 previous_ticks; + extern u64 previous_ticks; // previous frame uptime, in seconds - static double previous_seconds; + extern double previous_seconds; // delta time from last frame - static float delta; + extern float delta; // time the application should pause for - static float pause_timer; + extern float pause_timer; // pauses the entire application for the given time - static void pause_for(float duration); + void pause_for(float duration); // returns true on the given time interval - static bool on_interval(double time, float delta, float interval, float offset); + bool on_interval(double time, float delta, float interval, float offset); // returns true on the given time interval - static bool on_interval(float delta, float interval, float offset); + bool on_interval(float delta, float interval, float offset); // returns true on the given time interval - static bool on_interval(float interval, float offset = 0); + bool on_interval(float interval, float offset = 0); // returns true when the given timestamp is passed - static bool on_time(double time, double timestamp); + bool on_time(double time, double timestamp); // returns true between time intervals - static bool between_interval(double time, float interval, float offset); + bool between_interval(double time, float interval, float offset); // returns true between time intervals - static bool between_interval(float interval, float offset = 0); + bool between_interval(float interval, float offset = 0); }; class Stopwatch diff --git a/src/app.cpp b/src/app.cpp index dbec180..4838b4b 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -17,51 +17,11 @@ using namespace Blah; namespace { - // A dummy Frame Buffer that represents the Back Buffer - // it doesn't actually contain any textures or details. - class BackBuffer final : public Target - { - Attachments empty_textures; - - Attachments& textures() override - { - BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); - return empty_textures; - } - - const Attachments& textures() const override - { - BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); - return empty_textures; - } - - int width() const override - { - int w, h; - Platform::get_draw_size(&w, &h); - return w; - } - - int height() const override - { - int w, h; - Platform::get_draw_size(&w, &h); - return h; - } - - void clear(Color color, float depth, u8 stencil, ClearMask mask) override - { - if (Renderer::instance) - Renderer::instance->clear_backbuffer(color, depth, stencil, mask); - } - }; - Config app_config; bool app_is_running = false; bool app_is_exiting = false; u64 app_time_last; u64 app_time_accumulator = 0; - TargetRef app_backbuffer; void app_iterate() { @@ -135,6 +95,25 @@ namespace } } + // A dummy Frame Buffer that represents the Back Buffer + // it doesn't actually contain any textures or details. + class BackBuffer final : public Target + { + public: + Attachments empty_textures; + Attachments& textures() override { BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); return empty_textures; } + const Attachments& textures() const override { BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); return empty_textures; } + int width() const override { int w, h; Platform::get_draw_size(&w, &h); return w; } + int height() const override { int w, h; Platform::get_draw_size(&w, &h); return h; } + void clear(Color color, float depth, u8 stencil, ClearMask mask) override + { + BLAH_ASSERT_RENDERER(); + if (Renderer::instance) Renderer::instance->clear_backbuffer(color, depth, stencil, mask); + } + }; + + BackBuffer app_backbuffer; + TargetRef app_backbuffer_ref = TargetRef(&app_backbuffer); } bool App::run(const Config* c) @@ -160,7 +139,6 @@ bool App::run(const Config* c) // default values app_is_running = true; app_is_exiting = false; - app_backbuffer = TargetRef(new BackBuffer()); // initialize the system if (!Platform::init(app_config)) @@ -223,13 +201,12 @@ bool App::run(const Config* c) Renderer::instance->shutdown(); Platform::shutdown(); + delete Renderer::instance; + Renderer::instance = nullptr; + // clear static state app_is_running = false; app_is_exiting = false; - app_backbuffer = nullptr; - - delete Renderer::instance; - Renderer::instance = nullptr; Time::ticks = 0; Time::seconds = 0; @@ -308,8 +285,8 @@ void App::set_size(Point point) Point App::get_backbuffer_size() { BLAH_ASSERT_RUNNING(); - if (app_backbuffer) - return Point(app_backbuffer->width(), app_backbuffer->height()); + if (Renderer::instance) + return Point(app_backbuffer.width(), app_backbuffer.height()); return Point(0, 0); } @@ -341,7 +318,7 @@ const RendererFeatures& App::renderer() const TargetRef& App::backbuffer() { BLAH_ASSERT_RUNNING(); - return app_backbuffer; + return app_backbuffer_ref; } void System::open_url(const char* url) diff --git a/src/graphics/batch.cpp b/src/graphics/batch.cpp index 38c887e..5ce9abf 100644 --- a/src/graphics/batch.cpp +++ b/src/graphics/batch.cpp @@ -6,117 +6,13 @@ #include #include #include +#include "../internal/renderer.h" #include using namespace Blah; + namespace { - - // TODO: - // This shader needs to be graphics API agnostic - - const ShaderData opengl_shader_data = { - // vertex shader -#ifdef __EMSCRIPTEN__ - "#version 300 es\n" -#else - "#version 330\n" -#endif - "uniform mat4 u_matrix;\n" - "layout(location=0) in vec2 a_position;\n" - "layout(location=1) in vec2 a_tex;\n" - "layout(location=2) in vec4 a_color;\n" - "layout(location=3) in vec4 a_type;\n" - "out vec2 v_tex;\n" - "out vec4 v_col;\n" - "out vec4 v_type;\n" - "void main(void)\n" - "{\n" - " gl_Position = u_matrix * vec4(a_position.xy, 0, 1);\n" - " v_tex = a_tex;\n" - " v_col = a_color;\n" - " v_type = a_type;\n" - "}", - - // fragment shader -#ifdef __EMSCRIPTEN__ - "#version 300 es\n" - "precision mediump float;\n" -#else - "#version 330\n" -#endif - "uniform sampler2D u_texture;\n" - "in vec2 v_tex;\n" - "in vec4 v_col;\n" - "in vec4 v_type;\n" - "out vec4 o_color;\n" - "void main(void)\n" - "{\n" - " vec4 color = texture(u_texture, v_tex);\n" - " o_color = \n" - " v_type.x * color * v_col + \n" - " v_type.y * color.a * v_col + \n" - " v_type.z * v_col;\n" - "}" - }; - - const char* d3d11_shader = "" - "cbuffer constants : register(b0)\n" - "{\n" - " row_major float4x4 u_matrix;\n" - "}\n" - - "struct vs_in\n" - "{\n" - " float2 position : POS;\n" - " float2 texcoord : TEX;\n" - " float4 color : COL;\n" - " float4 mask : MASK;\n" - "};\n" - - "struct vs_out\n" - "{\n" - " float4 position : SV_POSITION;\n" - " float2 texcoord : TEX;\n" - " float4 color : COL;\n" - " float4 mask : MASK;\n" - "};\n" - - "Texture2D u_texture : register(t0);\n" - "SamplerState u_texture_sampler : register(s0);\n" - - "vs_out vs_main(vs_in input)\n" - "{\n" - " vs_out output;\n" - - " output.position = mul(float4(input.position, 0.0f, 1.0f), u_matrix);\n" - " output.texcoord = input.texcoord;\n" - " output.color = input.color;\n" - " output.mask = input.mask;\n" - - " return output;\n" - "}\n" - - "float4 ps_main(vs_out input) : SV_TARGET\n" - "{\n" - " float4 color = u_texture.Sample(u_texture_sampler, input.texcoord);\n" - " return\n" - " input.mask.x * color * input.color + \n" - " input.mask.y * color.a * input.color + \n" - " input.mask.z * input.color;\n" - "}\n"; - - const ShaderData d3d11_shader_data = { - d3d11_shader, - d3d11_shader, - { - { "POS", 0 }, - { "TEX", 0 }, - { "COL", 0 }, - { "MASK", 0 }, - } - }; - const VertexFormat format = VertexFormat( { { 0, VertexType::Float2, false }, @@ -124,11 +20,8 @@ namespace { 2, VertexType::UByte4, true }, { 3, VertexType::UByte4, true }, }); -} -namespace -{ - static Vec2f batch_shape_intersection(const Vec2f& p0, const Vec2f& p1, const Vec2f& q0, const Vec2f& q1) + Vec2f batch_shape_intersection(const Vec2f& p0, const Vec2f& p1, const Vec2f& q0, const Vec2f& q1) { const auto aa = p1 - p0; const auto bb = q0 - q1; @@ -208,21 +101,6 @@ do { \ INSERT_BATCH(); \ m_batch.variable = variable; -ShaderRef Batch::m_default_shader; - -Batch::Batch() -{ - texture_uniform = "u_texture"; - sampler_uniform = "u_texture_sampler"; - matrix_uniform = "u_matrix"; - clear(); -} - -Batch::~Batch() -{ - dispose(); -} - void Batch::push_matrix(const Mat3x2f& matrix, bool absolute) { m_matrix_stack.push_back(m_matrix); @@ -407,16 +285,11 @@ void Batch::render(const TargetRef& target, const Mat4x4f& matrix) if (!m_mesh) m_mesh = Mesh::create(); - if (!m_default_shader) - { - if (App::renderer().type == RendererType::OpenGL) - m_default_shader = Shader::create(opengl_shader_data); - else if (App::renderer().type == RendererType::D3D11) - m_default_shader = Shader::create(d3d11_shader_data); - } - if (!m_default_material) - m_default_material = Material::create(m_default_shader); + { + BLAH_ASSERT_RENDERER(); + m_default_material = Material::create(Renderer::instance->default_batcher_shader); + } } // upload data diff --git a/src/internal/platform_win32.cpp b/src/internal/platform_win32.cpp index e5f144c..2f5e6b9 100644 --- a/src/internal/platform_win32.cpp +++ b/src/internal/platform_win32.cpp @@ -72,7 +72,7 @@ namespace Blah wglDeleteContext_fn delete_context; wglMakeCurrent_fn make_current; } gl; - }; + } g_platform; // Win32 File Class class Win32File : public File @@ -187,8 +187,6 @@ namespace Blah using namespace Blah; namespace fs = std::filesystem; -static Blah::Win32Platform g_platform; - bool Platform::init(const Config& config) { // clear platform diff --git a/src/internal/renderer.h b/src/internal/renderer.h index 205fb19..31865eb 100644 --- a/src/internal/renderer.h +++ b/src/internal/renderer.h @@ -22,6 +22,9 @@ namespace Blah // Renderer Features RendererFeatures features; + // Default Shader for the Batcher + ShaderRef default_batcher_shader; + virtual ~Renderer() = default; // Initialize the Graphics diff --git a/src/internal/renderer_d3d11.cpp b/src/internal/renderer_d3d11.cpp index 7bebbc1..341853c 100644 --- a/src/internal/renderer_d3d11.cpp +++ b/src/internal/renderer_d3d11.cpp @@ -20,6 +20,63 @@ namespace Blah { + const char* d3d11_batch_shader = "" + "cbuffer constants : register(b0)\n" + "{\n" + " row_major float4x4 u_matrix;\n" + "}\n" + + "struct vs_in\n" + "{\n" + " float2 position : POS;\n" + " float2 texcoord : TEX;\n" + " float4 color : COL;\n" + " float4 mask : MASK;\n" + "};\n" + + "struct vs_out\n" + "{\n" + " float4 position : SV_POSITION;\n" + " float2 texcoord : TEX;\n" + " float4 color : COL;\n" + " float4 mask : MASK;\n" + "};\n" + + "Texture2D u_texture : register(t0);\n" + "SamplerState u_texture_sampler : register(s0);\n" + + "vs_out vs_main(vs_in input)\n" + "{\n" + " vs_out output;\n" + + " output.position = mul(float4(input.position, 0.0f, 1.0f), u_matrix);\n" + " output.texcoord = input.texcoord;\n" + " output.color = input.color;\n" + " output.mask = input.mask;\n" + + " return output;\n" + "}\n" + + "float4 ps_main(vs_out input) : SV_TARGET\n" + "{\n" + " float4 color = u_texture.Sample(u_texture_sampler, input.texcoord);\n" + " return\n" + " input.mask.x * color * input.color + \n" + " input.mask.y * color.a * input.color + \n" + " input.mask.z * input.color;\n" + "}\n"; + + const ShaderData d3d11_batch_shader_data = { + d3d11_batch_shader, + d3d11_batch_shader, + { + { "POS", 0 }, + { "TEX", 0 }, + { "COL", 0 }, + { "MASK", 0 }, + } + }; + class D3D11_Shader; class Renderer_D3D11 : public Renderer @@ -787,6 +844,9 @@ namespace Blah } } + // create default sprite batch shader + default_batcher_shader = Shader::create(d3d11_batch_shader_data); + return true; } diff --git a/src/internal/renderer_opengl.cpp b/src/internal/renderer_opengl.cpp index 1390eab..16d48ed 100644 --- a/src/internal/renderer_opengl.cpp +++ b/src/internal/renderer_opengl.cpp @@ -343,6 +343,51 @@ typedef void (APIENTRY* DEBUGPROC)(GLenum source, namespace Blah { + const ShaderData opengl_batch_shader_data = { + // vertex shader +#ifdef __EMSCRIPTEN__ + "#version 300 es\n" +#else + "#version 330\n" +#endif + "uniform mat4 u_matrix;\n" + "layout(location=0) in vec2 a_position;\n" + "layout(location=1) in vec2 a_tex;\n" + "layout(location=2) in vec4 a_color;\n" + "layout(location=3) in vec4 a_type;\n" + "out vec2 v_tex;\n" + "out vec4 v_col;\n" + "out vec4 v_type;\n" + "void main(void)\n" + "{\n" + " gl_Position = u_matrix * vec4(a_position.xy, 0, 1);\n" + " v_tex = a_tex;\n" + " v_col = a_color;\n" + " v_type = a_type;\n" + "}", + + // fragment shader +#ifdef __EMSCRIPTEN__ + "#version 300 es\n" + "precision mediump float;\n" +#else + "#version 330\n" +#endif + "uniform sampler2D u_texture;\n" + "in vec2 v_tex;\n" + "in vec4 v_col;\n" + "in vec4 v_type;\n" + "out vec4 o_color;\n" + "void main(void)\n" + "{\n" + " vec4 color = texture(u_texture, v_tex);\n" + " o_color = \n" + " v_type.x * color * v_col + \n" + " v_type.y * color.a * v_col + \n" + " v_type.z * v_col;\n" + "}" + }; + class Renderer_OpenGL : public Renderer { public: @@ -1158,6 +1203,9 @@ namespace Blah features.origin_bottom_left = true; features.max_texture_size = max_texture_size; + // create the default batch shader + default_batcher_shader = Shader::create(opengl_batch_shader_data); + return true; }