diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2021-12-25 22:01:57 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2021-12-25 22:01:57 -0800 |
commit | 189eac273ba14c8ca0d22b31182b030ccc4c7756 (patch) | |
tree | c49ac8c15404cb68ae4ccb4cf2a2ba0f7417c705 | |
parent | 8da03aff8bca547bb83f1b049a65232f03123d5a (diff) |
*: introduce a projection matrix and winmodesrev3
The bulk of this is mechanical wiring up of a projection_x to all
the nodes.
But this also introduces maintenance of the projection_x, with
aspect-ratio preservation in two of the modes: WINDOWED and
FULLSCREEN, with the previously default stretched-to-fill
fullscreen mode now relegated to a third FILLSCREEN winmode.
The default at startup is now an aspect ratio-preserving windowed
mode.
Simply press the 'f' key at any time to cycle through them.
This was mostly done in sars to provide a source-available test
for reproducing a fullscreen SDL2 bug I filed @
https://github.com/libsdl-org/SDL/issues/5139
Otherwise it's pretty silly to bother with doing anything on
sars... but it is a handy little mule for such things.
-rw-r--r-- | src/adult-node.c | 4 | ||||
-rw-r--r-- | src/adult-node.h | 2 | ||||
-rw-r--r-- | src/baby-node.c | 4 | ||||
-rw-r--r-- | src/baby-node.h | 2 | ||||
-rw-r--r-- | src/digit-node.c | 4 | ||||
-rw-r--r-- | src/digit-node.h | 2 | ||||
-rw-r--r-- | src/game.c | 22 | ||||
-rw-r--r-- | src/hungrycat-node.c | 4 | ||||
-rw-r--r-- | src/hungrycat-node.h | 2 | ||||
-rw-r--r-- | src/hungrycat.c | 2 | ||||
-rw-r--r-- | src/plasma-node.c | 12 | ||||
-rw-r--r-- | src/plasma-node.h | 3 | ||||
-rw-r--r-- | src/sars.c | 98 | ||||
-rw-r--r-- | src/sars.h | 13 | ||||
-rw-r--r-- | src/tex-node.c | 10 | ||||
-rw-r--r-- | src/tex-node.h | 4 | ||||
-rw-r--r-- | src/tex.c | 12 | ||||
-rw-r--r-- | src/tex.h | 2 | ||||
-rw-r--r-- | src/tv-node.c | 4 | ||||
-rw-r--r-- | src/tv-node.h | 2 | ||||
-rw-r--r-- | src/virus-node.c | 4 | ||||
-rw-r--r-- | src/virus-node.h | 2 |
22 files changed, 152 insertions, 62 deletions
diff --git a/src/adult-node.c b/src/adult-node.c index f314715..d3cdaf7 100644 --- a/src/adult-node.c +++ b/src/adult-node.c @@ -23,10 +23,10 @@ static tex_t *adult_tex; -stage_t * adult_node_new(stage_conf_t *conf, m4f_t *model_x) +stage_t * adult_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x) { if (!adult_tex) adult_tex = tex_new(gfx_adult.width, gfx_adult.height, gfx_adult.pixel_data); - return tex_node_new_tex(conf, adult_tex, model_x); + return tex_node_new_tex(conf, adult_tex, projection_x, model_x); } diff --git a/src/adult-node.h b/src/adult-node.h index 151014f..848a92d 100644 --- a/src/adult-node.h +++ b/src/adult-node.h @@ -20,6 +20,6 @@ typedef struct stage_conf_t stage_conf_t; typedef struct m4f_t m4f_t; -stage_t * adult_node_new(stage_conf_t *conf, m4f_t *model_x); +stage_t * adult_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x); #endif diff --git a/src/baby-node.c b/src/baby-node.c index 8f49670..c7befca 100644 --- a/src/baby-node.c +++ b/src/baby-node.c @@ -23,10 +23,10 @@ static tex_t *baby_tex; -stage_t * baby_node_new(stage_conf_t *conf, m4f_t *model_x) +stage_t * baby_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x) { if (!baby_tex) baby_tex = tex_new(gfx_baby.width, gfx_baby.height, gfx_baby.pixel_data); - return tex_node_new_tex(conf, baby_tex, model_x); + return tex_node_new_tex(conf, baby_tex, projection_x, model_x); } diff --git a/src/baby-node.h b/src/baby-node.h index f6cc02e..0eba576 100644 --- a/src/baby-node.h +++ b/src/baby-node.h @@ -20,6 +20,6 @@ typedef struct stage_conf_t stage_conf_t; typedef struct m4f_t m4f_t; -stage_t * baby_node_new(stage_conf_t *conf, m4f_t *model_x); +stage_t * baby_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x); #endif diff --git a/src/digit-node.c b/src/digit-node.c index a5e2795..8d970e2 100644 --- a/src/digit-node.c +++ b/src/digit-node.c @@ -49,12 +49,12 @@ static tex_t *digits_tex[10]; #define DIGIT_WIDTH 184 #define DIGIT_HEIGHT 288 -stage_t * digit_node_new(stage_conf_t *conf, unsigned digit, m4f_t *model_x) +stage_t * digit_node_new(stage_conf_t *conf, unsigned digit, m4f_t *projection_x, m4f_t *model_x) { assert(digit < 10); if (!digits_tex[digit]) digits_tex[digit] = tex_new(DIGIT_WIDTH, DIGIT_HEIGHT, digits_pixels[digit]); - return tex_node_new_tex(conf, digits_tex[digit], model_x); + return tex_node_new_tex(conf, digits_tex[digit], projection_x, model_x); } diff --git a/src/digit-node.h b/src/digit-node.h index 9e686de..fd94bdd 100644 --- a/src/digit-node.h +++ b/src/digit-node.h @@ -20,6 +20,6 @@ typedef struct stage_conf_t stage_conf_t; typedef struct m4f_t m4f_t; -stage_t * digit_node_new(stage_conf_t *conf, unsigned digit, m4f_t *model_x); +stage_t * digit_node_new(stage_conf_t *conf, unsigned digit, m4f_t *projection_x, m4f_t *model_x); #endif @@ -124,6 +124,7 @@ union entity_t { typedef struct game_t { game_state_t state; + sars_t *sars; stage_t *stage; stage_t *game_node; stage_t *babies_node; @@ -179,7 +180,7 @@ static adult_t * adult_new(game_t *game, stage_t *parent) fatal_if(!adult, "unale to allocate adult_t"); adult->entity.type = ENTITY_TYPE_ADULT; - adult->entity.node = adult_node_new(&(stage_conf_t){ .parent = parent, .name = "adult", .layer = 3, .alpha = 1.f }, &adult->entity.model_x); + adult->entity.node = adult_node_new(&(stage_conf_t){ .parent = parent, .name = "adult", .layer = 3, .alpha = 1.f }, &game->sars->projection_x, &adult->entity.model_x); adult->entity.scale = GAME_ADULT_SCALE; entity_update_x(game, &adult->entity); @@ -195,7 +196,7 @@ static baby_t * baby_new(game_t *game, stage_t *parent) fatal_if(!baby, "unale to allocate baby_t"); baby->entity.type = ENTITY_TYPE_BABY; - baby->entity.node = baby_node_new(&(stage_conf_t){ .parent = parent, .name = "baby", .active = 1, .alpha = 1.f }, &baby->entity.model_x); + baby->entity.node = baby_node_new(&(stage_conf_t){ .parent = parent, .name = "baby", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &baby->entity.model_x); baby->entity.scale = GAME_BABY_SCALE; baby->entity.position.x = randf(); baby->entity.position.y = randf(); @@ -213,7 +214,7 @@ static tv_t * tv_new(game_t *game, stage_t *parent) fatal_if(!tv, "unale to allocate tv_t"); tv->entity.type = ENTITY_TYPE_TV; - tv->entity.node = tv_node_new(&(stage_conf_t){ .parent = parent, .name = "tv", .layer = 1, .alpha = 1.f }, &tv->entity.model_x); + tv->entity.node = tv_node_new(&(stage_conf_t){ .parent = parent, .name = "tv", .layer = 1, .alpha = 1.f }, &game->sars->projection_x, &tv->entity.model_x); tv->entity.scale = GAME_TV_SCALE; entity_update_x(game, &tv->entity); @@ -236,7 +237,7 @@ static virus_t * virus_new(game_t *game, stage_t *parent) fatal_if(!virus, "unale to allocate virus_t"); virus->entity.type = ENTITY_TYPE_VIRUS; - virus->entity.node = virus_node_new(&(stage_conf_t){ .parent = parent, .name = "virus", .alpha = 1.f }, &virus->entity.model_x); + virus->entity.node = virus_node_new(&(stage_conf_t){ .parent = parent, .name = "virus", .alpha = 1.f }, &game->sars->projection_x, &virus->entity.model_x); virus->entity.scale = GAME_VIRUS_SCALE; randomize_virus(virus); entity_update_x(game, &virus->entity); @@ -265,7 +266,7 @@ static ix2_search_status_t virus_search(void *cb_context, ix2_object_t *ix2_obje switch (entity->any.type) { case ENTITY_TYPE_BABY: /* convert baby into inanimate virus (off the viruses array) */ - (void) virus_node_new(&(stage_conf_t){ .stage = entity->any.node, .replace = 1, .name = "baby-virus", .active = 1, .alpha = 1.f }, &entity->any.model_x); + (void) virus_node_new(&(stage_conf_t){ .stage = entity->any.node, .replace = 1, .name = "baby-virus", .active = 1, .alpha = 1.f }, &search->game->sars->projection_x, &entity->any.model_x); sfx_play(sfx.baby_infected); entity->any.type = ENTITY_TYPE_VIRUS; @@ -277,7 +278,7 @@ static ix2_search_status_t virus_search(void *cb_context, ix2_object_t *ix2_obje case ENTITY_TYPE_ADULT: /* convert adult into inanimate virus (off the viruses array) */ - (void) virus_node_new(&(stage_conf_t){ .stage = entity->any.node, .replace = 1, .name = "adult-virus", .active = 1, .alpha = 1.f }, &entity->any.model_x); + (void) virus_node_new(&(stage_conf_t){ .stage = entity->any.node, .replace = 1, .name = "adult-virus", .active = 1, .alpha = 1.f }, &search->game->sars->projection_x, &entity->any.model_x); sfx_play(sfx.adult_infected); search->game->state = GAME_STATE_OVER; return IX2_SEARCH_STOP_HIT; @@ -370,11 +371,11 @@ static ix2_search_status_t adult_search(void *cb_context, ix2_object_t *ix2_obje return IX2_SEARCH_MORE_MISS; /* convert adult into inanimate virus (off the viruses array) */ - (void) virus_node_new(&(stage_conf_t){ .stage = game->adult->entity.node, .replace = 1, .name = "adult-virus", .active = 1, .alpha = 1.f }, &game->adult->entity.model_x); + (void) virus_node_new(&(stage_conf_t){ .stage = game->adult->entity.node, .replace = 1, .name = "adult-virus", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &game->adult->entity.model_x); sfx_play(sfx.adult_infected); if (game->adult->holding) { - (void) virus_node_new(&(stage_conf_t){ .stage = game->adult->holding->any.node, .replace = 1, .name = "baby-virus", .active = 1, .alpha = 1.f }, &game->adult->holding->any.model_x); + (void) virus_node_new(&(stage_conf_t){ .stage = game->adult->holding->any.node, .replace = 1, .name = "baby-virus", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &game->adult->holding->any.model_x); sfx_play(sfx.baby_infected); } game->state = GAME_STATE_OVER; @@ -483,7 +484,7 @@ static void show_score(game_t *game) for (unsigned i = 1000000000, pos = 0; i > 0; score %= i, i /= 10, pos++) { unsigned v = score / i; - digit_node_new(&(stage_conf_t){ .parent = game->score_node, .name = "score-digit", .active = 1, .alpha = 1.f }, v, &game->score_digits_x[pos]); + digit_node_new(&(stage_conf_t){ .parent = game->score_node, .name = "score-digit", .active = 1, .alpha = 1.f }, v, &game->sars->projection_x, &game->score_digits_x[pos]); } stage_set_active(game->score_node, 1); @@ -500,8 +501,9 @@ static void * game_init(play_t *play, int argc, char *argv[]) game = calloc(1, sizeof(game_t)); fatal_if(!game, "Unable to allocate game_t"); + game->sars = sars; game->stage = sars->stage; - game->plasma_node = plasma_node_new(&(stage_conf_t){ .parent = sars->stage, .name = "plasma", .alpha = 1 }); + game->plasma_node = plasma_node_new(&(stage_conf_t){ .parent = sars->stage, .name = "plasma", .alpha = 1 }, &sars->projection_x); game->ix2 = ix2_new(NULL, 4, 4, 1 /* increase for nested searches */); diff --git a/src/hungrycat-node.c b/src/hungrycat-node.c index da78ed9..b880eda 100644 --- a/src/hungrycat-node.c +++ b/src/hungrycat-node.c @@ -21,7 +21,7 @@ #include "tex-node.h" -stage_t * hungrycat_node_new(stage_conf_t *conf, m4f_t *model_x) +stage_t * hungrycat_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x) { - return tex_node_new_mem(conf, gfx_hungrycat.width, gfx_hungrycat.height, gfx_hungrycat.pixel_data, model_x); + return tex_node_new_mem(conf, gfx_hungrycat.width, gfx_hungrycat.height, gfx_hungrycat.pixel_data, projection_x, model_x); } diff --git a/src/hungrycat-node.h b/src/hungrycat-node.h index 8c5839f..31ba133 100644 --- a/src/hungrycat-node.h +++ b/src/hungrycat-node.h @@ -20,6 +20,6 @@ typedef struct stage_conf_t stage_conf_t; typedef struct m4f_t m4f_t; -stage_t * hungrycat_node_new(stage_conf_t *conf, m4f_t *model_x); +stage_t * hungrycat_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x); #endif diff --git a/src/hungrycat.c b/src/hungrycat.c index bae9c10..8457d8a 100644 --- a/src/hungrycat.c +++ b/src/hungrycat.c @@ -57,7 +57,7 @@ static void * hungrycat_init(play_t *play, int argc, char *argv[]) hungrycat = calloc(1, sizeof(hungrycat_t)); fatal_if(!hungrycat, "Unable to allocate hungrycat_t"); - hungrycat->node = hungrycat_node_new(&(stage_conf_t){ .parent = sars->stage, .name = "hungrycat", .active = 1 }, &hungrycat->model_x); + hungrycat->node = hungrycat_node_new(&(stage_conf_t){ .parent = sars->stage, .name = "hungrycat", .active = 1 }, &sars->projection_x, &hungrycat->model_x); fatal_if(!hungrycat->node, "Unable to create hungrycat->node"); hungrycat->model_x = m4f_identity(); diff --git a/src/plasma-node.c b/src/plasma-node.c index 1bc0e40..1eb4c7a 100644 --- a/src/plasma-node.c +++ b/src/plasma-node.c @@ -22,19 +22,21 @@ #include "glad.h" #include "plasma-node.h" #include "shader-node.h" +#include "m4f.h" static const char *plasma_vs = "" "#version 120\n" + "uniform mat4 projection_x;" + "attribute vec3 vertex;" "attribute vec2 texcoord;" "void main()" "{" " gl_TexCoord[0].xy = texcoord;" - //" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" - " gl_Position = vec4(vertex, 1.f);" + " gl_Position = projection_x * vec4(vertex, 1.f);" "}" ""; @@ -78,16 +80,18 @@ static void plasma_uniforms(void *uniforms_ctxt, void *render_ctxt, unsigned n_u glUniform1f(uniforms[0], alpha); glUniform1f(uniforms[1], play_ticks(play, PLAY_TICKS_TIMER0) * .001f); // FIXME KLUDGE ALERT + glUniformMatrix4fv(uniforms[2], 1, GL_FALSE, &model_x->m[0][0]); } /* create plasma rendering stage */ -stage_t * plasma_node_new(const stage_conf_t *conf) +stage_t * plasma_node_new(const stage_conf_t *conf, m4f_t *projection_x) { - return shader_node_new_src(conf, plasma_vs, plasma_fs, NULL, plasma_uniforms, NULL, 2, + return shader_node_new_src(conf, plasma_vs, plasma_fs, projection_x, plasma_uniforms, NULL, 3, (const char *[]){ "alpha", "time", + "projection_x", } ); } diff --git a/src/plasma-node.h b/src/plasma-node.h index 1607ece..2c52431 100644 --- a/src/plasma-node.h +++ b/src/plasma-node.h @@ -17,9 +17,10 @@ #ifndef _PLASMA_NODE_H #define _PLASMA_NODE_H +typedef struct m4f_t m4f_t; typedef struct stage_t stage_t; typedef struct stage_conf_t stage_conf_t; -stage_t * plasma_node_new(const stage_conf_t *conf); +stage_t * plasma_node_new(const stage_conf_t *conf, m4f_t *projection_x); #endif @@ -21,18 +21,14 @@ #include "clear-node.h" #include "glad.h" +#include "m4f-3dx.h" #include "macros.h" #include "sars.h" #define SARS_DEFAULT_WIDTH 800 #define SARS_DEFAULT_HEIGHT 600 -//#define SARS_WINDOW_FLAGS (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL) #define SARS_WINDOW_FLAGS (SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI) -#if 0 -#define SARS_ASPECT_RATIO .7 -#endif - void sars_canvas_size(sars_t *sars, int *res_width, int *res_height) { @@ -120,15 +116,78 @@ uint32_t sars_viewport_id(sars_t *sars) } -void sars_toggle_fullscreen(sars_t *sars) +/* produce a boxed transformation matrix for the current screen/window dimensions */ +static m4f_t sars_boxed_projection_x(sars_t *sars) { - if (sars->windowed) { - if (!SDL_SetWindowFullscreen(sars->window, SDL_WINDOW_FULLSCREEN_DESKTOP)) - sars->windowed = 0; + static const float desired_ratio = (float)SARS_DEFAULT_WIDTH / (float)SARS_DEFAULT_HEIGHT; + v3f_t scale = { .x = 1.f, .y = 1.f, .z = 1.f }; + float display_ratio; + int w, h; + + sars_viewport_size(sars, &w, &h); + assert(w > 0 && h > 0); + + display_ratio = (float)w / (float)h; + + if (desired_ratio <= display_ratio) { + /* display is equal to or wider than desired, "pillarbox" / X-padded */ + scale.x = (float)h * desired_ratio / (float)w; } else { - if (!SDL_SetWindowFullscreen(sars->window, 0)) - sars->windowed = 1; + /* display is taller than desired, "letterbox" / Y-padded */ + scale.y = (float)w * (1.f / desired_ratio) / (float)h; + } + + return m4f_scale(NULL, &scale); +} + + +static void sars_update_projection_x(sars_t *sars) +{ + assert(sars); + + if (sars->winmode == SARS_WINMODE_FILLSCREEN) + sars->projection_x = m4f_identity(); + else + sars->projection_x = sars_boxed_projection_x(sars); +} + + +sars_winmode_t sars_winmode_set(sars_t *sars, sars_winmode_t winmode) +{ + assert(sars); + + if (sars->winmode == winmode) + return sars->winmode; + + switch (winmode) { + case SARS_WINMODE_WINDOW: + if (SDL_SetWindowFullscreen(sars->window, 0)) + return sars->winmode; + break; + + case SARS_WINMODE_FULLSCREEN: + if (sars->winmode == SARS_WINMODE_WINDOW) { + if (SDL_SetWindowFullscreen(sars->window, SDL_WINDOW_FULLSCREEN_DESKTOP)) + return sars->winmode; + } + break; + + case SARS_WINMODE_FILLSCREEN: + if (sars->winmode == SARS_WINMODE_WINDOW) { + if (SDL_SetWindowFullscreen(sars->window, SDL_WINDOW_FULLSCREEN_DESKTOP)) + return sars->winmode; + } + break; + + default: + assert(0); } + + sars->winmode = winmode; + + sars_update_projection_x(sars); + + return sars->winmode; } @@ -145,16 +204,17 @@ static void * sars_init(play_t *play, int argc, char *argv[]) (void) clear_node_new(&(stage_conf_t){.parent = sars->stage, .name = "gl-clear-sars", .active = 1}); sars->window_width = SARS_DEFAULT_WIDTH; - sars->window_height = SARS_DEFAULT_HEIGHT; + sars->window_height = SARS_DEFAULT_HEIGHT; if (argc > 1) { /* for now just support --window [WxH] */ if (!strcasecmp(argv[1], "--window")) { - sars->windowed = 1; + sars->winmode = SARS_WINMODE_WINDOW; /* this is kinda redundant since we default to windowed now */ if (argc > 2) sscanf(argv[2], "%ux%u", &sars->window_width, &sars->window_height); } + /* TODO: add --fullscreen? */ } fatal_if(SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) < 0, @@ -198,7 +258,7 @@ static void * sars_init(play_t *play, int argc, char *argv[]) SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, sars->window_width, sars->window_height, - SARS_WINDOW_FLAGS | (sars->windowed ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP)); + SARS_WINDOW_FLAGS | (sars->winmode == SARS_WINMODE_WINDOW ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP)); if (!sars->window) { fatal_if(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0) < 0, @@ -210,7 +270,7 @@ static void * sars_init(play_t *play, int argc, char *argv[]) SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, sars->window_width, sars->window_height, - SARS_WINDOW_FLAGS | (sars->windowed ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP)); + SARS_WINDOW_FLAGS | (sars->winmode == SARS_WINMODE_WINDOW ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP)); fatal_if(!sars->window, "Unable to create SDL window"); @@ -234,6 +294,9 @@ static void * sars_init(play_t *play, int argc, char *argv[]) #ifdef MSAA_RENDER_TARGET glEnable(GL_MULTISAMPLE); #endif + + sars_update_projection_x(sars); + return sars; } @@ -270,8 +333,13 @@ void sars_dispatch(play_t *play, void *context, SDL_Event *event) */ sars_canvas_size(sars, &w, &h); glViewport(0, 0, w, h); + sars_update_projection_x(sars); stage_dirty(sars->stage); } + + /* cycle fullscreen/windowed winmodes */ + if (event->type == SDL_KEYDOWN && event->key.keysym.sym == SDLK_f) + sars_winmode_set(sars, (sars->winmode + 1) % SARS_WINMODE_CNT); } @@ -30,12 +30,21 @@ typedef enum sars_context_t { SARS_CONTEXT_CNT } sars_context_t; +typedef enum sars_winmode_t { + SARS_WINMODE_WINDOW, /* windowed in the ideal aspect ratio (may be letterboxed if resized or --window WxH) */ + SARS_WINMODE_FULLSCREEN, /* fullscreened, in the ideal aspect ratio (likely letterboxed) */ + SARS_WINMODE_FILLSCREEN, /* fullscreened, in the screen's aspect ratio (likely stretched) */ + SARS_WINMODE_CNT +} sars_winmode_t; + typedef struct sars_t { SDL_Window *window; SDL_GLContext *gl; stage_t *stage; unsigned window_width, window_height; - unsigned windowed:1; + sars_winmode_t winmode; + + m4f_t projection_x; } sars_t; void sars_canvas_size(sars_t *sars, int *res_width, int *res_height); @@ -45,8 +54,8 @@ void sars_viewport_size(sars_t *sars, int *res_width, int *res_height); void sars_viewport_to_ndc(sars_t *sars, int x, int y, float *res_x, float *res_y); void sars_viewport_from_ndc(sars_t *sars, float x, float y, int *res_x, int *res_y); uint32_t sars_viewport_id(sars_t *sars); -void sars_toggle_fullscreen(sars_t *sars); void sars_render(play_t *play, void *context); void sars_dispatch(play_t *play, void *context, SDL_Event *event); +sars_winmode_t sars_winmode_set(sars_t *sars, sars_winmode_t winmode); #endif diff --git a/src/tex-node.c b/src/tex-node.c index 6d049ca..a3e0830 100644 --- a/src/tex-node.c +++ b/src/tex-node.c @@ -32,6 +32,7 @@ typedef struct tex_node_t { tex_t *tex; + m4f_t *projection_x; m4f_t *model_x; } tex_node_t; @@ -44,7 +45,7 @@ static void tex_node_render(const stage_t *stage, void *object, float alpha, voi assert(stage); assert(tex_node); - tex_render(tex_node->tex, alpha, tex_node->model_x); + tex_render(tex_node->tex, alpha, tex_node->projection_x, tex_node->model_x); } @@ -65,7 +66,7 @@ static const stage_ops_t tex_node_ops = { /* retun a tex node from a reusable refcounted tex instance */ -stage_t * tex_node_new_tex(stage_conf_t *conf, tex_t *tex, m4f_t *model_x) +stage_t * tex_node_new_tex(stage_conf_t *conf, tex_t *tex, m4f_t *projection_x, m4f_t *model_x) { tex_node_t *tex_node; stage_t *s; @@ -79,6 +80,7 @@ stage_t * tex_node_new_tex(stage_conf_t *conf, tex_t *tex, m4f_t *model_x) fatal_if(!s, "Unable to create stage \"%s\"", conf->name); tex_node->tex = tex_ref(tex); + tex_node->projection_x = projection_x; tex_node->model_x = model_x; return s; @@ -89,10 +91,10 @@ stage_t * tex_node_new_tex(stage_conf_t *conf, tex_t *tex, m4f_t *model_x) /* return a tex node from a pix array * the pixels are used in-place and no duplicate is made. */ -stage_t * tex_node_new_mem(stage_conf_t *conf, int width, int height, const unsigned char *buf, m4f_t *model_x) +stage_t * tex_node_new_mem(stage_conf_t *conf, int width, int height, const unsigned char *buf, m4f_t *projection_x, m4f_t *model_x) { tex_t *tex = tex_new(width, height, buf); - stage_t *stage = tex_node_new_tex(conf, tex_new(width, height, buf), model_x); + stage_t *stage = tex_node_new_tex(conf, tex_new(width, height, buf), projection_x, model_x); tex_free(tex); diff --git a/src/tex-node.h b/src/tex-node.h index 59c731b..d9a7f3f 100644 --- a/src/tex-node.h +++ b/src/tex-node.h @@ -21,7 +21,7 @@ typedef struct m4f_t m4f_t; typedef struct stage_t stage_t; typedef struct tex_t tex_t; -stage_t * tex_node_new_tex(stage_conf_t *conf, tex_t *tex, m4f_t *model_x); -stage_t * tex_node_new_mem(stage_conf_t *conf, int width, int height, const unsigned char *buf, m4f_t *model_x); +stage_t * tex_node_new_tex(stage_conf_t *conf, tex_t *tex, m4f_t *projection_x, m4f_t *model_x); +stage_t * tex_node_new_mem(stage_conf_t *conf, int width, int height, const unsigned char *buf, m4f_t *projection_x, m4f_t *model_x); #endif @@ -54,6 +54,7 @@ static const char *tex_vs = "" "#version 120\n" "uniform mat4 model_x;" + "uniform mat4 projection_x;" "attribute vec3 vertex;" "attribute vec2 texcoord;" @@ -61,7 +62,7 @@ static const char *tex_vs = "" "void main()" "{" " gl_TexCoord[0].xy = texcoord;" - " gl_Position = model_x * vec4(vertex, 1.f);" + " gl_Position = projection_x * model_x * vec4(vertex, 1.f);" "}" ""; @@ -81,11 +82,12 @@ static const char *tex_fs = "" /* Render simply renders a texd texture onto the screen */ -void tex_render(tex_t *tex, float alpha, m4f_t *model_x) +void tex_render(tex_t *tex, float alpha, m4f_t *projection_x, m4f_t *model_x) { int *uniforms, *attributes; assert(tex); + assert(projection_x); assert(model_x); shader_use(tex_shader, NULL, &uniforms, NULL, &attributes); @@ -104,7 +106,8 @@ void tex_render(tex_t *tex, float alpha, m4f_t *model_x) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glUniform1f(uniforms[0], alpha); - glUniformMatrix4fv(uniforms[1], 1, GL_FALSE, &model_x->m[0][0]); + glUniformMatrix4fv(uniforms[1], 1, GL_FALSE, &projection_x->m[0][0]); + glUniformMatrix4fv(uniforms[2], 1, GL_FALSE, &model_x->m[0][0]); glDrawArrays(GL_TRIANGLES, 0, 6); @@ -123,9 +126,10 @@ tex_t * tex_new(int width, int height, const unsigned char *buf) if (!vbo) { /* common to all tex instances */ tex_shader = shader_pair_new(tex_vs, tex_fs, - 2, + 3, (const char *[]) { "alpha", + "projection_x", "model_x", }, 2, @@ -22,7 +22,7 @@ typedef struct tex_t tex_t; typedef struct m4f_t m4f_t; -void tex_render(tex_t *tex, float alpha, m4f_t *model_x); +void tex_render(tex_t *tex, float alpha, m4f_t *projection_x, m4f_t *model_x); tex_t * tex_new(int width, int height, const unsigned char *buf); tex_t * tex_ref(tex_t *tex); tex_t * tex_free(tex_t *tex); diff --git a/src/tv-node.c b/src/tv-node.c index 267e2e2..0ca999f 100644 --- a/src/tv-node.c +++ b/src/tv-node.c @@ -23,10 +23,10 @@ static tex_t *tv_tex; -stage_t * tv_node_new(stage_conf_t *conf, m4f_t *model_x) +stage_t * tv_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x) { if (!tv_tex) tv_tex = tex_new(gfx_tv.width, gfx_tv.height, gfx_tv.pixel_data); - return tex_node_new_tex(conf, tv_tex, model_x); + return tex_node_new_tex(conf, tv_tex, projection_x, model_x); } diff --git a/src/tv-node.h b/src/tv-node.h index 3974994..f989c77 100644 --- a/src/tv-node.h +++ b/src/tv-node.h @@ -20,6 +20,6 @@ typedef struct stage_conf_t stage_conf_t; typedef struct m4f_t m4f_t; -stage_t * tv_node_new(stage_conf_t *conf, m4f_t *model_x); +stage_t * tv_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x); #endif diff --git a/src/virus-node.c b/src/virus-node.c index bf52385..5d22718 100644 --- a/src/virus-node.c +++ b/src/virus-node.c @@ -23,10 +23,10 @@ static tex_t *virus_tex; -stage_t * virus_node_new(stage_conf_t *conf, m4f_t *model_x) +stage_t * virus_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x) { if (!virus_tex) virus_tex = tex_new(gfx_virus.width, gfx_virus.height, gfx_virus.pixel_data); - return tex_node_new_tex(conf, virus_tex, model_x); + return tex_node_new_tex(conf, virus_tex, projection_x, model_x); } diff --git a/src/virus-node.h b/src/virus-node.h index 3c437ce..a7815d1 100644 --- a/src/virus-node.h +++ b/src/virus-node.h @@ -20,6 +20,6 @@ typedef struct stage_conf_t stage_conf_t; typedef struct m4f_t m4f_t; -stage_t * virus_node_new(stage_conf_t *conf, m4f_t *model_x); +stage_t * virus_node_new(stage_conf_t *conf, m4f_t *projection_x, m4f_t *model_x); #endif |