sdl_effect: Implement mosaic and crossfade-mosaic

This commit is contained in:
kichikuou
2022-01-23 14:08:23 +09:00
parent 49e707e40e
commit 10b414fb4e
9 changed files with 113 additions and 128 deletions
+1 -3
View File
@@ -40,7 +40,6 @@
#include "sdl_core.h"
static void ec6_cb(surface_t *, surface_t *);
static void sdl_effect_cb(surface_t *, surface_t *);
static void ec_dummy_cb(surface_t *, surface_t *);
@@ -56,7 +55,6 @@ typedef struct ecopyparam ecopyparam_t;
static ecopyparam_t ecp;
#include "sprite_eupdate_perspect.c"
#include "sprite_eupdate_mosaic.c"
#include "sprite_eupdate_uneune.c"
#include "sprite_eupdate_zmbbul.c"
@@ -68,7 +66,7 @@ static entrypoint *cb[39] = {
sdl_effect_cb,
sdl_effect_cb,
sdl_effect_cb,
ec6_cb,
sdl_effect_cb,
sdl_effect_cb,
sdl_effect_cb,
sdl_effect_cb,
-35
View File
@@ -1,35 +0,0 @@
// クロスフェードモザイク
static void ec6_cb(surface_t *src, surface_t *dst) {
int curstep, maxstep = 32;
surface_t *st, *dt;
static int slices[32]={4,8,12,16,20,28,36,40,44,48,56,64,72,80,88,96,
88,80,72,64,56,48,44,40,36,28,24,20,16,12,8,4};
curstep = maxstep * (ecp.curtime - ecp.sttime)/ (ecp.edtime - ecp.sttime);
if (ecp.oldstep == curstep) {
usleep(0);
return;
}
st = sf_dup(src);
dt = sf_dup(dst);
SDL_Surface *stt = com2surface(st);
SDL_Surface *dtt = com2surface(dt);
image_Mosaic(stt, 0, 0, stt->w, stt->h, 0, 0, slices[curstep]);
image_Mosaic(dtt, 0, 0, dtt->w, dtt->h, 0, 0, slices[curstep]);
SDL_FreeSurface(stt);
SDL_FreeSurface(dtt);
gre_Blend(sf0, 0, 0, st, 0, 0, dt, 0, 0, st->width, st->height, curstep*8);
ags_updateFull();
sf_free(st);
sf_free(dt);
ecp.oldstep = curstep;
}
+4 -48
View File
@@ -458,23 +458,6 @@ static int eCopyArea23(int sx, int sy, int w, int h, int dx, int dy, int opt) {
return key;
}
static int eCopyArea24(int sx, int sy, int w, int h, int dx, int dy, int opt) {
int i, key = 0, cnt;
int waitcnt = opt == 0 ? 100 : opt;
static int slices[8]={80,70,60,48,32,16,8,4};
cnt = sdl_getTicks();
for (i = 0; i < 8; i++ ) {
cnt += waitcnt;
sdl_Mosaic(sx, sy, w, h, dx, dy, slices[i]);
ags_updateArea(dx, dy, w, h);
EC_WAIT;
}
ags_copyArea(sx, sy, w, h, dx, dy);
ags_updateArea(dx, dy, w, h);
return key;
}
#define SCA25_6_SLICE 10
static int eCopyArea25(int sx, int sy, int w, int h, int dx, int dy, int opt) {
int r, rr, x, xx, y, yy, key = 0, cnt;
@@ -569,27 +552,6 @@ static int eCopyArea26(int sx, int sy, int w, int h, int dx, int dy, int opt) {
return key;
}
static void eCopyArea32(int step) {
static void *save;
static int slices[32]={4,8,12,16,20,28,36,40,44,48,56,64,72,80,88,96,
88,80,72,64,56,48,44,40,36,28,24,20,16,12,8,4};
if (step == 0) {
save = ags_saveRegion(ecp.dx, ecp.dy, ecp.w, ecp.h);
return;
}
if (step == 64) {
ags_copyArea(ecp.sx, ecp.sy, ecp.w, ecp.h, ecp.dx, ecp.dy);
ags_updateArea(ecp.dx, ecp.dy, ecp.w, ecp.h);
ags_delRegion(save);
return;
}
ags_putRegion(save, ecp.dx, ecp.dy);
ags_copyArea_alphaBlend(ecp.sx, ecp.sy, ecp.w, ecp.h, ecp.dx, ecp.dy, step*4);
sdl_Mosaic(ecp.sx, ecp.sy, ecp.w, ecp.h, ecp.dx, ecp.dy, slices[step >> 1]);
ags_updateArea(ecp.dx, ecp.dy, ecp.w, ecp.h);
}
static int eCopyArea39(int sx, int sy, int w, int h, int dx, int dy, int opt) {
int i,dy1,dy2,sy1,sy2, key = 0, cnt;
int waitcnt = opt == 0 ? 3 : opt;
@@ -864,6 +826,8 @@ static int duration(enum nact_effect effect, int opt, SDL_Rect *rect) {
case NACT_EFFECT_BLIND_LR:
case NACT_EFFECT_BLIND_RL:
return (opt ? opt : 40) * (rect->w / 16 + 16);
case NACT_EFFECT_MOSAIC:
return (opt ? opt : 100) * 8;
case NACT_EFFECT_FADEIN:
case NACT_EFFECT_WHITEIN:
case NACT_EFFECT_FADEOUT:
@@ -871,6 +835,8 @@ static int duration(enum nact_effect effect, int opt, SDL_Rect *rect) {
return opt ? opt * 32 : 1700;
case NACT_EFFECT_CROSSFADE:
return opt ? opt * 256 : 2700;
case NACT_EFFECT_CROSSFADE_MOSAIC:
return opt ? opt * 256 : 1400;
case NACT_EFFECT_CROSSFADE_DOWN:
case NACT_EFFECT_CROSSFADE_UP:
return opt ? opt * (rect->h + 256) : 1150;
@@ -1045,22 +1011,12 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
case 23:
ret = eCopyArea23(sx, sy, w, h, dx, dy, opt);
break;
case 24:
ret = eCopyArea24(sx, sy, w, h, dx, dy, opt);
break;
case 25:
ret = eCopyArea25(sx, sy, w, h, dx, dy, opt);
break;
case 26:
ret = eCopyArea26(sx, sy, w, h, dx, dy, opt);
break;
case 32:
i.step_max = 64;
i.effect_time = opt == 0 ? 1400 : opt * 256;
i.cancel = cancel;
i.callback = eCopyArea32;
ags_fader(&i);
return;
case 39:
ret = eCopyArea39(sx, sy, w, h, dx, dy, opt);
break;
+5
View File
@@ -23,11 +23,13 @@
// Effect types of the CE command.
enum nact_effect {
NACT_EFFECT_BLIND_DOWN = 11,
NACT_EFFECT_MOSAIC = 24,
NACT_EFFECT_FADEIN = 27,
NACT_EFFECT_WHITEIN = 28,
NACT_EFFECT_FADEOUT = 29,
NACT_EFFECT_WHITEOUT = 30,
NACT_EFFECT_CROSSFADE = 31,
NACT_EFFECT_CROSSFADE_MOSAIC = 32,
NACT_EFFECT_BLIND_UP = 33,
NACT_EFFECT_BLIND_UP_DOWN = 34,
NACT_EFFECT_CROSSFADE_DOWN = 35,
@@ -53,6 +55,7 @@ enum sact_effect {
SACT_EFFECT_FADEIN = 3,
SACT_EFFECT_WHITEOUT = 4,
SACT_EFFECT_WHITEIN = 5,
SACT_EFFECT_CROSSFADE_MOSAIC = 6,
SACT_EFFECT_BLIND_DOWN = 7,
SACT_EFFECT_BLIND_LR = 8,
SACT_EFFECT_BLIND_DOWN_LR = 9,
@@ -90,6 +93,8 @@ enum sdl_effect_type {
EFFECT_CROSSFADE_UP,
EFFECT_CROSSFADE_LR,
EFFECT_CROSSFADE_RL,
EFFECT_CROSSFADE_MOSAIC,
EFFECT_MOSAIC,
EFFECT_LINEAR_BLUR,
EFFECT_LINEAR_BLUR_VERT,
EFFECT_PENTAGRAM_IN_OUT,
-25
View File
@@ -325,31 +325,6 @@ void image_copy_to_alpha(agsurface_t *dib, int sx, int sy, int w, int h, int dx,
copy_to_alpha(dib, sdata, ddata, w, h, flag);
}
/* モザイク */
void image_Mosaic(SDL_Surface *dib, int sx, int sy, int w, int h, int dx, int dy, int slice) {
SDL_Rect r = {.h = slice};
for (int y = 0; y < h; y += slice) {
if (y + slice > h)
r.h = h - y;
r.w = slice;
for (int x = 0; x < w; x += slice) {
void *src = PIXEL_AT(dib, sx + x, sy + y);
Uint32 color;
switch (dib->format->BytesPerPixel) {
case 1: color = *(BYTE *)src; break;
case 2: color = *(WORD *)src; break;
default: color = *(DWORD *)src; break;
}
r.x = dx + x;
r.y = dy + y;
if (r.x + slice > w)
r.w = w - x;
SDL_FillRect(dib, &r, color);
}
}
}
/* 16bitCGの ALPHALEVELを指定 */
BYTE *changeImage16AlphaLevel(cgdata *cg) {
WORD *new_pic = malloc(sizeof(WORD) * cg->width * cg->height), *new_pic_;
-1
View File
@@ -31,7 +31,6 @@
extern void image_setdepth(int);
extern void image_copy_from_alpha(agsurface_t *dib, int sx, int sy, int w, int h, int dx, int dy, ALPHA_DIB_COPY_TYPE flag);
extern void image_copy_to_alpha(agsurface_t *dib, int sx, int sy, int w, int h, int dx, int dy, ALPHA_DIB_COPY_TYPE flag);
extern void image_Mosaic(SDL_Surface *dib, int sx, int sy, int w, int h, int dx, int dy, int slice);
extern BYTE *changeImage16AlphaLevel(cgdata *cg);
-1
View File
@@ -65,7 +65,6 @@ extern SDL_Rect sdl_drawString(int x, int y, const char *str_utf8, BYTE col);
extern void sdl_copyArea(int sx,int sy, int w, int h, int dx, int dy);
extern void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, BYTE sp);
extern void sdl_drawImage8_fromData(cgdata *cg, int x, int y, int w, int h);
extern void sdl_Mosaic(int sx, int sy, int w, int h, int dx, int dy, int slice);
extern void sdl_wrapColor(int sx, int sy, int w, int h, BYTE cl, int rate);
extern void sdl_scaledCopyArea(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int mirror);
extern void sdl_zoom(int x, int y, int w, int h);
-9
View File
@@ -341,15 +341,6 @@ SDL_Rect sdl_drawString(int x, int y, const char *str_utf8, BYTE col) {
return font_draw_glyph(x, y, str_utf8, col);
}
void sdl_Mosaic(int sx, int sy, int w, int h, int dx, int dy, int slice) {
SDL_LockSurface(sdl_dib);
image_Mosaic(sdl_dib, sx, sy, w, h, dx, dy, slice);
SDL_UnlockSurface(sdl_dib);
}
static void setBligtness(SDL_Surface *s, int val) {
int i;
Palette256 *pal = nact->sys_pal;
+103 -6
View File
@@ -32,11 +32,13 @@
enum sdl_effect_type from_nact_effect(enum nact_effect effect) {
switch (effect) {
case NACT_EFFECT_BLIND_DOWN: return EFFECT_BLIND_DOWN;
case NACT_EFFECT_MOSAIC: return EFFECT_MOSAIC;
case NACT_EFFECT_FADEIN: return EFFECT_FADEIN;
case NACT_EFFECT_WHITEIN: return EFFECT_WHITEIN;
case NACT_EFFECT_FADEOUT: return EFFECT_FADEOUT_FROM_NEW;
case NACT_EFFECT_WHITEOUT: return EFFECT_WHITEOUT_FROM_NEW;
case NACT_EFFECT_CROSSFADE: return EFFECT_CROSSFADE;
case NACT_EFFECT_CROSSFADE_MOSAIC: return EFFECT_CROSSFADE_MOSAIC;
case NACT_EFFECT_BLIND_UP: return EFFECT_BLIND_UP;
case NACT_EFFECT_BLIND_UP_DOWN: return EFFECT_BLIND_UP_DOWN;
case NACT_EFFECT_CROSSFADE_DOWN: return EFFECT_CROSSFADE_DOWN;
@@ -64,6 +66,7 @@ enum sdl_effect_type from_sact_effect(enum sact_effect effect) {
case SACT_EFFECT_FADEIN: return EFFECT_FADEIN;
case SACT_EFFECT_WHITEOUT: return EFFECT_WHITEOUT;
case SACT_EFFECT_WHITEIN: return EFFECT_WHITEIN;
case SACT_EFFECT_CROSSFADE_MOSAIC: return EFFECT_CROSSFADE_MOSAIC;
case SACT_EFFECT_BLIND_DOWN: return EFFECT_BLIND_DOWN;
case SACT_EFFECT_BLIND_LR: return EFFECT_BLIND_LR;
case SACT_EFFECT_BLIND_DOWN_LR: return EFFECT_BLIND_DOWN_LR;
@@ -138,6 +141,11 @@ static void crossfade_free(struct sdl_effect *eff) {
free(eff);
}
static struct sdl_effect *fallback_effect_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
WARNING("Effect %d is not supported in this system. Falling back to crossfade.\n", type);
return crossfade_new(rect, old, new);
}
// EFFECT_CROSSFADE_{UP,DOWN}
static void crossfade_down_step(struct sdl_effect *eff, double progress);
@@ -291,6 +299,95 @@ static void crossfade_animation_free(struct sdl_effect *eff) {
free(eff);
}
// EFFECT_MOSAIC, EFFECT_CROSSFADE_MOSAIC
struct mosaic_effect {
struct sdl_effect eff;
SDL_Texture *tmp_old, *tmp_new, *tx_mosaic;
};
static void mosaic_step(struct sdl_effect *eff, double progress);
static void mosaic_free(struct sdl_effect *eff);
static struct sdl_effect *mosaic_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
if (!SDL_RenderTargetSupported(sdl_renderer))
return fallback_effect_new(rect, old, new, type);
struct mosaic_effect *eff = calloc(1, sizeof(struct mosaic_effect));
if (!eff)
NOMEMERR();
effect_init(&eff->eff, rect, old, new, type);
eff->tmp_old = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, rect->w, rect->h);
eff->tmp_new = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, rect->w, rect->h);
eff->tx_mosaic = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, rect->w, rect->h);
eff->eff.step = mosaic_step;
eff->eff.finish = mosaic_free;
return &eff->eff;
}
static void mosaic(SDL_Texture *src, SDL_Texture *tmp, SDL_Texture *dst, int w, int h, double scale) {
int cx = w / 2;
int cy = h / 2;
SDL_FRect fr = {
.x = cx - cx / scale,
.y = cy - cy / scale,
.w = w / scale,
.h = h / scale,
};
SDL_SetRenderTarget(sdl_renderer, tmp);
SDL_RenderCopyF(sdl_renderer, src, NULL, &fr);
SDL_Rect dstr = {
.x = w * (1 - scale) / 2,
.y = h * (1 - scale) / 2,
.w = w * scale,
.h = h * scale,
};
SDL_SetRenderTarget(sdl_renderer, dst);
#if SDL_VERSION_ATLEAST(2, 0, 12)
SDL_SetTextureScaleMode(tmp, SDL_ScaleModeNearest);
#else
// Should be okay because nearest is the default scaling mode.
#endif
SDL_RenderCopy(sdl_renderer, tmp, NULL, &dstr);
SDL_SetRenderTarget(sdl_renderer, NULL);
}
static void mosaic_step(struct sdl_effect *eff, double progress) {
struct mosaic_effect *this = (struct mosaic_effect *)eff;
if (eff->type == EFFECT_MOSAIC) {
const int max_scale = 80;
int scale = (1.0 - progress) * (max_scale - 1) + 1;
mosaic(eff->tx_new, this->tmp_new, this->tx_mosaic, eff->dst_rect.w, eff->dst_rect.h, scale);
SDL_RenderCopy(sdl_renderer, this->tx_mosaic, NULL, &eff->dst_rect);
} else if (eff->type == EFFECT_CROSSFADE_MOSAIC) {
const int max_scale = 96;
double scale = (progress < 0.5 ? progress : 1.0 - progress) * 2 * (max_scale - 1) + 1;
mosaic(eff->tx_old, this->tmp_old, this->tx_mosaic, eff->dst_rect.w, eff->dst_rect.h, scale);
SDL_RenderCopy(sdl_renderer, this->tx_mosaic, NULL, &eff->dst_rect);
mosaic(eff->tx_new, this->tmp_new, this->tx_mosaic, eff->dst_rect.w, eff->dst_rect.h, scale);
SDL_SetTextureBlendMode(this->tx_mosaic, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(this->tx_mosaic, progress * 255);
SDL_RenderCopy(sdl_renderer, this->tx_mosaic, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(this->tx_mosaic, SDL_BLENDMODE_NONE);
} else {
assert(!"Cannot happen");
}
SDL_RenderPresent(sdl_renderer);
}
static void mosaic_free(struct sdl_effect *eff) {
struct mosaic_effect *this = (struct mosaic_effect *)eff;
SDL_DestroyTexture(this->tmp_old);
SDL_DestroyTexture(this->tmp_new);
SDL_DestroyTexture(this->tx_mosaic);
effect_finish(&this->eff, true);
free(this);
}
// EFFECT_{FADE,WHITE}{OUT,IN}
static void brightness_step(struct sdl_effect *eff, double progress);
@@ -491,10 +588,8 @@ static void linear_blur_step(struct sdl_effect *eff, double progress);
static void linear_blur_free(struct sdl_effect *eff);
static struct sdl_effect *linear_blur_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
if (!SDL_RenderTargetSupported(sdl_renderer)) {
WARNING("Effect %d is not supported in this system. Falling back to crossfade.\n", type);
return crossfade_new(rect, old, new);
}
if (!SDL_RenderTargetSupported(sdl_renderer))
return fallback_effect_new(rect, old, new, type);
struct linear_blur_effect *lbe = calloc(1, sizeof(struct linear_blur_effect));
if (!lbe)
@@ -609,8 +704,7 @@ static struct sdl_effect *polygon_mask_new(SDL_Rect *rect, SDL_Surface *old, SDL
}
#endif // HAS_SDL_RenderGeometry
WARNING("Effect %d is not supported in this system. Falling back to crossfade.\n", type);
return crossfade_new(rect, old, new);
return fallback_effect_new(rect, old, new, type);
}
#if HAS_SDL_RenderGeometry
@@ -932,6 +1026,9 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
case EFFECT_CROSSFADE_LR:
case EFFECT_CROSSFADE_RL:
return crossfade_animation_new(rect, sf_old, sf_new, type);
case EFFECT_MOSAIC:
case EFFECT_CROSSFADE_MOSAIC:
return mosaic_new(rect, sf_old, sf_new, type);
case EFFECT_FADEOUT:
case EFFECT_FADEOUT_FROM_NEW:
case EFFECT_FADEIN: