fencer/core/src/render.c
2023-11-20 12:04:55 +01:00

89 lines
3.2 KiB
C

#include "render.h"
#include "program.h"
#include "debug.h"
#include <SDL2/SDL_pixels.h>
#include <SDL2/SDL_render.h>
SDL_Renderer* g_renderer;
SDL_Texture* g_render_target;
SDL_Rect g_render_area;
IVector g_render_resolution;
void render_init(SDL_Window* window, const struct ProgramSettings* settings) {
LOG_INFO("render_init");
// create renderer, needs to be able to target textures, preferably hardware accelerated
g_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
// create render target texture
g_render_target = SDL_CreateTexture(
g_renderer,
SDL_PIXELFORMAT_ARGB32,
SDL_TEXTUREACCESS_TARGET,
settings->view_resolution.x, settings->view_resolution.y);
// store the desired view resolution
g_render_resolution = settings->view_resolution;
// get the destination area for rendering the target onto the window
render_calculate_render_area();
// clear target black
SDL_SetRenderTarget(g_renderer, g_render_target);
SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
SDL_RenderClear(g_renderer);
}
void render_clean() {
// clear up allocated SDL objects
SDL_DestroyTexture(g_render_target);
SDL_DestroyRenderer(g_renderer);
}
void render_present() {
// clear window white
SDL_SetRenderTarget(g_renderer, NULL);
SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
SDL_RenderClear(g_renderer);
// copy render target
SDL_Rect source_rect = {0, 0, g_render_resolution.x, g_render_resolution.y};
SDL_RenderCopy(g_renderer, g_render_target, &source_rect, &g_render_area);
SDL_RenderPresent(g_renderer);
// clear render target
SDL_SetRenderTarget(g_renderer, g_render_target);
SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
SDL_RenderClear(g_renderer);
}
void render_calculate_render_area() {
// get aspect ratios of both the window and the rendertexture
IVector window_resolution = render_get_window_size();
float window_aspect = (float)window_resolution.x / (float)window_resolution.y;
float target_aspect = (float)g_render_resolution.x / (float)g_render_resolution.y;
// calculate the largest area that will fit the entire rendertexture into the window space
g_render_area = (SDL_Rect) {0, 0, window_resolution.x, window_resolution.y};
if(window_aspect <= target_aspect) {
g_render_area.h = window_resolution.x / target_aspect;
g_render_area.y = (window_resolution.y - g_render_area.h) / 2;
} else {
g_render_area.w = window_resolution.y * target_aspect;
g_render_area.x += (window_resolution.x - g_render_area.w) / 2;
}
}
IVector render_get_window_size() {
// select window as target (store target to reset)
SDL_Texture* target = SDL_GetRenderTarget(g_renderer);
SDL_SetRenderTarget(g_renderer, NULL);
// fetch output size (= window size) of renderer
int window_width, window_height;
SDL_GetRendererOutputSize(g_renderer, &window_width, &window_height);
// reset render target
SDL_SetRenderTarget(g_renderer, target);
// construct IVector from fetched output size
return (IVector){window_width, window_height};
}
void render_handle_resize() {
render_calculate_render_area();
}