implemented scalers
This commit is contained in:
parent
35d6299688
commit
3d41defaf9
|
@ -14,6 +14,6 @@ void init() {
|
|||
|
||||
void tick() {
|
||||
sprites[0].x += 1;
|
||||
sprites[1].x += 2;
|
||||
sprites[1].x += 0;
|
||||
maps[0].scrollx += 1;
|
||||
}
|
||||
|
|
|
@ -9,12 +9,18 @@ struct sw_framebuffer {
|
|||
u32 _fb, _fbtex, _fbdepth;
|
||||
};
|
||||
|
||||
extern u32 sw_screen_vao;
|
||||
|
||||
struct sw_framebuffer *sw_framebuffer_create(struct sw_vec2i size);
|
||||
void sw_framebuffer_destroy(struct sw_framebuffer *fb);
|
||||
|
||||
void sw_framebuffer_static_init();
|
||||
|
||||
/* pass 0 to use currently bound */
|
||||
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);
|
||||
|
||||
#endif /* GUARD_4770FE04EA612B028DF68960A453BD0B */
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
#ifndef GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E
|
||||
#define GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E
|
||||
|
||||
#include "types.h"
|
||||
#include "vec2i.h"
|
||||
|
||||
#define SW_SCALE_STRETCH 0
|
||||
#define SW_SCALE_ASPECT 1
|
||||
#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 */
|
||||
|
|
|
@ -14,6 +14,8 @@ struct sw_shaderprogram {
|
|||
#define SW_SHADER_VERTEX 1
|
||||
#define SW_SHADER_FRAGMENT 2
|
||||
|
||||
#define SW_SHADERLOC_POS 0
|
||||
|
||||
struct sw_shader sw_shader_create(char const *source, i32 type);
|
||||
|
||||
struct sw_shaderprogram
|
||||
|
|
|
@ -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 */
|
|
@ -19,4 +19,7 @@ typedef i8 bool;
|
|||
i32 i32_max(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 */
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#ifndef GUARD_B329567D1B1FDC855E0489217F4BCBE2
|
||||
#define GUARD_B329567D1B1FDC855E0489217F4BCBE2
|
||||
|
||||
#include "types.h"
|
||||
|
||||
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 */
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
struct GLFWwindow;
|
||||
|
||||
struct sw_window {
|
||||
struct sw_vec2i size;
|
||||
struct sw_vec2i real_size;
|
||||
struct sw_vec2i game_size;
|
||||
struct sw_vec2i window_size;
|
||||
i32 scaler;
|
||||
|
||||
struct GLFWwindow *_window;
|
||||
|
|
|
@ -47,7 +47,9 @@ skunk_sources = [
|
|||
'src/gsa.c',
|
||||
'src/image32.c',
|
||||
'src/image8.c',
|
||||
'src/scaler.c',
|
||||
'src/shader.c',
|
||||
'src/shaders.c',
|
||||
'src/skunkworks.c',
|
||||
'src/types.c',
|
||||
'src/vec2i.c',
|
||||
|
|
|
@ -2,34 +2,12 @@
|
|||
#include "error.h"
|
||||
#include "gl.h"
|
||||
#include "shader.h"
|
||||
#include "shaders.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] = {
|
||||
-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 *fb;
|
||||
|
@ -50,13 +28,9 @@ void sw_framebuffer_destroy(struct sw_framebuffer *fb) {
|
|||
}
|
||||
|
||||
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");
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
glGenVertexArrays(1, &sw_screen_vao);
|
||||
glBindVertexArray(sw_screen_vao);
|
||||
|
||||
sw_log("init static framebuffer vbo");
|
||||
glGenBuffers(1, &vbo);
|
||||
|
@ -64,30 +38,27 @@ void sw_framebuffer_static_init() {
|
|||
glBufferData(
|
||||
GL_ARRAY_BUFFER, sizeof(f32) * 12, screen_rect, GL_STATIC_DRAW
|
||||
);
|
||||
glGetAttribLocation(program_copy._program, "pos");
|
||||
glVertexAttribPointer(
|
||||
glGetAttribLocation(program_copy._program, "pos"),
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
0,
|
||||
0
|
||||
);
|
||||
glVertexAttribPointer(SW_SHADERLOC_POS, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
glEnableVertexAttribArray(glGetAttribLocation(program_copy._program, "pos")
|
||||
);
|
||||
glEnableVertexAttribArray(SW_SHADERLOC_POS);
|
||||
|
||||
glBindVertexArray(0);
|
||||
sw_log("init static framebuffer done");
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
glBindVertexArray(0);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -54,6 +54,8 @@ sw_shaderprogram_create(char const *vertex, char const *fragment) {
|
|||
program._program = glCreateProgram();
|
||||
glAttachShader(program._program, v._shader);
|
||||
glAttachShader(program._program, f._shader);
|
||||
sw_log("set attribute locations");
|
||||
glBindAttribLocation(program._program, SW_SHADERLOC_POS, "pos");
|
||||
sw_log("link shader");
|
||||
glLinkProgram(program._program);
|
||||
glGetProgramiv(program._program, GL_LINK_STATUS, &ret);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -7,3 +7,11 @@ i32 i32_max(i32 v1, i32 v2) {
|
|||
i32 i32_min(i32 v1, i32 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;
|
||||
}
|
||||
|
|
35
src/window.c
35
src/window.c
|
@ -1,14 +1,20 @@
|
|||
#include "window.h"
|
||||
#include "gl.h"
|
||||
|
||||
#include <gl/gl.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "error.h"
|
||||
#include "framebuffer.h"
|
||||
#include "gl.h"
|
||||
#include "scaler.h"
|
||||
#include "shaders.h"
|
||||
#include "vec2i.h"
|
||||
|
||||
static void _tick();
|
||||
static struct sw_window *_tick_window;
|
||||
static void (*_tick_fn)();
|
||||
static void win_callback(GLFWwindow *glfw_win, i32 width, i32 height);
|
||||
static void GLAPIENTRY gldebug(
|
||||
GLenum source,
|
||||
GLenum type,
|
||||
|
@ -23,13 +29,15 @@ struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
|
|||
struct sw_window *win;
|
||||
|
||||
win = malloc(sizeof(struct sw_window));
|
||||
win->size = size;
|
||||
win->window_size = size;
|
||||
win->game_size = size;
|
||||
|
||||
sw_log("init glfw");
|
||||
glfwInit();
|
||||
glfwDefaultWindowHints();
|
||||
|
||||
win->_window = glfwCreateWindow(size.x, size.y, title, 0, 0);
|
||||
glfwSetWindowUserPointer(win->_window, win);
|
||||
glfwShowWindow(win->_window);
|
||||
glfwMakeContextCurrent(win->_window);
|
||||
glewInit();
|
||||
|
@ -41,9 +49,12 @@ struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
|
|||
glEnable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
sw_shaders_static_init();
|
||||
sw_framebuffer_static_init(); /* TODO: move elsewhere */
|
||||
win->_scaler_fb = sw_framebuffer_create(size);
|
||||
|
||||
glfwSetWindowSizeCallback(win->_window, win_callback);
|
||||
|
||||
glClearColor(0.1f, 0.2f, 0.3f, 1.f);
|
||||
sw_log("window setup complete");
|
||||
return win;
|
||||
|
@ -65,15 +76,31 @@ void sw_window_run(struct sw_window *window, void (*callback)()) {
|
|||
/* private functions */
|
||||
|
||||
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);
|
||||
_tick_fn();
|
||||
|
||||
glViewport(0, 0, _tick_window->window_size.x, _tick_window->window_size.y);
|
||||
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);
|
||||
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(
|
||||
GLenum source,
|
||||
GLenum type,
|
||||
|
|
Loading…
Reference in New Issue