@@ -21,7 +21,7 @@ endif() | |||
add_compile_options(-std=c++2a -Wall -Wextra -Wpedantic -Wno-unused-parameter) | |||
set(libraries | |||
third-party imgui fmt cpptoml msgpack | |||
cygnet third-party imgui fmt cpptoml msgpack | |||
SDL2 SDL2_image dl z) | |||
if(CMAKE_BUILD_TYPE STREQUAL Sanitize OR CMAKE_BUILD_TYPE STREQUAL "") |
@@ -16,9 +16,11 @@ public: | |||
void makeCurrent(); | |||
void clear(); | |||
void clear(float r, float g, float b, float a); | |||
void flip(); | |||
int width() { return w_; } | |||
int height() { return h_; } | |||
SDL_Window *sdl() { return win_.get(); } | |||
// xScale and yScale are what drawn objects need to be scaled with | |||
// in order to have square pixels. |
@@ -75,6 +75,7 @@ public: | |||
void draw(State &state) override { | |||
state.q.show(image_.texture(), x_, y_); | |||
state.q.show(image_.texture(), x_ + 1, y_ + 1, -1, 1); | |||
} | |||
private: |
@@ -40,7 +40,11 @@ void Window::makeCurrent() { | |||
} | |||
void Window::clear() { | |||
//glClearColor(0, 0, 0, 1); | |||
glClear(GL_COLOR_BUFFER_BIT); | |||
} | |||
void Window::clear(float r, float g, float b, float a) { | |||
glClearColor(r, g, b, a); | |||
glClear(GL_COLOR_BUFFER_BIT); | |||
} | |||
@@ -4,42 +4,30 @@ | |||
#include "common.h" | |||
#include <SDL2/SDL.h> | |||
#include <cygnet/Window.h> | |||
#include <cygnet/RenderQueue.h> | |||
#include <optional> | |||
namespace Swan { | |||
class Win { | |||
public: | |||
Win(SDL_Window *window, SDL_Renderer *renderer, float scale): | |||
window_(window), renderer_(renderer), scale_(scale) { | |||
if (SDL_GetRendererInfo(renderer_, &rinfo_) < 0) { | |||
panic << "GetRenedrerInfo failed: " << SDL_GetError(); | |||
abort(); | |||
} | |||
// For HiDPI, we must set the renderer's logical size. | |||
int w, h; | |||
SDL_GetWindowSize(window_, &w, &h); | |||
onResize(w, h); | |||
info << "Using renderer: " << rinfo_.name; | |||
Win(Cygnet::Window &window, Cygnet::RenderQueue &queue, float scale): | |||
window_(window), queue_(queue), scale_(scale) { | |||
} | |||
Vec2 getPixSize() { | |||
int w, h; | |||
SDL_GetWindowSize(window_, &w, &h); | |||
return Vec2((float)w / scale_, (float)h / scale_); | |||
return Vec2((float)window_.width() / scale_, (float)window_.height() / scale_); | |||
} | |||
Vec2 getSize() { | |||
int w, h; | |||
SDL_GetWindowSize(window_, &w, &h); | |||
return Vec2(((float)w / (scale_ * zoom_)) / TILE_SIZE, ((float)h / (scale_ * zoom_)) / TILE_SIZE); | |||
return Vec2( | |||
((float)window_.width() / (scale_ * zoom_)) / TILE_SIZE, | |||
((float)window_.height() / (scale_ * zoom_)) / TILE_SIZE); | |||
} | |||
void onResize(int w, int h) { | |||
SDL_RenderSetLogicalSize(renderer_, (int)((float)w / scale_), (int)((float)h / scale_)); | |||
window_.onResize(w, h); | |||
} | |||
SDL_Rect createDestRect(Vec2 pos, Vec2 pixsize) { | |||
@@ -62,32 +50,40 @@ public: | |||
const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect, | |||
ShowTextureArgs args) { | |||
/* | |||
SDL_Point *center = args.center ? &*args.center : nullptr; | |||
SDL_Rect destrect = createDestRect(pos, Vec2(srcrect->w * args.hscale, srcrect->h * args.hscale)); | |||
if (SDL_RenderCopyEx(renderer_, tex, srcrect, &destrect, args.angle, center, args.flip) < 0) | |||
warn << "RenderCopyEx failed: " << SDL_GetError(); | |||
*/ | |||
warn << "Need to implement showTexture"; | |||
} | |||
// We want an overload which uses RenderCopy instead of RenderCopyEx, | |||
// because RenderCopy might be faster | |||
void showTexture(const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect) { | |||
/* | |||
SDL_Rect destrect = createDestRect(pos, Vec2(srcrect->w, srcrect->h)); | |||
if (SDL_RenderCopy(renderer_, tex, srcrect, &destrect) < 0) | |||
warn << "RenderCopy failed: " << SDL_GetError(); | |||
*/ | |||
warn << "Need to implement showTexture"; | |||
} | |||
void drawRect(const Vec2 &pos, const Vec2 &size) { | |||
/* | |||
SDL_Rect destrect = createDestRect(pos, size * TILE_SIZE); | |||
if (SDL_RenderDrawRect(renderer_, &destrect) < 0) | |||
warn << "RenderDrawRect failed: " << SDL_GetError(); | |||
*/ | |||
warn << "Need to implement drawRect"; | |||
} | |||
Vec2 cam_; | |||
float zoom_ = 1; | |||
SDL_Window *window_; | |||
SDL_Renderer *renderer_; | |||
Cygnet::Window &window_; | |||
Cygnet::RenderQueue &queue_; | |||
float scale_; | |||
SDL_RendererInfo rinfo_; | |||
}; | |||
} |
@@ -6,6 +6,7 @@ | |||
#include <utility> | |||
#include "Win.h" | |||
#include "cygnet/GlWrappers.h" | |||
namespace Swan { | |||
namespace Draw { | |||
@@ -14,7 +15,7 @@ SDL_Color linearGradient( | |||
float val, std::initializer_list<std::pair<float, SDL_Color>> colors); | |||
void parallaxBackground( | |||
Win &win, SDL_Texture *tex, | |||
Win &win, Cygnet::GlTexture &tex, | |||
std::optional<SDL_Rect> srcrect, std::optional<SDL_Rect> destrect, | |||
float x, float y, float factor); | |||
@@ -45,20 +45,18 @@ SDL_Color linearGradient( | |||
} | |||
void parallaxBackground( | |||
Win &win, SDL_Texture *tex, | |||
Win &win, Cygnet::GlTexture &tex, | |||
std::optional<SDL_Rect> srcrect, std::optional<SDL_Rect> destrect, | |||
float x, float y, float factor) { | |||
/* | |||
SDL_Renderer *rnd = win.renderer_; | |||
// We only need to set a clip rect if we have a destrect | |||
std::optional<RenderClipRect> clip; | |||
if (!srcrect) { | |||
Uint32 fmt; | |||
int access, w, h; | |||
SDL_QueryTexture(tex, &fmt, &access, &w, &h); | |||
srcrect = SDL_Rect{ 0, 0, w, h }; | |||
srcrect = SDL_Rect{ 0, 0, tex.width(), tex.height() }; | |||
} | |||
if (destrect) { | |||
@@ -91,6 +89,8 @@ void parallaxBackground( | |||
SDL_RenderCopy(rnd, tex, &*srcrect, &r); | |||
} | |||
} | |||
*/ | |||
} | |||
} |
@@ -5,14 +5,36 @@ | |||
#include <chrono> | |||
#include <ratio> | |||
#include <cygnet/Window.h> | |||
#include <SDL2/SDL.h> | |||
#include <SDL2/SDL_image.h> | |||
#include <string.h> | |||
#include <imgui.h> | |||
#include <imgui_sdl/imgui_sdl.h> | |||
#include <cygnet/Window.h> | |||
#include <swan/swan.h> | |||
const char *vertexShader = R"( | |||
uniform mat3 transform; | |||
attribute vec2 position; | |||
attribute vec2 texCoord; | |||
varying vec2 v_texCoord; | |||
void main() { | |||
vec3 pos = transform * vec3(position, 0); | |||
gl_Position = vec4(pos.x, pos.y, 0, 1); | |||
v_texCoord = texCoord; | |||
} | |||
)"; | |||
const char *fragmentShader = R"( | |||
precision mediump float; | |||
varying vec2 v_texCoord; | |||
uniform sampler2D tex; | |||
void main() { | |||
gl_FragColor = texture2D(tex, v_texCoord); | |||
} | |||
)"; | |||
using namespace Swan; | |||
#define errassert(expr, str, errfn) do { \ | |||
@@ -75,33 +97,26 @@ int main(int argc, char **argv) { | |||
imgassert(IMG_Init(imgflags) == imgflags, "Could not initialize SDL_Image"); | |||
Deferred<IMG_Quit> sdl_image; | |||
// Create the window | |||
CPtr<SDL_Window, SDL_DestroyWindow> window( | |||
SDL_CreateWindow( | |||
"Project: SWAN", | |||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, | |||
(int)(640 * gui_scale), (int)(480 * gui_scale), winflags)); | |||
Cygnet::Window window("Project: SWAN", (int)(640 * gui_scale), (int)(480 * gui_scale)); | |||
Cygnet::GlProgram program( | |||
Cygnet::GlShader(Cygnet::GlShader::Type::VERTEX, vertexShader), | |||
Cygnet::GlShader(Cygnet::GlShader::Type::FRAGMENT, fragmentShader)); | |||
program.use(); | |||
Cygnet::RenderQueue mainQueue(program, 1.0/TILE_SIZE); | |||
// Load and display application icon | |||
CPtr<SDL_Surface, SDL_FreeSurface> icon( | |||
IMG_Load("assets/icon.png")); | |||
sdlassert(icon, "Could not load icon"); | |||
SDL_SetWindowIcon(window.get(), icon.get()); | |||
CPtr<SDL_Renderer, SDL_DestroyRenderer> renderer( | |||
SDL_CreateRenderer(window.get(), -1, renderflags)); | |||
sdlassert(renderer, "Could not create renderer"); | |||
SDL_SetRenderDrawBlendMode(renderer.get(), SDL_BLENDMODE_BLEND); | |||
SDL_SetRenderDrawColor(renderer.get(), 0, 0, 0, 255); | |||
SDL_SetWindowIcon(window.sdl(), icon.get()); | |||
Win win(window.get(), renderer.get(), gui_scale); | |||
Win win(window, mainQueue, gui_scale); | |||
// Init ImGUI and ImGUI_SDL | |||
IMGUI_CHECKVERSION(); | |||
CPtr<ImGuiContext, ImGui::DestroyContext> context( | |||
ImGui::CreateContext()); | |||
ImGuiSDL::Initialize(renderer.get(), (int)win.getPixSize().x, (int)win.getPixSize().y); | |||
Deferred<ImGuiSDL::Deinitialize> imgui_sdl; | |||
info << "Initialized with window size " << win.getPixSize(); | |||
// ImGuiIO is to glue SDL and ImGUI together | |||
@@ -234,8 +249,7 @@ int main(int argc, char **argv) { | |||
{ | |||
auto [r, g, b, a] = game.backgroundColor(); | |||
RenderDrawColor c(renderer.get(), r, g, b, a); | |||
SDL_RenderClear(renderer.get()); | |||
window.clear(r / 255.0, g / 255.0, b / 255.0, a / 255.0); | |||
} | |||
// ImGUI | |||
@@ -252,13 +266,14 @@ int main(int argc, char **argv) { | |||
{ | |||
ZoneScopedN("imgui render"); | |||
ImGui::Render(); | |||
ImGuiSDL::Render(ImGui::GetDrawData()); | |||
// TODO: Render ImGui using OpenGL | |||
} | |||
RTClock present_clock; | |||
{ | |||
ZoneScopedN("render present"); | |||
SDL_RenderPresent(renderer.get()); | |||
window.flip(); | |||
} | |||
FrameMark | |||
} |