implemented scalers

This commit is contained in:
DaniTheSkunk 2023-01-14 04:48:58 +00:00
parent 35d6299688
commit 3d41defaf9
15 changed files with 211 additions and 54 deletions

View File

@ -14,6 +14,6 @@ void init() {
void tick() { void tick() {
sprites[0].x += 1; sprites[0].x += 1;
sprites[1].x += 2; sprites[1].x += 0;
maps[0].scrollx += 1; maps[0].scrollx += 1;
} }

View File

@ -9,12 +9,18 @@ struct sw_framebuffer {
u32 _fb, _fbtex, _fbdepth; u32 _fb, _fbtex, _fbdepth;
}; };
extern u32 sw_screen_vao;
struct sw_framebuffer *sw_framebuffer_create(struct sw_vec2i size); struct sw_framebuffer *sw_framebuffer_create(struct sw_vec2i size);
void sw_framebuffer_destroy(struct sw_framebuffer *fb); void sw_framebuffer_destroy(struct sw_framebuffer *fb);
void sw_framebuffer_static_init(); void sw_framebuffer_static_init();
/* pass 0 to use currently bound */
void sw_framebuffer_copy_to_screen(struct sw_framebuffer *fb); void sw_framebuffer_copy_to_screen(struct sw_framebuffer *fb);
/* pass 0 to use currently bound */
void sw_framebuffer_render(struct sw_framebuffer *fb);
void sw_framebuffer_resize(struct sw_framebuffer *fb, struct sw_vec2i new_size); void sw_framebuffer_resize(struct sw_framebuffer *fb, struct sw_vec2i new_size);
#endif /* GUARD_4770FE04EA612B028DF68960A453BD0B */ #endif /* GUARD_4770FE04EA612B028DF68960A453BD0B */

View File

@ -1,8 +1,16 @@
#ifndef GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E #ifndef GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E
#define GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E #define GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E
#include "types.h"
#include "vec2i.h"
#define SW_SCALE_STRETCH 0 #define SW_SCALE_STRETCH 0
#define SW_SCALE_ASPECT 1 #define SW_SCALE_ASPECT 1
#define SW_SCALE_INTEGER 2 #define SW_SCALE_INTEGER 2
/* input texture and output framebuffer(unless screen) need to be bound */
void sw_scaler_apply(
i32 scaler, struct sw_vec2i in_size, struct sw_vec2i out_size
);
#endif /* GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E */ #endif /* GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E */

View File

