mirror of
https://gitlab.com/dosowisko.net/libsuperderpy.git
synced 2025-02-12 16:14:23 +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) {
|
SYMBOL_INTERNAL void ReloadGamestates(struct Game* game) {
|
||||||
struct Gamestate* tmp = game->_priv.gamestates;
|
struct Gamestate* tmp = game->_priv.gamestates;
|
||||||
|
ReloadShaders(game, true);
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if (tmp->loaded) {
|
if (tmp->loaded) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
|
@ -355,7 +356,21 @@ static bool Identity(struct libsuperderpy_list* elem, void* data) {
|
||||||
return elem->data == 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;
|
struct libsuperderpy_list *prev = NULL, *tmp = *list, *start;
|
||||||
void* d = NULL;
|
void* d = NULL;
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
|
@ -506,6 +521,7 @@ SYMBOL_INTERNAL void PauseExecution(struct Game* game) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_INTERNAL void ResumeExecution(struct Game* game) {
|
SYMBOL_INTERNAL void ResumeExecution(struct Game* game) {
|
||||||
|
ReloadShaders(game, true);
|
||||||
PrintConsole(game, "DEBUG: reloading the gamestates...");
|
PrintConsole(game, "DEBUG: reloading the gamestates...");
|
||||||
struct Gamestate* tmp = game->_priv.gamestates;
|
struct Gamestate* tmp = game->_priv.gamestates;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
|
|
|
@ -80,7 +80,8 @@ void* AddGarbage(struct Game* game, void* data);
|
||||||
void ClearGarbage(struct Game* game);
|
void ClearGarbage(struct Game* game);
|
||||||
void ClearScreen(struct Game* game);
|
void ClearScreen(struct Game* game);
|
||||||
struct libsuperderpy_list* AddToList(struct libsuperderpy_list* list, void* data);
|
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 AddTimeline(struct Game* game, struct Timeline* timeline);
|
||||||
void RemoveTimeline(struct Game* game, struct Timeline* timeline);
|
void RemoveTimeline(struct Game* game, struct Timeline* timeline);
|
||||||
void DrawTimelines(struct Game* game);
|
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);
|
char* GetLibraryPath(struct Game* game, char* filename);
|
||||||
void PauseExecution(struct Game* game);
|
void PauseExecution(struct Game* game);
|
||||||
void ResumeExecution(struct Game* game);
|
void ResumeExecution(struct Game* game);
|
||||||
|
void ReloadShaders(struct Game* game, bool force);
|
||||||
|
void DestroyShaders(struct Game* game);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -420,8 +420,8 @@ SYMBOL_INTERNAL void libsuperderpy_mainloop(void* g) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
al_set_new_bitmap_flags(data.bitmap_flags);
|
al_set_new_bitmap_flags(data.bitmap_flags);
|
||||||
// TODO: compile shaders
|
|
||||||
al_convert_memory_bitmaps();
|
al_convert_memory_bitmaps();
|
||||||
|
ReloadShaders(game, false);
|
||||||
game->_priv.loading.loaded++;
|
game->_priv.loading.loaded++;
|
||||||
|
|
||||||
tmp->loaded = true;
|
tmp->loaded = true;
|
||||||
|
@ -631,6 +631,7 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
|
||||||
if (game->handlers.destroy) {
|
if (game->handlers.destroy) {
|
||||||
(*game->handlers.destroy)(game);
|
(*game->handlers.destroy)(game);
|
||||||
}
|
}
|
||||||
|
DestroyShaders(game);
|
||||||
|
|
||||||
ClearScreen(game);
|
ClearScreen(game);
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
|
|
110
src/shader.c
110
src/shader.c
|
@ -22,39 +22,101 @@
|
||||||
#include <allegro5/allegro.h>
|
#include <allegro5/allegro.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
ALLEGRO_SHADER* CreateShader(struct Game* game, const char* vertex, const char* fragment) {
|
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;
|
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);
|
PrintConsole(game, "Creating shader V:%s F:%s...", vertex, fragment);
|
||||||
|
|
||||||
ALLEGRO_SHADER* shader = al_create_shader(ALLEGRO_SHADER_GLSL);
|
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;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyShader(struct Game* game, ALLEGRO_SHADER* shader) {
|
static bool ShaderIdentity(struct libsuperderpy_list* item, void* shader) {
|
||||||
RemoveFromList(&game->_priv.shaders, shader, NULL);
|
return ((struct ShaderListItem*)item->data)->shader == shader;
|
||||||
al_destroy_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