teach begin_draw_texture to draw an arbitrary fragment

this is a tiny intermediate step towards a more flexible sprite system

it also seems to improve performance a little bit, though that's moot
since we're going to rewrite this part later together with most of the
rendering code anyway.
This commit is contained in:
Andrei Alexeyev 2018-01-29 05:37:05 +02:00
parent 52dbb99343
commit 48649b2c24
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
6 changed files with 74 additions and 50 deletions

View file

@ -101,6 +101,7 @@ void aniplayer_update(AniPlayer *plr) {
void play_animation_frame(Animation *ani, float x, float y, int frame) {
int mirror = frame/(ani->cols*ani->rows);
frame = frame%(ani->cols*ani->rows);
if(mirror) {
glPushMatrix();
glCullFace(GL_FRONT);

View file

@ -99,30 +99,15 @@ void draw_animation(float x, float y, int col, int row, const char *name) {
}
void draw_animation_p(float x, float y, int col, int row, Animation *ani) {
glBindTexture(GL_TEXTURE_2D, ani->tex->gltex);
float frame_w = (float)ani->tex->w / ani->cols;
float frame_h = (float)ani->tex->h / ani->rows;
float s = (float)ani->tex->w/ani->cols/ani->tex->truew;
float t = ((float)ani->tex->h)/ani->tex->trueh/(float)ani->rows;
glPushMatrix();
if(x || y)
glTranslatef(x,y,0);
if(ani->w != 1 || ani->h != 1)
glScalef(ani->w,ani->h, 1);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glScalef(s,t,1);
if(col || row)
glTranslatef(col, row, 0);
glMatrixMode(GL_MODELVIEW);
begin_draw_texture(
(FloatRect){ x, y, ani->w, ani->h },
(FloatRect){ col*frame_w, row*frame_h, frame_w, frame_h },
ani->tex
);
draw_quad();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
end_draw_texture();
}

View file

@ -309,54 +309,81 @@ void draw_texture(float x, float y, const char *name) {
draw_texture_p(x, y, get_tex(name));
}
void begin_draw_texture(float x, float y, float w, float h, Texture *tex) {
static struct draw_texture_state {
bool drawing;
bool texture_matrix_tainteed;
} draw_texture_state;
void begin_draw_texture(FloatRect dest, FloatRect frag, Texture *tex) {
if(draw_texture_state.drawing) {
log_fatal("Already drawing. Did you forget to call end_draw_texture, or call me on the wrong thread?");
}
draw_texture_state.drawing = true;
glBindTexture(GL_TEXTURE_2D, tex->gltex);
glPushMatrix();
float wq = ((float)tex->w)/tex->truew;
float hq = ((float)tex->h)/tex->trueh;
float x = dest.x;
float y = dest.y;
float w = dest.w;
float h = dest.h;
float s = frag.w/tex->truew;
float t = frag.h/tex->trueh;
if(s != 1 || t != 1 || frag.x || frag.y) {
draw_texture_state.texture_matrix_tainteed = true;
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1.0/tex->truew, 1.0/tex->trueh, 1);
if(frag.x || frag.y) {
glTranslatef(frag.x, frag.y, 0);
}
if(s != 1 || t != 1) {
glScalef(frag.w, frag.h, 1);
}
glMatrixMode(GL_MODELVIEW);
}
if(x || y) {
glTranslatef(x, y, 0);
}
if(w == 0) {
w = tex->w;
}
if(h == 0) {
h = tex->h;
}
if(w != 1 || h != 1) {
glScalef(w, h, 1);
}
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
if(wq != 1 || hq != 1) {
glScalef(wq, hq, 1);
}
glMatrixMode(GL_MODELVIEW);
}
void end_draw_texture(void) {
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
if(!draw_texture_state.drawing) {
log_fatal("Not drawing. Did you forget to call begin_draw_texture, or call me on the wrong thread?");
}
if(draw_texture_state.texture_matrix_tainteed) {
draw_texture_state.texture_matrix_tainteed = false;
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
glPopMatrix();
draw_texture_state.drawing = false;
}
void draw_texture_p(float x, float y, Texture *tex) {
begin_draw_texture(x, y, 0, 0, tex);
begin_draw_texture((FloatRect){ x, y, tex->w, tex->h }, (FloatRect){ 0, 0, tex->w, tex->h }, tex);
draw_quad();
end_draw_texture();
}
void draw_texture_with_size_p(float x, float y, float w, float h, Texture *tex) {
begin_draw_texture(x, y, w, h, tex);
begin_draw_texture((FloatRect){ x, y, w, h }, (FloatRect){ 0, 0, tex->w, tex->h }, tex);
draw_quad();
end_draw_texture();
}

View file

@ -33,7 +33,7 @@ void free_texture(Texture *tex);
void draw_texture(float x, float y, const char *name);
void draw_texture_p(float x, float y, Texture *tex);
void begin_draw_texture(float x, float y, float w, float h, Texture *tex);
void begin_draw_texture(FloatRect dest, FloatRect frag, Texture *tex);
void end_draw_texture(void);
void draw_texture_with_size(float x, float y, float w, float h, const char *name);

View file

@ -364,7 +364,11 @@ void draw_stars(int x, int y, int numstars, int numfrags, int maxstars, int maxf
glUniform4fv(uniloc(shader, "back_color"), 1, clr);
glUniform1f(uniloc(shader, "fill"), 1);
begin_draw_texture(x - star_width, y, star_width, star_width, star);
begin_draw_texture(
(FloatRect){ x - star_width, y, star_width, star_width },
(FloatRect){ 0, 0, star->w, star->h },
star
);
while(i < numstars) {
glTranslatef(1, 0, 0);

View file

@ -62,6 +62,13 @@ char* ucs4_to_utf8(const uint32_t *ucs4);
// math utils
//
typedef struct FloatRect {
float x;
float y;
float w;
float h;
} FloatRect;
#include <complex.h>
// These definitions are common but non-standard, so we provide our own