mirror of
https://gitlab.com/dosowisko.net/libsuperderpy.git
synced 2025-02-08 06:06:43 +01:00
shader: auto rebuild and auto destroy shaders
This commit is contained in:
parent
5fe62da08f
commit
71ec8b396e
4 changed files with 110 additions and 28 deletions
|
@ -94,6 +94,7 @@ SYMBOL_INTERNAL void LogicGamestates(struct Game* game, double delta) {
|
|||
|
||||
SYMBOL_INTERNAL void ReloadGamestates(struct Game* game) {
|
||||
struct Gamestate* tmp = game->_priv.gamestates;
|
||||
ReloadShaders(game, true);
|
||||
while (tmp) {
|
||||
if (tmp->loaded) {
|
||||
game->_priv.current_gamestate = tmp;
|
||||
|
@ -355,7 +356,21 @@ static bool Identity(struct libsuperderpy_list* elem, void* data) {
|
|||
return elem->data == data;
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL struct libsuperderpy_list* RemoveFromList(struct libsuperderpy_list** list, void* data, bool (*identity)(struct libsuperderpy_list* elem, void* data)) {
|
||||
SYMBOL_INTERNAL struct libsuperderpy_list* FindInList(struct libsuperderpy_list* list, void* data, bool (*identity)(struct libsuperderpy_list* elem, void* data)) {
|
||||
struct libsuperderpy_list* tmp = list;
|
||||
if (!identity) {
|
||||
identity = Identity;
|
||||
}
|
||||
while (tmp) {
|
||||
if (identity(tmp, data)) {
|
||||
return tmp;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL void* RemoveFromList(struct libsuperderpy_list** list, void* data, bool (*identity)(struct libsuperderpy_list* elem, void* data)) {
|
||||
struct libsuperderpy_list *prev = NULL, *tmp = *list, *start;
|
||||
void* d = NULL;
|
||||
if (!identity) {
|
||||
|
@ -506,6 +521,7 @@ SYMBOL_INTERNAL void PauseExecution(struct Game* game) {
|
|||
}
|
||||
|
||||
SYMBOL_INTERNAL void ResumeExecution(struct Game* game) {
|
||||
ReloadShaders(game, true);
|
||||
PrintConsole(game, "DEBUG: reloading the gamestates...");
|
||||
struct Gamestate* tmp = game->_priv.gamestates;
|
||||
while (tmp) {
|
||||
|
|
|
@ -80,7 +80,8 @@ void* AddGarbage(struct Game* game, void* data);
|
|||
void ClearGarbage(struct Game* game);
|
||||
void ClearScreen(struct Game* game);
|
||||
struct libsuperderpy_list* AddToList(struct libsuperderpy_list* list, void* data);
|
||||
struct libsuperderpy_list* RemoveFromList(struct libsuperderpy_list** list, void* data, bool (*identity)(struct libsuperderpy_list* elem, void* data));
|
||||
struct libsuperderpy_list* FindInList(struct libsuperderpy_list* list, void* data, bool (*identity)(struct libsuperderpy_list* elem, void* data));
|
||||
void* RemoveFromList(struct libsuperderpy_list** list, void* data, bool (*identity)(struct libsuperderpy_list* elem, void* data));
|
||||
void AddTimeline(struct Game* game, struct Timeline* timeline);
|
||||
void RemoveTimeline(struct Game* game, struct Timeline* timeline);
|
||||
void DrawTimelines(struct Game* game);
|
||||
|
@ -91,5 +92,7 @@ struct Gamestate* AllocateGamestate(struct Game* game, const char* name);
|
|||
char* GetLibraryPath(struct Game* game, char* filename);
|
||||
void PauseExecution(struct Game* game);
|
||||
void ResumeExecution(struct Game* game);
|
||||
void ReloadShaders(struct Game* game, bool force);
|
||||
void DestroyShaders(struct Game* game);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -420,8 +420,8 @@ SYMBOL_INTERNAL void libsuperderpy_mainloop(void* g) {
|
|||
#endif
|
||||
|
||||
al_set_new_bitmap_flags(data.bitmap_flags);
|
||||
// TODO: compile shaders
|
||||
al_convert_memory_bitmaps();
|
||||
ReloadShaders(game, false);
|
||||
game->_priv.loading.loaded++;
|
||||
|
||||
tmp->loaded = true;
|
||||
|
@ -631,6 +631,7 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
|
|||
if (game->handlers.destroy) {
|
||||
(*game->handlers.destroy)(game);
|
||||
}
|
||||
DestroyShaders(game);
|
||||
|
||||
ClearScreen(game);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
|
|
112
src/shader.c
112
src/shader.c
|
@ -22,39 +22,101 @@
|
|||
#include <allegro5/allegro.h>
|
||||
#include <math.h>
|
||||
|
||||
ALLEGRO_SHADER* CreateShader(struct Game* game, const char* vertex, const char* fragment) {
|
||||
const char* log;
|
||||
static bool AttachToShader(struct Game* game, ALLEGRO_SHADER* shader, ALLEGRO_SHADER_TYPE type, const char* filename) {
|
||||
bool ret;
|
||||
if (filename) {
|
||||
ret = al_attach_shader_source_file(shader, type, filename);
|
||||
} else {
|
||||
ret = al_attach_shader_source(shader, type, al_get_default_shader_source(al_get_shader_platform(shader), type));
|
||||
}
|
||||
if (!ret) {
|
||||
const char* log;
|
||||
log = al_get_shader_log(shader);
|
||||
if (log) {
|
||||
FatalError(game, false, "%s", log);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ShaderListItem {
|
||||
ALLEGRO_SHADER* shader;
|
||||
char* vertex;
|
||||
char* fragment;
|
||||
bool loaded;
|
||||
};
|
||||
|
||||
SYMBOL_EXPORT ALLEGRO_SHADER* CreateShader(struct Game* game, const char* vertex, const char* fragment) {
|
||||
PrintConsole(game, "Creating shader V:%s F:%s...", vertex, fragment);
|
||||
|
||||
ALLEGRO_SHADER* shader = al_create_shader(ALLEGRO_SHADER_GLSL);
|
||||
if (!al_attach_shader_source_file(shader, ALLEGRO_VERTEX_SHADER, vertex)) {
|
||||
log = al_get_shader_log(shader);
|
||||
if (log) {
|
||||
PrintConsole(game, "%s", log);
|
||||
}
|
||||
}
|
||||
if (!al_attach_shader_source_file(shader, ALLEGRO_PIXEL_SHADER, fragment)) {
|
||||
log = al_get_shader_log(shader);
|
||||
if (log) {
|
||||
PrintConsole(game, "%s", log);
|
||||
}
|
||||
}
|
||||
if (!al_build_shader(shader)) {
|
||||
log = al_get_shader_log(shader);
|
||||
if (log) {
|
||||
PrintConsole(game, "%s", log);
|
||||
}
|
||||
}
|
||||
|
||||
game->_priv.shaders = AddToList(game->_priv.shaders, shader);
|
||||
struct ShaderListItem* item = malloc(sizeof(struct ShaderListItem));
|
||||
item->shader = shader;
|
||||
item->vertex = vertex ? strdup(vertex) : NULL;
|
||||
item->fragment = fragment ? strdup(fragment) : NULL;
|
||||
item->loaded = false;
|
||||
|
||||
PrintConsole(game, "Shader compiled successfully.");
|
||||
game->_priv.shaders = AddToList(game->_priv.shaders, item);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void DestroyShader(struct Game* game, ALLEGRO_SHADER* shader) {
|
||||
RemoveFromList(&game->_priv.shaders, shader, NULL);
|
||||
al_destroy_shader(shader);
|
||||
static bool ShaderIdentity(struct libsuperderpy_list* item, void* shader) {
|
||||
return ((struct ShaderListItem*)item->data)->shader == shader;
|
||||
}
|
||||
|
||||
SYMBOL_EXPORT void DestroyShader(struct Game* game, ALLEGRO_SHADER* shader) {
|
||||
struct ShaderListItem* item = RemoveFromList(&game->_priv.shaders, shader, ShaderIdentity);
|
||||
if (!item) {
|
||||
PrintConsole(game, "Tried to destroy a unregistered shader!");
|
||||
al_destroy_shader(shader);
|
||||
return;
|
||||
}
|
||||
al_destroy_shader(item->shader);
|
||||
if (item->vertex) {
|
||||
free(item->vertex);
|
||||
}
|
||||
if (item->fragment) {
|
||||
free(item->fragment);
|
||||
}
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL void ReloadShaders(struct Game* game, bool force) {
|
||||
struct libsuperderpy_list* list = game->_priv.shaders;
|
||||
PrintConsole(game, "Reloading shaders...");
|
||||
while (list) {
|
||||
struct ShaderListItem* item = list->data;
|
||||
if (!item->loaded || force) {
|
||||
PrintConsole(game, "V:%s, F:%s", item->vertex, item->fragment);
|
||||
AttachToShader(game, item->shader, ALLEGRO_VERTEX_SHADER, item->vertex);
|
||||
AttachToShader(game, item->shader, ALLEGRO_PIXEL_SHADER, item->fragment);
|
||||
|
||||
if (!al_build_shader(item->shader)) {
|
||||
const char* log = al_get_shader_log(item->shader);
|
||||
if (log) {
|
||||
FatalError(game, false, "%s", log);
|
||||
}
|
||||
}
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
PrintConsole(game, "Shaders reloaded.");
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL void DestroyShaders(struct Game* game) {
|
||||
PrintConsole(game, "Destroying shaders...");
|
||||
while (game->_priv.shaders) {
|
||||
struct ShaderListItem* item = game->_priv.shaders->data;
|
||||
al_destroy_shader(item->shader);
|
||||
if (item->vertex) {
|
||||
free(item->vertex);
|
||||
}
|
||||
if (item->fragment) {
|
||||
free(item->fragment);
|
||||
}
|
||||
struct libsuperderpy_list* prev = game->_priv.shaders;
|
||||
game->_priv.shaders = game->_priv.shaders->next;
|
||||
free(prev);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue