stuff/fuzz.c
2022-01-01 20:50:20 +01:00

252 lines
5.1 KiB
C

/*
fuzz.c : Fancy software filter.
I was bored.
(C)2016 Marisa Kirisame, UnSX Team.
Released under the MIT license.
*/
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <time.h>
#ifndef FUZZ_FONT_PATH
#error please define FUZZ_FONT_PATH with the absolute path to a bitmap font
#endif
typedef struct
{
float r,g,b,a;
} rgbfpx_t;
typedef struct
{
Uint8 r,g,b,a;
} __attribute__((packed)) rgb8px_t;
float t = 0.f;
const int fw = 640, fh = 480;
float rn( float sdx, float sdy )
{
return cosf(sdy*3874.8674f+sdx*6783.5325f)*2737.8474f;
}
float fract( float x )
{
return x-floorf(x);
}
SDL_Window *w;
SDL_Surface *ws, *fz;
rgbfpx_t *fl1, *fl2, *fl3;
const int fw1 = 320, fw2 = 160, fw3 = 80, fh1 = 240, fh2 = 120, fh3 = 60;
rgbfpx_t layers[3] =
{
// Void
{0.71f,0.67f,0.95f,1.f},
{0.66f,0.84f,0.73f,1.f},
{0.95f,0.73f,0.81f,1.f}
// SWWM GZ
//{0.91f,0.87f,1.95f,1.f},
//{0.66f,1.84f,0.73f,1.f},
//{1.35f,0.73f,1.21f,1.f}
// RED ONI
//{0.61f,0.77f,0.85f,1.f},
//{0.86f,0.64f,0.63f,1.f},
//{1.25f,0.33f,0.41f,1.f}
// RED-EYED RAMPAGE
//{1.81f,0.97f,0.75f,1.f},
//{0.36f,0.64f,0.93f,1.f},
//{1.25f,0.33f,0.41f,1.f}
// RED STAR OF INNOCENCE
//{1.31f,0.87f,1.25f,1.f},
//{0.76f,0.64f,0.63f,1.f},
//{1.25f,1.13f,0.21f,1.f}
};
float speed[3] =
{
1.3526f,
0.7843f,
0.3725f
};
void mklayer1( void )
{
for ( int y=0; y<fh1; y++ )
{
float rg;
for ( int x=0; x<fw1; x++ )
{
rg = 2.f*fabsf(fract(rn(x,y)+t*speed[0])-0.5f);
fl1[x+y*fw1].r = layers[0].r*rg;
fl1[x+y*fw1].g = layers[0].g*rg;
fl1[x+y*fw1].b = layers[0].b*rg;
fl1[x+y*fw1].a = layers[0].a*rg;
}
}
}
void mklayer2( void )
{
for ( int y=0; y<fh2; y++ )
{
float rg;
for ( int x=0; x<fw2; x++ )
{
rg = 2.f*fabsf(fract(rn(x,y)+t*speed[1])-0.5f);
fl2[x+y*fw2].r = layers[1].r*rg;
fl2[x+y*fw2].g = layers[1].g*rg;
fl2[x+y*fw2].b = layers[1].b*rg;
fl2[x+y*fw2].a = layers[1].a*rg;
}
}
}
void mklayer3( void )
{
for ( int y=0; y<fh3; y++ )
{
float rg;
for ( int x=0; x<fw3; x++ )
{
rg = 2.f*fabsf(fract(rn(x,y)+t*speed[2])-0.5f);
fl3[x+y*fw3].r = layers[2].r*rg;
fl3[x+y*fw3].g = layers[2].g*rg;
fl3[x+y*fw3].b = layers[2].b*rg;
fl3[x+y*fw3].a = layers[2].a*rg;
}
}
}
float clamp( float a, float l, float h )
{
return (a>h)?h:(a>l)?a:l;
}
void mergedown( void )
{
rgbfpx_t twofivefive = {255.f,255.f,255.f,255.f};
#pragma omp parallel for
for ( int y=0; y<fh; y++ )
{
int y1, y2, y3;
rgb8px_t *stripe;
rgbfpx_t merged;
y1 = y>>1;
y2 = y>>2;
y3 = y>>3;
stripe = (rgb8px_t*)((Uint8*)fz->pixels+y*fz->pitch);
for ( int x=0; x<fw; x++ )
{
int x1, x2, x3;
x1 = x>>1;
x2 = x>>2;
x3 = x>>3;
// gcc is stupid
asm( "movaps %1,%%xmm0\n"
"mulps %2,%%xmm0\n"
"mulps %3,%%xmm0\n"
"mulps %4,%%xmm0\n"
"movaps %%xmm0,%0\n"
:"=m"(merged)
:"m"(fl1[x1+y1*fw1]),"m"(fl2[x2+y2*fw2]),
"m"(fl3[x3+y3*fw3]),"m"(twofivefive));
stripe[x].r = clamp(merged.r,0,255);
stripe[x].g = clamp(merged.g,0,255);
stripe[x].b = clamp(merged.b,0,255);
stripe[x].a = clamp(merged.a,0,255);
}
}
}
#define TMAX 64
int ti = 0;
float ts = 0.f, tl[TMAX] = {0.f};
float avg_fps( float nt )
{
ts = ts-tl[ti]+nt;
tl[ti] = nt;
if ( ++ti == TMAX ) ti = 0;
return ts/TMAX;
}
#define NANOS_SEC 1000000000L
long ticker( void )
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW,&ts);
return ts.tv_nsec+ts.tv_sec*NANOS_SEC;
}
int main( void )
{
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS);
w = SDL_CreateWindow("Fuzz",SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,fw,fh,SDL_WINDOW_SHOWN);
ws = SDL_GetWindowSurface(w);
fz = SDL_CreateRGBSurface(0,fw,fh,32,0xFF,0xFF00,0xFF0000,0xFF000000);
SDL_SetSurfaceBlendMode(fz,SDL_BLENDMODE_NONE);
fl1 = malloc(sizeof(rgbfpx_t)*fw1*fh1);
fl2 = malloc(sizeof(rgbfpx_t)*fw2*fh2);
fl3 = malloc(sizeof(rgbfpx_t)*fw3*fh3);
TTF_Init();
TTF_Font *fon = TTF_OpenFont(FUZZ_FONT_PATH,16);
if ( !fon )
{
fprintf(stderr,"Could not open font '%s'.\n",FUZZ_FONT_PATH);
TTF_Quit();
free(fl3);
free(fl2);
free(fl1);
SDL_FreeSurface(fz);
SDL_DestroyWindow(w);
SDL_Quit();
return 1;
}
SDL_Event e;
SDL_Color fpscol = {160,0,0,255};
int active = 1;
long tick, tock;
float frame = 0.f, fps = NAN, fpsmin = INFINITY, fpsmax = -INFINITY,
fpsavg = 0.f;
char fpst[16];
while ( active )
{
tick = ticker();
while ( SDL_PollEvent(&e) ) if ( (e.type == SDL_QUIT)
|| ((e.type == SDL_KEYDOWN)
&& (e.key.keysym.sym == SDLK_ESCAPE)) ) active = 0;
mklayer1();
mklayer2();
mklayer3();
mergedown();
SDL_BlitSurface(fz,0,ws,0);
snprintf(fpst,15,"%.2f FPS",fps);
SDL_Surface *txt = TTF_RenderText_Blended(fon,fpst,fpscol);
SDL_BlitSurface(txt,0,ws,0);
SDL_FreeSurface(txt);
SDL_UpdateWindowSurface(w);
tock = ticker();
frame = (float)(tock-tick)/NANOS_SEC;
fps = 1.f/frame;
fpsavg = avg_fps(fps);
if ( fps > fpsmax ) fpsmax = fps;
if ( fps < fpsmin ) fpsmin = fps;
printf("FPS: %.2f (%.2f min, %.2f max, %.2f avg)\n",fps,
fpsmin,fpsmax,fpsavg);
t += frame;
}
TTF_CloseFont(fon);
TTF_Quit();
free(fl3);
free(fl2);
free(fl1);
SDL_FreeSurface(fz);
SDL_DestroyWindow(w);
SDL_Quit();
return 0;
}