MandAzur/src/mandelbrotshader.cpp

165 lines
3.4 KiB
C++

#include <azur/gint/render.h>
#include "mandelbrotshader.h"
#include <cstdlib>
#include <cstdio>
#include <gint/rtc.h>
#include <gint/usb.h>
#include <gint/usb-ff-bulk.h>
#include <num/num.h>
uint8_t AZRP_SHADER_MANDELBROT = -1;
__attribute__((constructor))
static void register_shader(void)
{
extern azrp_shader_t azrp_shader_mandelbrot;
AZRP_SHADER_MANDELBROT = azrp_register_shader(azrp_shader_mandelbrot);
}
void azrp_shader_mandelbrot_configure(void)
{
azrp_set_uniforms(AZRP_SHADER_MANDELBROT, (void *)azrp_width);
}
void azrp_mandelbrot_USBDEBUG( void )
{
char texttosend[1024];
sprintf( texttosend, "data" );
usb_fxlink_text(texttosend, 0);
}
void azrp_mandelbrot_init( )
{
}
void azrp_mandelbrot_close( void )
{
}
struct command {
uint8_t shader_id;
uint8_t current_frag;
libnum::num xmin;
libnum::num xmax;
libnum::num ymin;
libnum::num ymax;
libnum::num xinc;
libnum::num yinc;
};
void azrp_mandelbrot( void )
{
prof_enter(azrp_perf_cmdgen);
struct command cmd;
cmd.shader_id = AZRP_SHADER_MANDELBROT;
cmd.current_frag = 0;
cmd.xmin = libnum::num(-1.98f);
cmd.xmax = libnum::num(1.98f);
cmd.ymin = libnum::num(-1.12f);
cmd.ymax = libnum::num(1.12f);
cmd.xinc = libnum::num((2*1.98f)/azrp_width);
cmd.yinc = libnum::num((2*1.12f)/azrp_height);
int fragmin = 0;
int fragcount = (azrp_height >> 4) + 1;
azrp_queue_command(&cmd, sizeof cmd, fragmin, fragcount);
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_mandelbrot( void *uniforms, void *comnd, void *fragment )
{
struct command *cmd = (struct command *) comnd;
uint16_t *frag = (uint16_t *) fragment;
int maxiter = 256;
libnum::num cr = libnum::num(-0.480f);
libnum::num ci = libnum::num(0.600f);
for( int j=0; j<16; j++)
{
int offset = azrp_width * j;
for( int i=0; i<azrp_width; i++ )
{
libnum::num zr = cmd->xmin + libnum::num(i)* cmd->xinc;
libnum::num zi = cmd->ymax - libnum::num(cmd->current_frag*16)*cmd->yinc - libnum::num(j)*cmd->yinc;
libnum::num zr2 = zr * zr;
libnum::num zi2 = zi * zi;
int u=0;
while((zr2+zi2)<4 && (u<maxiter))
{
libnum::num temp = zr;
zr2 = zr * zr;
zi2 = zi * zi;
zr = zr2 - zi2 + cr;
zi = 2*zi*temp + ci;
u++;
}
if(u==maxiter)
{
frag[offset + i] = 0x0000;
}
else
{
int CR, CG, CB;
if (u<maxiter/4)
{
CR = 0;
CG = u*4;
CB = 255;
}
else if (u<2*maxiter/4)
{
CR = 0;
CG = 255;
CB = 255-(u-maxiter)/4;
}
else if (u<3*maxiter/4)
{
CR = (u-2*maxiter)/4;
CG = 255;
CB = 0;
}
else if (u<4*maxiter/4)
{
CR = 255;
CG = 255-(u-3*maxiter)/4;
CB = 0;
}
frag[offset + i] = C_RGB(CR,CG,CB);
}
}
}
cmd->current_frag++;
}