@ -14,6 +14,8 @@ struct sw_shaderprogram {
#define SW_SHADER_VERTEX 1 #define SW_SHADER_VERTEX 1
#define SW_SHADER_FRAGMENT 2 #define SW_SHADER_FRAGMENT 2
#define SW_SHADERLOC_POS 0
struct sw_shader sw_shader_create(char const *source, i32 type); struct sw_shader sw_shader_create(char const *source, i32 type);
struct sw_shaderprogram struct sw_shaderprogram

11
include/shaders.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef GUARD_1B77D3247B24AE540CDA7D1880E34980
#define GUARD_1B77D3247B24AE540CDA7D1880E34980
#include "shader.h"
extern struct sw_shaderprogram sw_shaders_copy;
extern struct sw_shaderprogram sw_shaders_scale;
void sw_shaders_static_init();
#endif /* GUARD_1B77D3247B24AE540CDA7D1880E34980 */

View File

@ -19,4 +19,7 @@ typedef i8 bool;
i32 i32_max(i32 v1, i32 v2); i32 i32_max(i32 v1, i32 v2);
i32 i32_min(i32 v1, i32 v2); i32 i32_min(i32 v1, i32 v2);
f32 f32_max(f32 v1, f32 v2);
f32 f32_min(f32 v1, f32 v2);
#endif /* GUARD_649E63003BEAE79ECA2B813C4E131C9A */ #endif /* GUARD_649E63003BEAE79ECA2B813C4E131C9A */

View File

@ -1,10 +1,12 @@
#ifndef GUARD_B329567D1B1FDC855E0489217F4BCBE2 #ifndef GUARD_B329567D1B1FDC855E0489217F4BCBE2
#define GUARD_B329567D1B1FDC855E0489217F4BCBE2 #define GUARD_B329567D1B1FDC855E0489217F4BCBE2
#include "types.h"
struct sw_vec2i { struct sw_vec2i {
int x, y; i32 x, y;
}; };
struct sw_vec2i sw_vec2i(int x, int y); struct sw_vec2i sw_vec2i(i32 x, i32 y);
#endif /* GUARD_B329567D1B1FDC855E0489217F4BCBE2 */ #endif /* GUARD_B329567D1B1FDC855E0489217F4BCBE2 */

View File

@ -8,8 +8,8 @@
struct GLFWwindow; struct GLFWwindow;
struct sw_window { struct sw_window {
struct sw_vec2i size; struct sw_vec2i game_size;
struct sw_vec2i real_size; struct sw_vec2i window_size;
i32 scaler; i32 scaler;
struct GLFWwindow *_window; struct GLFWwindow *_window;

View File

@ -47,7 +47,9 @@ skunk_sources = [
'src/gsa.c', 'src/gsa.c',
'src/image32.c', 'src/image32.c',
'src/image8.c', 'src/image8.c',
'src/scaler.c',
'src/shader.c', 'src/shader.c',
'src/shaders.c',
'src/skunkworks.c', 'src/skunkworks.c',
'src/types.c', 'src/types.c',
'src/vec2i.c', 'src/vec2i.c',

View File

@ -2,34 +2,12 @@
#include "error.h" #include "error.h"
#include "gl.h" #include "gl.h"
#include "shader.h" #include "shader.h"
#include "shaders.h"
#include <stdlib.h> #include <stdlib.h>
static struct sw_shaderprogram program_copy;
static char *vert_copy = "#version 300 es\n\
precision highp float;\
in vec2 pos;\
out vec2 out_tex_coord;\
void main() {\
gl_Position = vec4(pos, 0.0f, 1.0f);\
out_tex_coord = vec2(pos.x * 0.5 + 0.5, pos.y * 0.5 + 0.5);\
}";
static char *frag_copy = "#version 300 es\n\
precision highp float;\
in vec2 out_tex_coord;\
uniform sampler2D tex;\
out vec4 color;\
void main() {\
vec4 col = texture(tex, out_tex_coord);\
if(col.a > 0.0) {\
color = col;\
}\
}";
static f32 screen_rect[12] = { static f32 screen_rect[12] = {
-1.f, -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f}; -1.f, -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f};
static u32 vao, vbo; static u32 sw_screen_vao, vbo;
struct sw_framebuffer *sw_framebuffer_create(struct sw_vec2i size) { struct sw_framebuffer *sw_framebuffer_create(struct sw_vec2i size) {
struct sw_framebuffer *fb; struct sw_framebuffer *fb;
@ -50,13 +28,9 @@ void sw_framebuffer_destroy(struct sw_framebuffer *fb) {
} }
void sw_framebuffer_static_init() { void sw_framebuffer_static_init() {
sw_log("init static framebuffer");
program_copy = sw_shaderprogram_create(vert_copy, frag_copy);
sw_log("init static framebuffer vao"); sw_log("init static framebuffer vao");
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &sw_screen_vao);
glBindVertexArray(vao); glBindVertexArray(sw_screen_vao);
sw_log("init static framebuffer vbo"); sw_log("init static framebuffer vbo");
glGenBuffers(1, &vbo); glGenBuffers(1, &vbo);
@ -64,30 +38,27 @@ void sw_framebuffer_static_init() {
glBufferData( glBufferData(
GL_ARRAY_BUFFER, sizeof(f32) * 12, screen_rect, GL_STATIC_DRAW GL_ARRAY_BUFFER, sizeof(f32) * 12, screen_rect, GL_STATIC_DRAW
); );
glGetAttribLocation(program_copy._program, "pos"); glVertexAttribPointer(SW_SHADERLOC_POS, 2, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(
glGetAttribLocation(program_copy._program, "pos"),
2,
GL_FLOAT,
GL_FALSE,
0,
0
);
glEnableVertexAttribArray(glGetAttribLocation(program_copy._program, "pos") glEnableVertexAttribArray(SW_SHADERLOC_POS);
);
glBindVertexArray(0); glBindVertexArray(0);
sw_log("init static framebuffer done"); sw_log("init static framebuffer done");
} }
void sw_framebuffer_copy_to_screen(struct sw_framebuffer *fb) { void sw_framebuffer_copy_to_screen(struct sw_framebuffer *fb) {
glBindVertexArray(vao);
sw_shaderprogram_use(program_copy);
glBindTexture(GL_TEXTURE_2D, fb->_fbtex);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
sw_shaderprogram_use(sw_shaders_copy);
sw_framebuffer_render(fb);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); void sw_framebuffer_render(struct sw_framebuffer *fb) {
glBindVertexArray(sw_screen_vao);
if(fb) {
glBindTexture(GL_TEXTURE_2D, fb->_fbtex);
}
glClear(GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 12); glDrawArrays(GL_TRIANGLES, 0, 12);
glBindVertexArray(0); glBindVertexArray(0);

62
src/scaler.c Normal file
View File

@ -0,0 +1,62 @@
#include "scaler.h"
#include "error.h"
#include "framebuffer.h"
#include "gl.h"
#include "shader.h"
#include "shaders.h"
void sw_scaler_apply(
i32 scaler, struct sw_vec2i in_size, struct sw_vec2i out_size
) {
(void)in_size;
(void)out_size;
f32 scalex, scaley, scale, xoff, yoff;
switch(scaler) {
case SW_SCALE_STRETCH:
sw_shaderprogram_use(sw_shaders_copy);
break;
case SW_SCALE_ASPECT:
sw_shaderprogram_use(sw_shaders_scale);
scalex = (f32)out_size.x / (f32)in_size.x;
scaley = (f32)out_size.y / (f32)in_size.y;
scale = f32_min(scalex, scaley);
xoff = (out_size.x - in_size.x * scale) / 2 / out_size.x;
yoff = (out_size.y - in_size.y * scale) / 2 / out_size.y;
glUniform2f(
glGetUniformLocation(sw_shaders_scale._program, "offset"),
xoff,
yoff
);
glUniform2f(
glGetUniformLocation(sw_shaders_scale._program, "size_ratio"),
(f32)out_size.x / (f32)in_size.x / scale,
(f32)out_size.y / (f32)in_size.y / scale
);
break;
case SW_SCALE_INTEGER:
sw_shaderprogram_use(sw_shaders_scale);
scalex = (f32)out_size.x / (f32)in_size.x;
scaley = (f32)out_size.y / (f32)in_size.y;
scale = f32_min(scalex, scaley);
scale = i32_max(1, (i32)scale);
xoff = (out_size.x - in_size.x * scale) / 2 / out_size.x;
yoff = (out_size.y - in_size.y * scale) / 2 / out_size.y;
glUniform2f(
glGetUniformLocation(sw_shaders_scale._program, "offset"),
xoff,
yoff
);
glUniform2f(
glGetUniformLocation(sw_shaders_scale._program, "size_ratio"),
(f32)out_size.x / (f32)in_size.x / scale,
(f32)out_size.y / (f32)in_size.y / scale
);
break;
default:
sw_error("unknown scaler %i", scaler);
}
sw_framebuffer_render(0);
}

View File

@ -54,6 +54,8 @@ sw_shaderprogram_create(char const *vertex, char const *fragment) {
program._program = glCreateProgram(); program._program = glCreateProgram();
glAttachShader(program._program, v._shader); glAttachShader(program._program, v._shader);
glAttachShader(program._program, f._shader); glAttachShader(program._program, f._shader);
sw_log("set attribute locations");
glBindAttribLocation(program._program, SW_SHADERLOC_POS, "pos");
sw_log("link shader"); sw_log("link shader");
glLinkProgram(program._program); glLinkProgram(program._program);
glGetProgramiv(program._program, GL_LINK_STATUS, &ret); glGetProgramiv(program._program, GL_LINK_STATUS, &ret);

53
src/shaders.c Normal file
View File

@ -0,0 +1,53 @@
#include "shaders.h"
#include "error.h"
struct sw_shaderprogram sw_shaders_copy;
struct sw_shaderprogram sw_shaders_scale;
static char *vert_copy = "#version 300 es\n\
precision highp float;\
in vec2 pos;\
out vec2 out_tex_coord;\
void main() {\
gl_Position = vec4(pos, 0.0f, 1.0f);\
out_tex_coord = vec2(pos.x * 0.5 + 0.5, pos.y * 0.5 + 0.5);\
}";
static char *frag_copy = "#version 300 es\n\
precision highp float;\
in vec2 out_tex_coord;\
uniform sampler2D tex;\
out vec4 color;\
void main() {\
vec4 col = texture(tex, out_tex_coord);\
if(col.a > 0.0) {\
color = col;\
}\
}";
static char *frag_scale = "#version 300 es\n\
precision highp float;\
in vec2 out_tex_coord;\
uniform sampler2D tex;\
uniform float scale;\
uniform vec2 offset;\
uniform vec2 size_ratio;\
out vec4 color;\
void main() {\
vec2 tc = (out_tex_coord-offset)*size_ratio;\
vec4 col = vec4(0,0,0,0);\
if(tc.x <= 1.0 && tc.y <= 1.0 && tc.x >= 0.0 && tc.y >= 0.0) {\
col = texture(tex, tc);\
}\
if(col.a > 0.0) {\
color = col;\
} else { \
discard;\
}\
}";
void sw_shaders_static_init() {
sw_log("initialising shaders");
sw_shaders_copy = sw_shaderprogram_create(vert_copy, frag_copy);
sw_shaders_scale = sw_shaderprogram_create(vert_copy, frag_scale);
}

View File

@ -7,3 +7,11 @@ i32 i32_max(i32 v1, i32 v2) {
i32 i32_min(i32 v1, i32 v2) { i32 i32_min(i32 v1, i32 v2) {
return v1 < v2 ? v1 : v2; return v1 < v2 ? v1 : v2;
} }
f32 f32_max(f32 v1, f32 v2) {
return v1 > v2 ? v1 : v2;
}
f32 f32_min(f32 v1, f32 v2) {
return v1 < v2 ? v1 : v2;
}

View File

@ -1,14 +1,20 @@
#include "window.h" #include "window.h"
#include "gl.h"
#include <gl/gl.h>
#include <stdlib.h> #include <stdlib.h>
#include "GLFW/glfw3.h"
#include "error.h" #include "error.h"
#include "framebuffer.h" #include "framebuffer.h"
#include "gl.h" #include "scaler.h"
#include "shaders.h"
#include "vec2i.h"
static void _tick(); static void _tick();
static struct sw_window *_tick_window; static struct sw_window *_tick_window;
static void (*_tick_fn)(); static void (*_tick_fn)();
static void win_callback(GLFWwindow *glfw_win, i32 width, i32 height);
static void GLAPIENTRY gldebug( static void GLAPIENTRY gldebug(
GLenum source, GLenum source,
GLenum type, GLenum type,
@ -23,13 +29,15 @@ struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
struct sw_window *win; struct sw_window *win;
win = malloc(sizeof(struct sw_window)); win = malloc(sizeof(struct sw_window));
win->size = size; win->window_size = size;
win->game_size = size;
sw_log("init glfw"); sw_log("init glfw");
glfwInit(); glfwInit();
glfwDefaultWindowHints(); glfwDefaultWindowHints();
win->_window = glfwCreateWindow(size.x, size.y, title, 0, 0); win->_window = glfwCreateWindow(size.x, size.y, title, 0, 0);
glfwSetWindowUserPointer(win->_window, win);
glfwShowWindow(win->_window); glfwShowWindow(win->_window);
glfwMakeContextCurrent(win->_window); glfwMakeContextCurrent(win->_window);
glewInit(); glewInit();
@ -41,9 +49,12 @@ struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
sw_shaders_static_init();
sw_framebuffer_static_init(); /* TODO: move elsewhere */ sw_framebuffer_static_init(); /* TODO: move elsewhere */
win->_scaler_fb = sw_framebuffer_create(size); win->_scaler_fb = sw_framebuffer_create(size);
glfwSetWindowSizeCallback(win->_window, win_callback);
glClearColor(0.1f, 0.2f, 0.3f, 1.f); glClearColor(0.1f, 0.2f, 0.3f, 1.f);
sw_log("window setup complete"); sw_log("window setup complete");
return win; return win;
@ -65,15 +76,31 @@ void sw_window_run(struct sw_window *window, void (*callback)()) {
/* private functions */ /* private functions */
void _tick() { void _tick() {
glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, _tick_window->game_size.x, _tick_window->game_size.y);
glBindFramebuffer(GL_FRAMEBUFFER, _tick_window->_scaler_fb->_fb); glBindFramebuffer(GL_FRAMEBUFFER, _tick_window->_scaler_fb->_fb);
_tick_fn(); _tick_fn();
glViewport(0, 0, _tick_window->window_size.x, _tick_window->window_size.y);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
sw_framebuffer_copy_to_screen(_tick_window->_scaler_fb); glBindTexture(GL_TEXTURE_2D, _tick_window->_scaler_fb->_fbtex);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
sw_scaler_apply(
SW_SCALE_INTEGER, _tick_window->game_size, _tick_window->window_size
);
glfwSwapBuffers(_tick_window->_window); glfwSwapBuffers(_tick_window->_window);
glfwPollEvents(); glfwPollEvents();
} }
static void win_callback(GLFWwindow *glfw_win, i32 width, i32 height) {
struct sw_window *win;
sw_log("resizing window to %ix%i", width, height);
win = glfwGetWindowUserPointer(glfw_win);
win->window_size = sw_vec2i(width, height);
}
void GLAPIENTRY gldebug( void GLAPIENTRY gldebug(
GLenum source, GLenum source,
GLenum type, GLenum type,