diff --git a/azur/CMakeLists.txt b/azur/CMakeLists.txt index 454266e..2b9ae22 100644 --- a/azur/CMakeLists.txt +++ b/azur/CMakeLists.txt @@ -69,7 +69,10 @@ if(AZUR_GRAPHICS_GINT_CG) src/gint/shaders/triangle.c src/gint/shaders/triangle.S # Line shader - src/gint/shaders/line.c) + src/gint/shaders/line.c + # Circle shader + src/gint/shaders/circle.c + ) endif() add_library(azur STATIC ${SOURCES}) diff --git a/azur/include/azur/gint/render.h b/azur/include/azur/gint/render.h index 62487e1..1ed3e43 100644 --- a/azur/include/azur/gint/render.h +++ b/azur/include/azur/gint/render.h @@ -203,10 +203,15 @@ void azrp_image(int x, int y, bopti_image_t const *image); void azrp_subimage(int x, int y, bopti_image_t const *image, int left, int top, int width, int height, int flags); + void azrp_triangle(int x1, int y1, int x2, int y2, int x3, int y3, int color); +/* Draw a line between point (x1, y1) and (x2,y2) with clipping */ void azrp_line( int x1, int y1, int x2, int y2, int color); +/* Draw a circle of radius rad and center (xC, yC) */ +void azrp_circle(int xC, int yC, int rad, int color); + /* See below for more detailed image functions. Dynamic effects are provided with the same naming convention as gint. */ @@ -220,7 +225,7 @@ void azrp_shader_image_p8_configure(void); void azrp_shader_image_p4_configure(void); void azrp_shader_triangle_configure(void); void azrp_shader_line_configure(void); - +void azrp_shader_circle_configure(void); //--- // Performance indicators diff --git a/azur/src/gint/shaders/circle.c b/azur/src/gint/shaders/circle.c new file mode 100644 index 0000000..8f38be8 --- /dev/null +++ b/azur/src/gint/shaders/circle.c @@ -0,0 +1,155 @@ +#include + +uint8_t AZRP_SHADER_CIRCLE = -1; + +__attribute__((constructor)) +static void register_shader(void) +{ + extern azrp_shader_t azrp_shader_circle; + AZRP_SHADER_CIRCLE = azrp_register_shader(azrp_shader_circle); +} + +void azrp_shader_circle_configure(void) +{ + azrp_set_uniforms(AZRP_SHADER_CIRCLE, (void *)azrp_width); +} + +static int min(int x, int y) +{ + return (x < y) ? x : y; +} +static int max(int x, int y) +{ + return (x > y) ? x : y; +} + +//--- + +typedef struct +{ + uint16_t x; + uint16_t y; +}Pixel; + +Pixel TablePixels[14][396]; // 14 fragments each able to store as much pixels as width +uint16_t NbPixels[14]; // Nunmber of pixels in each fragment + +struct command { + uint8_t shader_id; + uint16_t color; + uint8_t currfrag; + + uint16_t* pixnb; + Pixel **data; +}; + +void AddPixel( int xp, int yp ) +{ + if (xp >= 0 && xp < azrp_width && yp >= 0 && yp < azrp_height) + { + int currfrag = yp >> 4; + + uint16_t nbpixinfrag = NbPixels[ currfrag ]; + + TablePixels[ currfrag ][ nbpixinfrag ].x = xp; + TablePixels[ currfrag ][ nbpixinfrag ].y = yp & 15; + + NbPixels[ currfrag ]++; + } +} + +void azrp_circle(int xc, int yc, int rad, int color) +{ + prof_enter(azrp_perf_cmdgen); + + + for(int i=0;i<14;i++) NbPixels[i]=0; + + + int xmin = xc - rad; + int xmax = xc + rad; + int ymin = yc - rad; + int ymax = yc + rad; + + + // The circle is fully outside the screen + if ((xmax < 0) || (xmin > azrp_width) || (ymax < 0) || (ymin > azrp_height)) + { + prof_leave(azrp_perf_cmdgen); + return; + } + + int ytop = max( xmin, 0 ); + int ybot = min( xmax, azrp_height ); + + int frag_first = ytop >> 4; + int frag_last = ybot >> 4; + int frag_count = frag_last - frag_first + 1; + + + struct command cmd; + cmd.shader_id = AZRP_SHADER_CIRCLE; + cmd.color = color; + cmd.currfrag = frag_first; + + int x = 0; + int y = rad; + int d = rad - 1; + + while (y >= x) + { + AddPixel( xc+x, yc+y ); + AddPixel( xc+y, yc+y ); + AddPixel( xc-x, yc+y ); + AddPixel( xc-y, yc+x ); + AddPixel( xc+x, yc-y ); + AddPixel( xc+y, yc-x ); + AddPixel( xc-x, yc-y ); + AddPixel( xc-y, yc-x ); + + if (d >= 2*x) + { + d = d - 2*x - 1; + x++; + } + else if (d < 2*(rad-y)) + { + d = d + 2*y - 1; + y--; + } + else + { + d = d + 2*(y - x - 1); + y--; + x++; + } + } + + cmd.pixnb = NbPixels; + cmd.data = TablePixels; + + azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count); + prof_leave(azrp_perf_cmdgen); +} + +void azrp_shader_circle( void *uniforms, void *comnd, void *fragment ) +{ + struct command *cmd = (struct command *) comnd; + uint16_t *frag = (uint16_t *) fragment; + + uint16_t *nbPix = cmd->pixnb; + uint16_t taille = nbPix[ cmd->currfrag ]; + + Pixel **pixData = cmd->data; + Pixel *currFragPix = pixData[ cmd->currfrag ]; + + + for( int i=0; icurrfrag]; i++ ) + { + + frag[ azrp_width * currFragPix[i].y + currFragPix[i].x ] = cmd->color; + } + + cmd->currfrag++; + +} \ No newline at end of file diff --git a/azur/src/gint/shaders/line.c b/azur/src/gint/shaders/line.c index b95cfae..5030f57 100644 --- a/azur/src/gint/shaders/line.c +++ b/azur/src/gint/shaders/line.c @@ -57,9 +57,9 @@ void azrp_line(int xA, int yA, int xB, int yB, int color) //International Journal of Computer Graphics & Animation (IJCGA) Vol.9, No.1/2/3, July 2019 int xmin = 0; - int xmax = azrp_width; + int xmax = azrp_width-1; int ymin = 0; - int ymax = azrp_height; + int ymax = azrp_height-1; //step 1 line are fully out of the screen if ((xAxmax && xB>xmax) || (yAymax && yB>ymax)) {