diff --git a/include/blah.h b/include/blah.h index 920c3ef..8cd72da 100644 --- a/include/blah.h +++ b/include/blah.h @@ -45,6 +45,7 @@ #include "blah/math/rectI.h" #include "blah/math/stopwatch.h" #include "blah/math/vec2.h" +#include "blah/math/vec3.h" #include "blah/math/vec4.h" #include "blah/streams/bufferstream.h" diff --git a/include/blah/core/app.h b/include/blah/core/app.h index 7256c31..e8dd74b 100644 --- a/include/blah/core/app.h +++ b/include/blah/core/app.h @@ -1,8 +1,13 @@ #pragma once #include +#include +#include namespace Blah { + using AppEventFn = std::function; + using AppLogFn = std::function; + struct Config { const char* name; @@ -11,15 +16,12 @@ namespace Blah int max_updates; int target_framerate; - void (*on_startup)(); - void (*on_shutdown)(); - void (*on_update)(); - void (*on_render)(); - void (*on_exit_request)(); - - void (*on_info)(const char* text); - void (*on_warn)(const char* text); - void (*on_error)(const char* text); + AppEventFn on_startup; + AppEventFn on_shutdown; + AppEventFn on_update; + AppEventFn on_render; + AppEventFn on_exit_request; + AppLogFn on_log; Config(); }; diff --git a/include/blah/core/filesystem.h b/include/blah/core/filesystem.h index 7e3790a..e7a572a 100644 --- a/include/blah/core/filesystem.h +++ b/include/blah/core/filesystem.h @@ -42,7 +42,7 @@ namespace Blah template FilePath join(const FilePath& a, const FilePath& b, const Args&... args) { - return join(a, join(b, args...)); + return join(a, join(b, std::forward(args)...)); } } } \ No newline at end of file diff --git a/include/blah/core/log.h b/include/blah/core/log.h index 7f2fbad..36266dd 100644 --- a/include/blah/core/log.h +++ b/include/blah/core/log.h @@ -1,7 +1,7 @@ #pragma once // error / abort -#ifdef DEBUG +#if defined(DEBUG) || defined(_DEBUG) #include #define BLAH_ERROR(message) \ @@ -23,6 +23,9 @@ #define BLAH_ASSERT(condition, message) \ do { if (!(condition)) { BLAH_ERROR(message); } } while(0) +#define BLAH_ASSERT_FMT(condition, message, ...) \ + do { if (!(condition)) { BLAH_ERROR_FMT(message, __VA_ARGS__); } } while(0) + // maximum length of a print/warn/error message #ifndef BLAH_MESSAGE #define BLAH_MESSAGE 1024 @@ -32,6 +35,13 @@ namespace Blah { namespace Log { + enum class Category + { + Info, + Warning, + Error + }; + void print(const char* info, ...); void warn(const char* info, ...); void error(const char* info, ...); diff --git a/include/blah/graphics/framebuffer.h b/include/blah/graphics/framebuffer.h index a9c7f25..6cad044 100644 --- a/include/blah/graphics/framebuffer.h +++ b/include/blah/graphics/framebuffer.h @@ -14,6 +14,15 @@ namespace Blah class FrameBuffer; typedef std::shared_ptr FrameBufferRef; + enum class ClearMask + { + None = 0, + Color = 1, + Depth = 2, + Stencil = 4, + All = (int)Color | (int)Depth | (int)Stencil + }; + class FrameBuffer { protected: @@ -56,7 +65,7 @@ namespace Blah virtual int height() const = 0; // Clears the FrameBuffer - virtual void clear(Color color) = 0; + virtual void clear(Color color = Color::black, float depth = 1.0f, uint8_t stencil = 0, ClearMask mask = ClearMask::All) = 0; }; } diff --git a/include/blah/math/calc.h b/include/blah/math/calc.h index c897750..252ed39 100644 --- a/include/blah/math/calc.h +++ b/include/blah/math/calc.h @@ -61,6 +61,8 @@ namespace Blah float cos(float x); + float tan(float x); + float atan2(float y, float x); float pow(float x, float n); diff --git a/include/blah/math/mat4x4.h b/include/blah/math/mat4x4.h index eda1029..1cdd5f2 100644 --- a/include/blah/math/mat4x4.h +++ b/include/blah/math/mat4x4.h @@ -1,4 +1,5 @@ #pragma once +#include "vec3.h" namespace Blah { @@ -36,8 +37,11 @@ namespace Blah static Mat4x4 create_ortho(float width, float height, float z_near_plane, float z_far_plane); static Mat4x4 create_ortho_offcenter(float left, float right, float bottom, float top, float z_near_plane, float z_far_plane); + static Mat4x4 create_perspective(float field_of_view, float ratio, float z_near_plane, float z_far_plane); static Mat4x4 create_translation(float x, float y, float z); static Mat4x4 create_scale(float x, float y, float z); + static Mat4x4 create_lookat(Vec3 position, Vec3 target, Vec3 up); + Mat4x4 operator* (const Mat4x4& rhs); }; diff --git a/include/blah/math/rectI.h b/include/blah/math/rectI.h index 2a8bfd5..fb4e10e 100644 --- a/include/blah/math/rectI.h +++ b/include/blah/math/rectI.h @@ -17,12 +17,12 @@ namespace Blah RectI(int rx, int ry, int rw, int rh); RectI(Point pos, Point size); - int left() const { return x; } - int right() const { return x + w; } - int top() const { return y; } - int bottom() const { return y + h; } - int centerX() const { return x + w / 2; } - int centerY() const { return y + h / 2; } + int left() const; + int right() const; + int top() const; + int bottom() const; + int center_x() const; + int center_y() const; Point center() const; Point top_left() const; @@ -30,14 +30,7 @@ namespace Blah Point bottom_left() const; Point bottom_right() const; - bool overlaps(const RectI& other) const - { - return x < other.x + other.w - && other.x < x + w - && y < other.y + other.h - && other.y < y + h; - } - + bool overlaps(const RectI& other) const; bool contains(const Point& pt) const; bool contains(const Vec2& pt) const; @@ -51,14 +44,14 @@ namespace Blah char get_sector(const Point& pt) const; char get_sector(const Vec2& pt) const; - bool operator==(const RectI& rhs) const { return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; } - bool operator!=(const RectI& rhs) const { return !(*this == rhs); } + bool operator==(const RectI& rhs) const; + bool operator!=(const RectI& rhs) const; RectI operator+(const Point& rhs) const; RectI operator-(const Point& rhs) const; + RectI operator*(const int& rhs) const; + RectI operator/(const int& rhs) const; RectI& operator+=(const Point& rhs); RectI& operator-=(const Point& rhs); - - RectI operator*(const int& rhs) const { return RectI(x * rhs, y * rhs, w * rhs, h * rhs); } }; } \ No newline at end of file diff --git a/include/blah/math/vec2.h b/include/blah/math/vec2.h index 4e872b5..1449a2c 100644 --- a/include/blah/math/vec2.h +++ b/include/blah/math/vec2.h @@ -33,39 +33,108 @@ namespace Blah bool operator ==(const Vec2& rhs) const; bool operator !=(const Vec2& rhs) const; - + + // Returns the absolute value of the Vector + Vec2 abs() const; + + // Returns the Normalized Vector + // If the length is 0, the resulting Vector is 0,0 Vec2 normal() const; + + // Rotates the Vector 90 degrees right (y, -x) Vec2 turn_right() const; + + // Rotates the Vector 90 degrees left (-y, x) Vec2 turn_left() const; + + // Returns the length of the Vector float length() const; + + // Returns the squared length of the Vector float length_squared() const; + + // Gets the perpendicular Vector (-y, x) Vec2 perpendicular() const; + + // Gets the angle, in radians, of the Vector float angle() const; + // Calculates the Dot Product between two vectors static float dot(Vec2 a, Vec2 b); + + // Calculates the Dot Product between two vectors static float dot(float x, float y, Vec2 b); + + // Calculates the Dot Product between two vectors static float dot(float x1, float y1, float x2, float y2); + // Transforms a Vector by the given Matrix static Vec2 transform(const Vec2& vec, const Mat3x2& matrix); + + // Transforms a Vector by the given Matrix static Vec2 transform(float x, float y, const Mat3x2& matrix); - static Vec2 from_angle(float radians, float length); - static Vec2 from_angle(float radians); + + // Transforms a Vector Normal by the given Matrix + static Vec2 transform_normal(const Vec2& vec, const Mat3x2& matrix); + + // Transforms a Vector Normal by the given Matrix + static Vec2 transform_normal(float x, float y, const Mat3x2& matrix); + + // Calculates a Vector value from the given radians + static Vec2 from_angle(float radians, float length = 1.0f); + + // Lerps between two Vectors static Vec2 lerp(Vec2 start, Vec2 end, float t); - static Vec2 bezier_lerp(Vec2 start, Vec2 b, Vec2 end, float t); - static Vec2 bezier_lerp(Vec2 start, Vec2 b, Vec2 c, Vec2 end, float t); + + // Lerps between two Vectors along a Bezier curve + static Vec2 lerp_bezier(Vec2 start, Vec2 b, Vec2 end, float t); + + // Lerps between two Vectors along a Bezier curve + static Vec2 lerp_bezier(Vec2 start, Vec2 b, Vec2 c, Vec2 end, float t); + + // Reflects a vector along the given Normal static Vec2 reflect(const Vec2& vector, const Vec2& normal); + // Gets the minimum between two vectors + static Vec2 min(const Vec2& a, const Vec2& b); + + // Gets the maximum between two vectors + static Vec2 max(const Vec2& a, const Vec2& b); + + // (1, 0) static const Vec2 unit_x; + + // (0, 1) static const Vec2 unit_y; + + // (1, 0) static const Vec2 right; + + // (0, -1) static const Vec2 up; + + // (0, 1) static const Vec2 down; + + // (-1, 0) static const Vec2 left; + + // (0, 0) static const Vec2 zero; + + // (1, 1) static const Vec2 one; + + // (0.707, -0.707) static const Vec2 up_right; + + // (-0.707, -0.707) static const Vec2 up_left; + + // (0.707, 0.707) static const Vec2 down_right; + + // (-0.707, 0.707) static const Vec2 down_left; }; diff --git a/include/blah/math/vec3.h b/include/blah/math/vec3.h new file mode 100644 index 0000000..f64cd3c --- /dev/null +++ b/include/blah/math/vec3.h @@ -0,0 +1,56 @@ +#pragma once +#include "calc.h" + +namespace Blah +{ + struct Vec3 + { + float x; + float y; + float z; + + Vec3() + : x(0) + , y(0) + , z(0) + {} + + Vec3(float x, float y, float z) + : x(x) + , y(y) + , z(z) + {} + + inline Vec3 operator +(const Vec3 rhs) const + { + return Vec3(x + rhs.x, y + rhs.y, z + rhs.z); + } + + inline Vec3 operator -(const Vec3 rhs) const + { + return Vec3(x + rhs.x, y + rhs.y, z + rhs.z); + } + + inline Vec3 normal() const + { + float ls = x * x + y * y + z * z; + float length = (float)Calc::sqrt(ls); + return Vec3(x / length, y / length, z / length); + } + + static inline float dot(Vec3 a, Vec3 b) + { + return a.x * b.x + + a.y * b.y + + a.z * b.z; + } + + static inline Vec3 cross(Vec3 a, Vec3 b) + { + return Vec3( + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x); + } + }; +} \ No newline at end of file diff --git a/src/core/app.cpp b/src/core/app.cpp index 384d3c5..5ea0bb3 100644 --- a/src/core/app.cpp +++ b/src/core/app.cpp @@ -27,9 +27,7 @@ Config::Config() on_update = nullptr; on_render = nullptr; on_exit_request = App::exit; - on_info = nullptr; - on_warn = nullptr; - on_error = nullptr; + on_log = nullptr; } namespace @@ -302,9 +300,9 @@ namespace return App::draw_height(); } - virtual void clear(Color color) override + virtual void clear(Color color, float depth, uint8_t stencil, ClearMask mask) override { - GraphicsBackend::clear_backbuffer(color); + GraphicsBackend::clear_backbuffer(color, depth, stencil, mask); } }; diff --git a/src/core/log.cpp b/src/core/log.cpp index 75622d3..6913ec2 100644 --- a/src/core/log.cpp +++ b/src/core/log.cpp @@ -13,9 +13,9 @@ void Log::print(const char* format, ...) vsnprintf(msg, sizeof(char) * BLAH_MESSAGE, format, ap); va_end(ap); - if (App::is_running() && App::config()->on_info != nullptr) + if (App::is_running() && App::config()->on_log) { - App::config()->on_info(msg); + App::config()->on_log(msg, Category::Info); } else { @@ -31,13 +31,13 @@ void Log::warn(const char* format, ...) vsnprintf(msg, sizeof(char) * BLAH_MESSAGE, format, ap); va_end(ap); - if (App::is_running() && App::config()->on_warn != nullptr) + if (App::is_running() && App::config()->on_log) { - App::config()->on_warn(msg); + App::config()->on_log(msg, Category::Warning); } else { - printf("\033[01;33mWARN:\033[0m\t%s\n", msg); + printf("WARN: %s\n", msg); } } @@ -49,12 +49,12 @@ void Log::error(const char* format, ...) vsnprintf(msg, sizeof(char) * BLAH_MESSAGE, format, ap); va_end(ap); - if (App::is_running() && App::config()->on_error != nullptr) + if (App::is_running() && App::config()->on_log) { - App::config()->on_error(msg); + App::config()->on_log(msg, Category::Error); } else { - printf("\033[1;31mERROR:\033[0m\t%s\n", msg); + printf("ERROR: %s\n", msg); } } \ No newline at end of file diff --git a/src/core/time.cpp b/src/core/time.cpp index 92e911c..a61938a 100644 --- a/src/core/time.cpp +++ b/src/core/time.cpp @@ -1,5 +1,4 @@ #include -#include using namespace Blah; @@ -26,7 +25,9 @@ void Time::pause_for(float duration) bool Time::on_interval(double time, float delta, float interval, float offset) { - return floor((time - offset - delta) / interval) < floor((time - offset) / interval); + auto last = static_cast((time - offset - delta) / interval); + auto next = static_cast((time - offset) / interval); + return last < next; } bool Time::on_interval(float delta, float interval, float offset) @@ -39,14 +40,15 @@ bool Time::on_interval(float interval, float offset) return Time::on_interval(Time::seconds, Time::delta, interval, offset); } -bool Time::on_time(double time, double timestamp) +bool Time::on_time(double time, double timestamp) { - return time >= timestamp && time - Time::delta < timestamp; + float c = static_cast(time) - Time::delta; + return time >= timestamp && c < timestamp; } bool Time::between_interval(double time, float interval, float offset) { - return modf(time - offset, interval * 2) >= interval; + return modf(time - offset, ((double)interval) * 2) >= interval; } bool Time::between_interval(float interval, float offset) diff --git a/src/drawing/batch.cpp b/src/drawing/batch.cpp index 6fd527f..cddac61 100644 --- a/src/drawing/batch.cpp +++ b/src/drawing/batch.cpp @@ -507,7 +507,7 @@ void Batch::bezier_line(const Vec2& from, const Vec2& b, const Vec2& to, int ste for (int i = 1; i < steps; i++) { - Vec2 at = Vec2::bezier_lerp(from, b, to, add * i); + Vec2 at = Vec2::lerp_bezier(from, b, to, add * i); line(prev, at, t, color); prev = at; } @@ -522,7 +522,7 @@ void Batch::bezier_line(const Vec2& from, const Vec2& b, const Vec2& c, const Ve for (int i = 1; i < steps; i++) { - Vec2 at = Vec2::bezier_lerp(from, b, c, to, add * i); + Vec2 at = Vec2::lerp_bezier(from, b, c, to, add * i); line(prev, at, t, color); prev = at; } @@ -668,8 +668,8 @@ void Batch::rect_rounded(const Rect& rect, float rtl, int rtl_steps, float rtr, { // get corners Rect tl = Rect(rect.top_left(), Vec2(rtl, rtl)); - Rect tr = Rect(rect.top_right() + Vec2(-rtr, 0), Vec2(rtr, rtr)); - Rect bl = Rect(rect.bottom_left() + Vec2(0, -rbl), Vec2(rbl, rbl)); + Rect tr = Rect(rect.top_right() + Vec2(-rtr, 0.0f), Vec2(rtr, rtr)); + Rect bl = Rect(rect.bottom_left() + Vec2(0.0f, -rbl), Vec2(rbl, rbl)); Rect br = Rect(rect.bottom_right() + Vec2(-rbr, -rbr), Vec2(rbr, rbr)); // rounded corners diff --git a/src/internal/graphics_backend.h b/src/internal/graphics_backend.h index dd69a4e..b388fea 100644 --- a/src/internal/graphics_backend.h +++ b/src/internal/graphics_backend.h @@ -39,7 +39,7 @@ namespace Blah void render(const RenderPass& pass); // Clears the backbuffer - void clear_backbuffer(Color color); + void clear_backbuffer(Color color, float depth, uint8_t stencil, ClearMask mask); // Creates a new Texture. // if the Texture is invalid, this should return an empty reference. diff --git a/src/internal/graphics_backend_d3d11.cpp b/src/internal/graphics_backend_d3d11.cpp index efd5ad1..5a0ad3a 100644 --- a/src/internal/graphics_backend_d3d11.cpp +++ b/src/internal/graphics_backend_d3d11.cpp @@ -25,7 +25,8 @@ namespace Blah ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; IDXGISwapChain* swap_chain = nullptr; - ID3D11RenderTargetView* backbuffer = nullptr; + ID3D11RenderTargetView* backbuffer_view = nullptr; + ID3D11DepthStencilView* backbuffer_depth_view = nullptr; // supported renderer features RendererFeatures features; @@ -120,12 +121,10 @@ namespace Blah desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; - if (is_framebuffer) - desc.BindFlags |= D3D11_BIND_RENDER_TARGET; + bool is_depth_stencil = false; switch (format) { @@ -144,9 +143,18 @@ namespace Blah case TextureFormat::DepthStencil: desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; m_size = width * height * 4; + is_depth_stencil = true; break; } + if (!is_depth_stencil) + desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + else + desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL; + + if (is_framebuffer && !is_depth_stencil) + desc.BindFlags |= D3D11_BIND_RENDER_TARGET; + m_dxgi_format = desc.Format; auto hr = state.device->CreateTexture2D(&desc, NULL, &texture); @@ -158,11 +166,14 @@ namespace Blah return; } - hr = state.device->CreateShaderResourceView(texture, NULL, &view); - if (!SUCCEEDED(hr)) + if (!is_depth_stencil) { - texture->Release(); - texture = nullptr; + hr = state.device->CreateShaderResourceView(texture, NULL, &view); + if (!SUCCEEDED(hr)) + { + texture->Release(); + texture = nullptr; + } } } @@ -219,15 +230,6 @@ namespace Blah { HRESULT hr; - // bounds - D3D11_BOX box; - box.left = 0; - box.right = m_width; - box.top = 0; - box.bottom = m_height; - box.front = 0; - box.back = 1; - // create staging texture if (!staging) { @@ -257,7 +259,7 @@ namespace Blah staging, 0, 0, 0, 0, texture, 0, - &box); + nullptr); // get data D3D11_MAPPED_SUBRESOURCE map; @@ -347,12 +349,27 @@ namespace Blah return m_attachments[0]->height(); } - virtual void clear(Color color) override + virtual void clear(Color color, float depth, uint8_t stencil, ClearMask mask) override { float col[4] = { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f }; - for (int i = 0; i < m_attachments.size(); i++) - state.context->ClearRenderTargetView(color_views[i], col); + if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color) + { + for (int i = 0; i < color_views.size(); i++) + state.context->ClearRenderTargetView(color_views[i], col); + } + + if (depth_view) + { + UINT flags = 0; + if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth) + flags |= D3D11_CLEAR_DEPTH; + if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil) + flags |= D3D11_CLEAR_STENCIL; + + if (flags != 0) + state.context->ClearDepthStencilView(depth_view, flags, depth, stencil); + } } }; @@ -480,9 +497,9 @@ namespace Blah hash = 5381; for (auto& it : attributes) { - for (int i = 0, n = strlen(it.semantic_name); i < n; i++) + for (size_t i = 0, n = strlen(it.semantic_name); i < n; i++) hash = ((hash << 5) + hash) + it.semantic_name[i]; - hash = it.semantic_index << 5 + hash; + hash = (it.semantic_index << 5) + hash; } // Shader is ready for use! @@ -575,7 +592,7 @@ namespace Blah // buffer description D3D11_BUFFER_DESC desc = { 0 }; - desc.ByteWidth = index_stride * m_index_capacity; + desc.ByteWidth = (UINT)(index_stride * m_index_capacity); desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -623,7 +640,7 @@ namespace Blah { // buffer description D3D11_BUFFER_DESC desc = { 0 }; - desc.ByteWidth = format.stride * m_vertex_capacity; + desc.ByteWidth = (UINT)(format.stride * m_vertex_capacity); desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -722,10 +739,13 @@ namespace Blah state.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&frame_buffer); if (frame_buffer) { - state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer); + state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer_view); frame_buffer->Release(); } + // TODO: + // create a depth backbuffer + // Store Features state.features.instancing = true; state.features.max_texture_size = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; @@ -802,8 +822,8 @@ namespace Blah if (state.last_size != next_size) { // release old buffer - if (state.backbuffer) - state.backbuffer->Release(); + if (state.backbuffer_view) + state.backbuffer_view->Release(); // perform resize hr = state.swap_chain->ResizeBuffers(0, next_size.x, next_size.y, DXGI_FORMAT_B8G8R8A8_UNORM, 0); @@ -815,7 +835,7 @@ namespace Blah hr = state.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&frame_buffer); if (SUCCEEDED(hr) && frame_buffer) { - hr = state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer); + hr = state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer_view); BLAH_ASSERT(SUCCEEDED(hr), "Failed to update Backbuffer on Resize"); frame_buffer->Release(); } @@ -870,7 +890,7 @@ namespace Blah // Set the Target if (pass.target == App::backbuffer || !pass.target) { - ctx->OMSetRenderTargets(1, &state.backbuffer, nullptr); + ctx->OMSetRenderTargets(1, &state.backbuffer_view, state.backbuffer_depth_view); } else { @@ -1015,7 +1035,9 @@ namespace Blah { if (mesh->instance_count() <= 0) { - ctx->DrawIndexed(pass.index_count, pass.index_start, 0); + ctx->DrawIndexed( + static_cast(pass.index_count), + static_cast(pass.index_start), 0); } else { @@ -1034,10 +1056,25 @@ namespace Blah } } - void GraphicsBackend::clear_backbuffer(Color color) + void GraphicsBackend::clear_backbuffer(Color color, float depth, uint8_t stencil, ClearMask mask) { - float clear[4] = { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f }; - state.context->ClearRenderTargetView(state.backbuffer, clear); + if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color) + { + float clear[4] = { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f }; + state.context->ClearRenderTargetView(state.backbuffer_view, clear); + } + + if (state.backbuffer_depth_view) + { + UINT flags = 0; + if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth) + flags |= D3D11_CLEAR_DEPTH; + if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil) + flags |= D3D11_CLEAR_STENCIL; + + if (flags != 0) + state.context->ClearDepthStencilView(state.backbuffer_depth_view, flags, depth, stencil); + } } // Utility Methods @@ -1092,7 +1129,7 @@ namespace Blah D3D11_SHADER_DESC shader_desc; reflector->GetDesc(&shader_desc); - for (int i = 0; i < shader_desc.BoundResources; i++) + for (UINT i = 0; i < shader_desc.BoundResources; i++) { D3D11_SHADER_INPUT_BIND_DESC desc; reflector->GetResourceBindingDesc(i, &desc); @@ -1117,7 +1154,7 @@ namespace Blah } } - for (int i = 0; i < shader_desc.ConstantBuffers; i++) + for (UINT i = 0; i < shader_desc.ConstantBuffers; i++) { D3D11_SHADER_BUFFER_DESC desc; @@ -1138,7 +1175,7 @@ namespace Blah } // get the uniforms - for (int j = 0; j < desc.Variables; j++) + for (UINT j = 0; j < desc.Variables; j++) { D3D11_SHADER_VARIABLE_DESC var_desc; D3D11_SHADER_TYPE_DESC type_desc; diff --git a/src/internal/graphics_backend_gl.cpp b/src/internal/graphics_backend_gl.cpp index 3439a06..329cb57 100644 --- a/src/internal/graphics_backend_gl.cpp +++ b/src/internal/graphics_backend_gl.cpp @@ -749,13 +749,24 @@ namespace Blah return m_height; } - virtual void clear(Color color) override + virtual void clear(Color color, float depth, uint8_t stencil, ClearMask mask) override { + int clear = 0; + + if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color) + clear |= GL_COLOR_BUFFER_BIT; + if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth) + clear |= GL_DEPTH_BUFFER_BIT; + if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil) + clear |= GL_STENCIL_BUFFER_BIT; + gl.BindFramebuffer(GL_FRAMEBUFFER, m_id); gl.Disable(GL_SCISSOR_TEST); gl.ColorMask(true, true, true, true); gl.ClearColor(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f); - gl.Clear(GL_COLOR_BUFFER_BIT); + gl.ClearDepth(depth); + gl.ClearStencil(stencil); + gl.Clear(clear); } }; @@ -1485,13 +1496,24 @@ namespace Blah } } - void GraphicsBackend::clear_backbuffer(Color color) + void GraphicsBackend::clear_backbuffer(Color color, float depth, uint8_t stencil, ClearMask mask) { + int clear = 0; + + if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color) + clear |= GL_COLOR_BUFFER_BIT; + if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth) + clear |= GL_DEPTH_BUFFER_BIT; + if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil) + clear |= GL_STENCIL_BUFFER_BIT; + gl.BindFramebuffer(GL_FRAMEBUFFER, 0); gl.Disable(GL_SCISSOR_TEST); gl.ColorMask(true, true, true, true); gl.ClearColor(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f); - gl.Clear(GL_COLOR_BUFFER_BIT); + gl.ClearDepth(depth); + gl.ClearStencil(stencil); + gl.Clear(clear); } } diff --git a/src/internal/platform_backend_sdl2.cpp b/src/internal/platform_backend_sdl2.cpp index f7f75fc..6350233 100644 --- a/src/internal/platform_backend_sdl2.cpp +++ b/src/internal/platform_backend_sdl2.cpp @@ -10,7 +10,6 @@ #include #include -#include #include #if _WIN32 diff --git a/src/math/calc.cpp b/src/math/calc.cpp index e6d734c..67a4b5b 100644 --- a/src/math/calc.cpp +++ b/src/math/calc.cpp @@ -113,6 +113,11 @@ float Calc::cos(float x) return cosf(x); } +float Calc::tan(float x) +{ + return tanf(x); +} + float Calc::atan2(float y, float x) { return atan2f(y, x); diff --git a/src/math/mat4x4.cpp b/src/math/mat4x4.cpp index 313d9f3..3ea3ca0 100644 --- a/src/math/mat4x4.cpp +++ b/src/math/mat4x4.cpp @@ -1,4 +1,5 @@ #include +#include using namespace Blah; @@ -59,6 +60,29 @@ Mat4x4 Mat4x4::create_ortho_offcenter(float left, float right, float bottom, flo return result; } +Mat4x4 Mat4x4::create_perspective(float field_of_view, float ratio, float z_near_plane, float z_far_plane) +{ + float yScale = 1.0f / (float)Calc::tan(field_of_view * 0.5f); + float xScale = yScale / ratio; + + Mat4x4 result; + + result.m11 = xScale; + result.m12 = result.m13 = result.m14 = 0.0f; + + result.m22 = yScale; + result.m21 = result.m23 = result.m24 = 0.0f; + + result.m31 = result.m32 = 0.0f; + result.m33 = z_far_plane / (z_near_plane - z_far_plane); + result.m34 = -1.0f; + + result.m41 = result.m42 = result.m44 = 0.0f; + result.m43 = z_near_plane * z_far_plane / (z_near_plane - z_far_plane); + + return result; +} + Mat4x4 Mat4x4::create_translation(float x, float y, float z) { Mat4x4 result = identity; @@ -81,6 +105,34 @@ Mat4x4 Mat4x4::create_scale(float x, float y, float z) return result; } +Mat4x4 Mat4x4::create_lookat(Vec3 position, Vec3 target, Vec3 up) +{ + Vec3 zaxis = (position - target).normal(); + Vec3 xaxis = Vec3::cross(up, zaxis).normal(); + Vec3 yaxis = Vec3::cross(zaxis, xaxis); + + Mat4x4 result; + + result.m11 = xaxis.x; + result.m12 = yaxis.x; + result.m13 = zaxis.x; + result.m14 = 0.0f; + result.m21 = xaxis.y; + result.m22 = yaxis.y; + result.m23 = zaxis.y; + result.m24 = 0.0f; + result.m31 = xaxis.z; + result.m32 = yaxis.z; + result.m33 = zaxis.z; + result.m34 = 0.0f; + result.m41 = -Vec3::dot(xaxis, position); + result.m42 = -Vec3::dot(yaxis, position); + result.m43 = -Vec3::dot(zaxis, position); + result.m44 = 1.0f; + + return result; +} + Mat4x4 Mat4x4::operator*(const Mat4x4& rhs) { Mat4x4 m; diff --git a/src/math/rectI.cpp b/src/math/rectI.cpp index 18c2456..fd4b28a 100644 --- a/src/math/rectI.cpp +++ b/src/math/rectI.cpp @@ -26,11 +26,68 @@ RectI::RectI(Point pos, Point size) h = size.y; } -Point RectI::center() const { return Point(centerX(), centerY()); } -Point RectI::top_left() const { return Point(left(), top()); } -Point RectI::top_right() const { return Point(right(), top()); } -Point RectI::bottom_left() const { return Point(left(), bottom()); } -Point RectI::bottom_right() const { return Point(right(), bottom()); } +int RectI::left() const +{ + return x; +} + +int RectI::right() const +{ + return x + w; +} + +int RectI::top() const +{ + return y; +} + +int RectI::bottom() const +{ + return y + h; +} + +int RectI::center_x() const +{ + return x + w / 2; +} + +int RectI::center_y() const +{ + return y + h / 2; +} + +Point RectI::center() const +{ + return Point(x + w / 2, y + h / 2); +} + +Point RectI::top_left() const +{ + return Point(x, y); +} + +Point RectI::top_right() const +{ + return Point(x + w, y); +} + +Point RectI::bottom_left() const +{ + return Point(x, y + h); +} + +Point RectI::bottom_right() const +{ + return Point(x + w, y + h); +} + +bool RectI::overlaps(const RectI& other) const +{ + return x < other.x + other.w + && other.x < x + w + && y < other.y + other.h + && other.y < y + h; +} bool RectI::contains(const Point& point) const { @@ -84,7 +141,42 @@ char RectI::get_sector(const Vec2& pt) const return h | v; } -RectI RectI::operator+(const Point& rhs) const { return RectI(x + rhs.x, y + rhs.y, w, h); } -RectI RectI::operator-(const Point& rhs) const { return RectI(x - rhs.x, y - rhs.y, w, h); } -RectI& RectI::operator+=(const Point& rhs) { x += rhs.x; y += rhs.y; return *this; } -RectI& RectI::operator-=(const Point& rhs) { x -= rhs.x; y -= rhs.y; return *this; } \ No newline at end of file +bool RectI::operator==(const RectI& rhs) const +{ + return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; +} + +bool RectI::operator!=(const RectI& rhs) const +{ + return !(*this == rhs); +} + +RectI RectI::operator+(const Point& rhs) const +{ + return RectI(x + rhs.x, y + rhs.y, w, h); +} + +RectI RectI::operator-(const Point& rhs) const +{ + return RectI(x - rhs.x, y - rhs.y, w, h); +} + +RectI RectI::operator*(const int& rhs) const +{ + return RectI(x * rhs, y * rhs, w * rhs, h * rhs); +} + +RectI RectI::operator/(const int& rhs) const +{ + return RectI(x / rhs, y / rhs, w / rhs, h / rhs); +} + +RectI& RectI::operator+=(const Point& rhs) +{ + x += rhs.x; y += rhs.y; return *this; +} + +RectI& RectI::operator-=(const Point& rhs) +{ + x -= rhs.x; y -= rhs.y; return *this; +} diff --git a/src/math/vec2.cpp b/src/math/vec2.cpp index 6ad6c82..dff0d29 100644 --- a/src/math/vec2.cpp +++ b/src/math/vec2.cpp @@ -5,28 +5,100 @@ using namespace Blah; -Vec2::Vec2() { x = y = 0; } -Vec2::Vec2(float vx, float vy) { x = vx; y = vy; } -Vec2::Vec2(int vx, float vy) { x = (float)vx; y = vy; } -Vec2::Vec2(float vx, int vy) { x = vx; y = (float)vy; } -Vec2::Vec2(int vx, int vy) { x = (float)vx; y = (float)vy; } -Vec2::Vec2(Point p) { x = (float)p.x; y = (float)p.y; } +Vec2::Vec2() + : x(0) + , y(0) +{} -Vec2 Vec2::operator +(const Vec2 rhs) const { return Vec2(x + rhs.x, y + rhs.y); } -Vec2 Vec2::operator -(const Vec2 rhs) const { return Vec2(x - rhs.x, y - rhs.y); } -Vec2 Vec2::operator /(const float rhs) const { return Vec2(x / rhs, y / rhs); } -Vec2 Vec2::operator *(const float rhs) const { return Vec2(x * rhs, y * rhs); } -Vec2 Vec2::operator-() const { return Vec2(-x, -y); } +Vec2::Vec2(float vx, float vy) + : x(vx) + , y(vy) +{} -Vec2& Vec2::operator +=(const Vec2& rhs) { x += rhs.x; y += rhs.y; return *this; } -Vec2& Vec2::operator -=(const Vec2& rhs) { x -= rhs.x; y -= rhs.y; return *this; } -Vec2& Vec2::operator /=(const Vec2& rhs) { x /= rhs.x; y /= rhs.y; return *this; } -Vec2& Vec2::operator *=(const Vec2& rhs) { x *= rhs.x; y *= rhs.y; return *this; } -Vec2& Vec2::operator/=(float rhs) { x /= rhs; y /= rhs; return *this; } -Vec2& Vec2::operator*=(float rhs) { x *= rhs; y *= rhs; return *this; } +Vec2::Vec2(int vx, float vy) + : x(static_cast(vx)) + , y(vy) +{} -bool Vec2::operator ==(const Vec2& rhs) const { return x == rhs.x && y == rhs.y; } -bool Vec2::operator !=(const Vec2& rhs) const { return x != rhs.x || y != rhs.y; } +Vec2::Vec2(float vx, int vy) + : x(vx) + , y(static_cast(vy)) +{} + +Vec2::Vec2(int vx, int vy) + : x(static_cast(vx)) + , y(static_cast(vy)) +{} + +Vec2::Vec2(Point p) + : x(static_cast(p.x)) + , y(static_cast(p.y)) +{} + +Vec2 Vec2::operator +(const Vec2 rhs) const +{ + return Vec2(x + rhs.x, y + rhs.y); +} + +Vec2 Vec2::operator -(const Vec2 rhs) const +{ + return Vec2(x - rhs.x, y - rhs.y); +} + +Vec2 Vec2::operator /(const float rhs) const +{ + return Vec2(x / rhs, y / rhs); +} + +Vec2 Vec2::operator *(const float rhs) const +{ + return Vec2(x * rhs, y * rhs); +} + +Vec2 Vec2::operator-() const +{ + return Vec2(-x, -y); +} + +Vec2& Vec2::operator +=(const Vec2& rhs) +{ + x += rhs.x; y += rhs.y; return *this; +} + +Vec2& Vec2::operator -=(const Vec2& rhs) +{ + x -= rhs.x; y -= rhs.y; return *this; +} + +Vec2& Vec2::operator /=(const Vec2& rhs) +{ + x /= rhs.x; y /= rhs.y; return *this; +} + +Vec2& Vec2::operator *=(const Vec2& rhs) +{ + x *= rhs.x; y *= rhs.y; return *this; +} + +Vec2& Vec2::operator/=(float rhs) +{ + x /= rhs; y /= rhs; return *this; +} + +Vec2& Vec2::operator*=(float rhs) +{ + x *= rhs; y *= rhs; return *this; +} + +bool Vec2::operator ==(const Vec2& rhs) const +{ + return x == rhs.x && y == rhs.y; +} + +bool Vec2::operator !=(const Vec2& rhs) const +{ + return x != rhs.x || y != rhs.y; +} Vec2 Vec2::normal() const { @@ -46,8 +118,15 @@ Vec2 Vec2::turn_left() const return Vec2(-y, x); } -float Vec2::length() const { return sqrtf(x * x + y * y); } -float Vec2::length_squared() const { return x * x + y * y; } +float Vec2::length() const +{ + return sqrtf(x * x + y * y); +} + +float Vec2::length_squared() const +{ + return x * x + y * y; +} Vec2 Vec2::perpendicular() const { @@ -59,9 +138,20 @@ float Vec2::angle() const return Calc::atan2(y, x); } -float Vec2::dot(Vec2 a, Vec2 b) { return (a.x * b.x + a.y * b.y); } -float Vec2::dot(float x, float y, Vec2 b) { return (x * b.x + y * b.y); } -float Vec2::dot(float x1, float y1, float x2, float y2) { return (x1 * x2 + y1 * y2); } +float Vec2::dot(Vec2 a, Vec2 b) +{ + return (a.x * b.x + a.y * b.y); +} + +float Vec2::dot(float x, float y, Vec2 b) +{ + return (x * b.x + y * b.y); +} + +float Vec2::dot(float x1, float y1, float x2, float y2) +{ + return (x1 * x2 + y1 * y2); +} Vec2 Vec2::transform(const Vec2& vec, const Mat3x2& matrix) { @@ -77,16 +167,25 @@ Vec2 Vec2::transform(float x, float y, const Mat3x2& matrix) (x * matrix.m12) + (y * matrix.m22) + matrix.m32); } +Vec2 transform_normal(const Vec2& vec, const Mat3x2& matrix) +{ + return Vec2( + vec.x * matrix.m11 + vec.y * matrix.m21, + vec.x * matrix.m12 + vec.y * matrix.m22); +} + +Vec2 transform_normal(float x, float y, const Mat3x2& matrix) +{ + return Vec2( + x * matrix.m11 + y * matrix.m21, + x * matrix.m12 + y * matrix.m22); +} + Vec2 Vec2::from_angle(float radians, float length) { return Vec2((float)cos(radians) * length, (float)sin(radians) * length); } -Vec2 Vec2::from_angle(float radians) -{ - return from_angle(radians, 1); -} - Vec2 Vec2::lerp(Vec2 a, Vec2 b, float t) { if (t == 0) @@ -97,14 +196,14 @@ Vec2 Vec2::lerp(Vec2 a, Vec2 b, float t) return a + (b - a) * t; } -Vec2 Vec2::bezier_lerp(Vec2 start, Vec2 b, Vec2 end, float t) +Vec2 Vec2::lerp_bezier(Vec2 start, Vec2 b, Vec2 end, float t) { return lerp(lerp(start, b, t), lerp(b, end, t), t); } -Vec2 Vec2::bezier_lerp(Vec2 start, Vec2 b, Vec2 c, Vec2 end, float t) +Vec2 Vec2::lerp_bezier(Vec2 start, Vec2 b, Vec2 c, Vec2 end, float t) { - return bezier_lerp(lerp(start, b, t), lerp(b, c, t), lerp(c, end, t), t); + return lerp_bezier(lerp(start, b, t), lerp(b, c, t), lerp(c, end, t), t); } Vec2 Vec2::reflect(const Vec2& vector, const Vec2& normal) @@ -116,6 +215,20 @@ Vec2 Vec2::reflect(const Vec2& vector, const Vec2& normal) vector.y - 2.0f * dot * normal.y); } +Vec2 Vec2::min(const Vec2& a, const Vec2& b) +{ + return Vec2( + a.x < b.x ? a.x : b.x, + a.y < b.y ? a.y : b.y); +} + +Vec2 Vec2::max(const Vec2& a, const Vec2& b) +{ + return Vec2( + a.x > b.x ? a.x : b.x, + a.y > b.y ? a.y : b.y); +} + const Vec2 Vec2::unit_x = Vec2(1, 0); const Vec2 Vec2::unit_y = Vec2(0, 1); const Vec2 Vec2::right = Vec2(1, 0);