added framebuffer; also opengl debugging
This commit is contained in:
parent
75f83bf3f6
commit
35d6299688
BIN
gfx.png
BIN
gfx.png
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef GUARD_4770FE04EA612B028DF68960A453BD0B
|
||||||
|
#define GUARD_4770FE04EA612B028DF68960A453BD0B
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "vec2i.h"
|
||||||
|
|
||||||
|
struct sw_framebuffer {
|
||||||
|
struct sw_vec2i size;
|
||||||
|
u32 _fb, _fbtex, _fbdepth;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sw_framebuffer *sw_framebuffer_create(struct sw_vec2i size);
|
||||||
|
void sw_framebuffer_destroy(struct sw_framebuffer *fb);
|
||||||
|
|
||||||
|
void sw_framebuffer_static_init();
|
||||||
|
|
||||||
|
void sw_framebuffer_copy_to_screen(struct sw_framebuffer *fb);
|
||||||
|
void sw_framebuffer_resize(struct sw_framebuffer *fb, struct sw_vec2i new_size);
|
||||||
|
|
||||||
|
#endif /* GUARD_4770FE04EA612B028DF68960A453BD0B */
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E
|
||||||
|
#define GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E
|
||||||
|
|
||||||
|
#define SW_SCALE_STRETCH 0
|
||||||
|
#define SW_SCALE_ASPECT 1
|
||||||
|
#define SW_SCALE_INTEGER 2
|
||||||
|
|
||||||
|
#endif /* GUARD_D3B2B8EAB7F3D9A513B3C06FAAF6357E */
|
|
@ -1,14 +1,19 @@
|
||||||
#ifndef GUARD_F247452E0BF1EC9CD9131C2A6FD281CA
|
#ifndef GUARD_F247452E0BF1EC9CD9131C2A6FD281CA
|
||||||
#define GUARD_F247452E0BF1EC9CD9131C2A6FD281CA
|
#define GUARD_F247452E0BF1EC9CD9131C2A6FD281CA
|
||||||
|
|
||||||
|
#include "framebuffer.h"
|
||||||
|
#include "types.h"
|
||||||
#include "vec2i.h"
|
#include "vec2i.h"
|
||||||
|
|
||||||
struct GLFWwindow;
|
struct GLFWwindow;
|
||||||
|
|
||||||
struct sw_window {
|
struct sw_window {
|
||||||
struct sw_vec2i size;
|
struct sw_vec2i size;
|
||||||
|
struct sw_vec2i real_size;
|
||||||
|
i32 scaler;
|
||||||
|
|
||||||
struct GLFWwindow *_window;
|
struct GLFWwindow *_window;
|
||||||
|
struct sw_framebuffer *_scaler_fb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sw_window *sw_window_create(struct sw_vec2i size, char *title);
|
struct sw_window *sw_window_create(struct sw_vec2i size, char *title);
|
||||||
|
|
|
@ -43,6 +43,7 @@ skunk_sources = [
|
||||||
'src/color32.c',
|
'src/color32.c',
|
||||||
'src/error.c',
|
'src/error.c',
|
||||||
'src/file.c',
|
'src/file.c',
|
||||||
|
'src/framebuffer.c',
|
||||||
'src/gsa.c',
|
'src/gsa.c',
|
||||||
'src/image32.c',
|
'src/image32.c',
|
||||||
'src/image8.c',
|
'src/image8.c',
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
#include "framebuffer.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "gl.h"
|
||||||
|
#include "shader.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;
|
||||||
|
|
||||||
|
struct sw_framebuffer *sw_framebuffer_create(struct sw_vec2i size) {
|
||||||
|
struct sw_framebuffer *fb;
|
||||||
|
|
||||||
|
sw_log("init framebuffer");
|
||||||
|
fb = malloc(sizeof(struct sw_framebuffer));
|
||||||
|
glGenFramebuffers(1, &fb->_fb);
|
||||||
|
glGenTextures(1, &fb->_fbtex);
|
||||||
|
glGenTextures(1, &fb->_fbdepth);
|
||||||
|
sw_framebuffer_resize(fb, size);
|
||||||
|
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sw_framebuffer_destroy(struct sw_framebuffer *fb) {
|
||||||
|
glDeleteTextures(1, &fb->_fbtex);
|
||||||
|
glDeleteFramebuffers(1, &fb->_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);
|
||||||
|
|
||||||
|
sw_log("init static framebuffer vbo");
|
||||||
|
glGenBuffers(1, &vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(glGetAttribLocation(program_copy._program, "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);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 12);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sw_framebuffer_resize(
|
||||||
|
struct sw_framebuffer *fb, struct sw_vec2i new_size
|
||||||
|
) {
|
||||||
|
sw_log("resize framebuffer to %ix%i", new_size.x, new_size.y);
|
||||||
|
fb->size = new_size;
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fb->_fb);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, fb->_fbtex);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_RGBA8,
|
||||||
|
new_size.x,
|
||||||
|
new_size.y,
|
||||||
|
0,
|
||||||
|
GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fb->_fbtex, 0);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, fb->_fbdepth);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_DEPTH_COMPONENT,
|
||||||
|
new_size.x,
|
||||||
|
new_size.y,
|
||||||
|
0,
|
||||||
|
GL_DEPTH_COMPONENT,
|
||||||
|
GL_UNSIGNED_SHORT,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, fb->_fbdepth, 0);
|
||||||
|
}
|
15
src/gsa.c
15
src/gsa.c
|
@ -54,18 +54,17 @@ static i32 next_render_vert;
|
||||||
static struct render_vert render_verts[MAX_RENDER_VERTS * 4];
|
static struct render_vert render_verts[MAX_RENDER_VERTS * 4];
|
||||||
static sw_color32 palette[256];
|
static sw_color32 palette[256];
|
||||||
static f32 palette_gl[1024];
|
static f32 palette_gl[1024];
|
||||||
|
static u32 tex;
|
||||||
|
|
||||||
int gsa_main(int argc, char *argv[]) {
|
int gsa_main(int argc, char *argv[]) {
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
u32 tex;
|
|
||||||
i32 max_components;
|
i32 max_components;
|
||||||
|
|
||||||
sw_log("Initialising GameSkunkAdvance v0.0");
|
sw_log("Initialising GameSkunkAdvance v0.0");
|
||||||
|
|
||||||
_win = sw_window_create(sw_vec2i(304, 176), "Game Skunk Advance v0.0");
|
_win = sw_window_create(sw_vec2i(304, 176), "Game Skunk Advance v0.0");
|
||||||
program = sw_shaderprogram_create(vert_source, frag_source);
|
program = sw_shaderprogram_create(vert_source, frag_source);
|
||||||
sw_shaderprogram_use(program);
|
|
||||||
|
|
||||||
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_components);
|
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_components);
|
||||||
sw_log("GL_MAX_VERTEX_UNIFORM_COMPONENTS: %i", max_components);
|
sw_log("GL_MAX_VERTEX_UNIFORM_COMPONENTS: %i", max_components);
|
||||||
|
@ -88,9 +87,11 @@ int gsa_main(int argc, char *argv[]) {
|
||||||
_gfx->_data
|
_gfx->_data
|
||||||
);
|
);
|
||||||
|
|
||||||
glGenBuffers(1, &vao);
|
sw_log("setup gsa vao");
|
||||||
|
glGenVertexArrays(1, &vao);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
|
|
||||||
|
sw_log("setup gsa vbo");
|
||||||
glGenBuffers(1, &vbo);
|
glGenBuffers(1, &vbo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
glVertexAttribPointer(
|
glVertexAttribPointer(
|
||||||
|
@ -112,7 +113,9 @@ int gsa_main(int argc, char *argv[]) {
|
||||||
glEnableVertexAttribArray(glGetAttribLocation(program._program, "pos"));
|
glEnableVertexAttribArray(glGetAttribLocation(program._program, "pos"));
|
||||||
glEnableVertexAttribArray(glGetAttribLocation(program._program, "tex_coord")
|
glEnableVertexAttribArray(glGetAttribLocation(program._program, "tex_coord")
|
||||||
);
|
);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
sw_log("gsa setup done");
|
||||||
init();
|
init();
|
||||||
sw_window_run(_win, _gsa_tick);
|
sw_window_run(_win, _gsa_tick);
|
||||||
|
|
||||||
|
@ -202,8 +205,11 @@ void _gsa_tick() {
|
||||||
sw_color32_get_bf(palette[0]),
|
sw_color32_get_bf(palette[0]),
|
||||||
sw_color32_get_af(palette[0])
|
sw_color32_get_af(palette[0])
|
||||||
);
|
);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
|
sw_shaderprogram_use(program);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
|
|
||||||
/* TODO: only do when palette changed */
|
/* TODO: only do when palette changed */
|
||||||
update_palette_gl();
|
update_palette_gl();
|
||||||
glUniform4fv(
|
glUniform4fv(
|
||||||
|
@ -216,5 +222,6 @@ void _gsa_tick() {
|
||||||
GL_DYNAMIC_DRAW
|
GL_DYNAMIC_DRAW
|
||||||
);
|
);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, next_render_vert);
|
glDrawArrays(GL_TRIANGLES, 0, next_render_vert);
|
||||||
|
glBindVertexArray(0);
|
||||||
/* glEnd(); */
|
/* glEnd(); */
|
||||||
}
|
}
|
||||||
|
|
12
src/shader.c
12
src/shader.c
|
@ -11,6 +11,8 @@ struct sw_shader sw_shader_create(char const *source, i32 type) {
|
||||||
i32 length;
|
i32 length;
|
||||||
i32 ret;
|
i32 ret;
|
||||||
|
|
||||||
|
sw_log("create shader");
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case SW_SHADER_VERTEX:
|
case SW_SHADER_VERTEX:
|
||||||
gltype = GL_VERTEX_SHADER;
|
gltype = GL_VERTEX_SHADER;
|
||||||
|
@ -44,14 +46,24 @@ struct sw_shaderprogram
|
||||||
sw_shaderprogram_create(char const *vertex, char const *fragment) {
|
sw_shaderprogram_create(char const *vertex, char const *fragment) {
|
||||||
struct sw_shaderprogram program;
|
struct sw_shaderprogram program;
|
||||||
struct sw_shader v, f;
|
struct sw_shader v, f;
|
||||||
|
i32 ret;
|
||||||
|
|
||||||
|
sw_log("create shader program");
|
||||||
v = sw_shader_create(vertex, SW_SHADER_VERTEX);
|
v = sw_shader_create(vertex, SW_SHADER_VERTEX);
|
||||||
f = sw_shader_create(fragment, SW_SHADER_FRAGMENT);
|
f = sw_shader_create(fragment, SW_SHADER_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("link shader");
|
||||||
glLinkProgram(program._program);
|
glLinkProgram(program._program);
|
||||||
|
glGetProgramiv(program._program, GL_LINK_STATUS, &ret);
|
||||||
|
if(!ret) {
|
||||||
|
char str[256];
|
||||||
|
i32 len;
|
||||||
|
|
||||||
|
glGetProgramInfoLog(program._program, 256, &len, str);
|
||||||
|
sw_error("Shader Link Error: %s", str);
|
||||||
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
53
src/window.c
53
src/window.c
|
@ -2,11 +2,22 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
#include "framebuffer.h"
|
||||||
#include "gl.h"
|
#include "gl.h"
|
||||||
|
|
||||||
void _tick();
|
static void _tick();
|
||||||
struct sw_window *_tick_window;
|
static struct sw_window *_tick_window;
|
||||||
void (*_tick_fn)();
|
static void (*_tick_fn)();
|
||||||
|
static void GLAPIENTRY gldebug(
|
||||||
|
GLenum source,
|
||||||
|
GLenum type,
|
||||||
|
GLuint id,
|
||||||
|
GLenum severity,
|
||||||
|
GLsizei length,
|
||||||
|
const char *msg,
|
||||||
|
const void *user
|
||||||
|
);
|
||||||
|
|
||||||
struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
|
struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
|
||||||
struct sw_window *win;
|
struct sw_window *win;
|
||||||
|
@ -14,6 +25,7 @@ struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
|
||||||
win = malloc(sizeof(struct sw_window));
|
win = malloc(sizeof(struct sw_window));
|
||||||
win->size = size;
|
win->size = size;
|
||||||
|
|
||||||
|
sw_log("init glfw");
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwDefaultWindowHints();
|
glfwDefaultWindowHints();
|
||||||
|
|
||||||
|
@ -21,16 +33,24 @@ struct sw_window *sw_window_create(struct sw_vec2i size, char *title) {
|
||||||
glfwShowWindow(win->_window);
|
glfwShowWindow(win->_window);
|
||||||
glfwMakeContextCurrent(win->_window);
|
glfwMakeContextCurrent(win->_window);
|
||||||
glewInit();
|
glewInit();
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
glDebugMessageCallback(gldebug, 0);
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
|
sw_log("setup ogl defaults");
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
sw_framebuffer_static_init(); /* TODO: move elsewhere */
|
||||||
|
win->_scaler_fb = sw_framebuffer_create(size);
|
||||||
|
|
||||||
glClearColor(0.1f, 0.2f, 0.3f, 1.f);
|
glClearColor(0.1f, 0.2f, 0.3f, 1.f);
|
||||||
|
sw_log("window setup complete");
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sw_window_run(struct sw_window *window, void (*callback)()) {
|
void sw_window_run(struct sw_window *window, void (*callback)()) {
|
||||||
|
sw_log("run window");
|
||||||
_tick_window = window;
|
_tick_window = window;
|
||||||
_tick_fn = callback;
|
_tick_fn = callback;
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
|
@ -45,8 +65,33 @@ void sw_window_run(struct sw_window *window, void (*callback)()) {
|
||||||
/* private functions */
|
/* private functions */
|
||||||
|
|
||||||
void _tick() {
|
void _tick() {
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, _tick_window->_scaler_fb->_fb);
|
||||||
_tick_fn();
|
_tick_fn();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
sw_framebuffer_copy_to_screen(_tick_window->_scaler_fb);
|
||||||
glfwSwapBuffers(_tick_window->_window);
|
glfwSwapBuffers(_tick_window->_window);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLAPIENTRY gldebug(
|
||||||
|
GLenum source,
|
||||||
|
GLenum type,
|
||||||
|
GLuint id,
|
||||||
|
GLenum severity,
|
||||||
|
GLsizei length,
|
||||||
|
const char *msg,
|
||||||
|
const void *user
|
||||||
|
) {
|
||||||
|
(void)source;
|
||||||
|
(void)id;
|
||||||
|
(void)severity;
|
||||||
|
(void)length;
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
if(type == GL_DEBUG_TYPE_ERROR) {
|
||||||
|
sw_error("%s", msg);
|
||||||
|
} else {
|
||||||
|
sw_log("%s", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue