From 1719aa0714437056552ca6cfb26dc62eda70979c Mon Sep 17 00:00:00 2001 From: SlyVTT Date: Fri, 26 May 2023 18:14:57 +0200 Subject: [PATCH] added azrp_poly() and azrp_filledpoly() shaders --- azur/CMakeLists.txt | 2 + azur/include/azur/gint/render.h | 7 + azur/src/gint/shaders/filledcircle.c | 195 ++++++++++++--------------- azur/src/gint/shaders/filledpoly.c | 162 ++++++++++++++++++++++ azur/src/gint/shaders/poly.c | 15 +++ 5 files changed, 275 insertions(+), 106 deletions(-) create mode 100644 azur/src/gint/shaders/filledpoly.c create mode 100644 azur/src/gint/shaders/poly.c diff --git a/azur/CMakeLists.txt b/azur/CMakeLists.txt index 27f475d..6c17035 100644 --- a/azur/CMakeLists.txt +++ b/azur/CMakeLists.txt @@ -78,6 +78,8 @@ if(AZUR_GRAPHICS_GINT_CG) # Circle shader src/gint/shaders/circle.c src/gint/shaders/filledcircle.c + src/gint/shaders/poly.c + src/gint/shaders/filledpoly.c ) endif() diff --git a/azur/include/azur/gint/render.h b/azur/include/azur/gint/render.h index 33e4b65..6a78620 100644 --- a/azur/include/azur/gint/render.h +++ b/azur/include/azur/gint/render.h @@ -214,6 +214,12 @@ void azrp_circle( int xc, int yx, uint16_t rad, uint16_t color ); /* azrp_filledcircle() : Draw a filled circle with clipping to the screen resolution with a center (xc,yc) and a radius rad */ void azrp_filledcircle( int xc, int yx, uint16_t rad, uint16_t color ); +/* azrp_poly() : Draw a polygon with clipping*/ +void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color); + +/* azrp_filledpoly() : Draw a filled polygon with clipping*/ +void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color); + /* See below for more detailed image functions. Dynamic effects are provided with the same naming convention as gint. */ @@ -230,6 +236,7 @@ void azrp_shader_line_configure(void); void azrp_shader_circle_configure(void); void azrp_shader_filledcircle_configure(void); +void azrp_shader_filledpoly_configure(void); //--- // Performance indicators diff --git a/azur/src/gint/shaders/filledcircle.c b/azur/src/gint/shaders/filledcircle.c index 337be35..2ab23a1 100644 --- a/azur/src/gint/shaders/filledcircle.c +++ b/azur/src/gint/shaders/filledcircle.c @@ -2,132 +2,115 @@ uint8_t AZRP_SHADER_FILLEDCIRCLE = -1; -__attribute__((constructor)) -static void register_shader(void) -{ - extern azrp_shader_t azrp_shader_filledcircle; - AZRP_SHADER_FILLEDCIRCLE = azrp_register_shader(azrp_shader_filledcircle); +__attribute__((constructor)) static void register_shader(void) { + extern azrp_shader_t azrp_shader_filledcircle; + AZRP_SHADER_FILLEDCIRCLE = azrp_register_shader(azrp_shader_filledcircle); } -void azrp_shader_filledcircle_configure(void) -{ - azrp_set_uniforms(AZRP_SHADER_FILLEDCIRCLE, (void *)azrp_width); +void azrp_shader_filledcircle_configure(void) { + azrp_set_uniforms(AZRP_SHADER_FILLEDCIRCLE, (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; -} +static int min(int x, int y) { return (x < y) ? x : y; } +static int max(int x, int y) { return (x > y) ? x : y; } //--- -#define TABLE_WIDTH +#define TABLE_WIDTH struct command { - uint8_t shader_id; - uint16_t color; - uint8_t curr_frag; - int16_t DataFilling[2*224]; // Each line of the screen can have a xmin and a xmax value + uint8_t shader_id; + uint16_t color; + uint8_t curr_frag; + int16_t DataFilling[2 * 224]; // Each line of the screen can have a xmin and + // a xmax value }; -void AddPixelFilledCircle( int16_t xpmin, int16_t xpmax, int16_t yp, struct command *cmd ) -{ - if (yp >= 0 && yp < azrp_height) - { - if (xpmin>=0) cmd->DataFilling[2*yp] = xpmin; - else cmd->DataFilling[2*yp] = 0; +void AddPixelFilledCircle(int16_t xpmin, int16_t xpmax, int16_t yp, + struct command *cmd) { + if (yp >= 0 && yp < azrp_height) { + if (xpmin >= 0) + cmd->DataFilling[2 * yp] = xpmin; + else + cmd->DataFilling[2 * yp] = 0; - if (xpmaxDataFilling[2*yp+1] = xpmax; - else cmd->DataFilling[2*yp+1] = azrp_width-1; - } + if (xpmax < azrp_width) + cmd->DataFilling[2 * yp + 1] = xpmax; + else + cmd->DataFilling[2 * yp + 1] = azrp_width - 1; + } } -void azrp_filledcircle(int xc, int yc, uint16_t rad, uint16_t color) -{ - prof_enter(azrp_perf_cmdgen); +void azrp_filledcircle(int xc, int yc, uint16_t rad, uint16_t color) { + prof_enter(azrp_perf_cmdgen); + int xmin = xc - rad; + int xmax = xc + rad; + int ymin = yc - rad; + int ymax = yc + rad; - 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( ymin, 0 ); - int ybot = min( ymax, azrp_height-1 ); - - int frag_first = ytop / azrp_frag_height; - int frag_last = ybot / azrp_frag_height; - int frag_count = frag_last - frag_first + 1; - - - struct command cmd; - cmd.shader_id = AZRP_SHADER_FILLEDCIRCLE; - cmd.color = color; - cmd.curr_frag = frag_first; - - // reset the point counters in each cell of the table - for( int i = 0; i < 224; i++ ) - { - cmd.DataFilling[2*i] = -1; // reset with value equels -1 - cmd.DataFilling[2*i+1] = -1; // reset with value equals -1 - } - - int x = 0; - int y = rad; - int m = 5 - 4*rad; - - while (x <= y) - { - AddPixelFilledCircle( xc-x, xc+x, yc-y, &cmd ); - AddPixelFilledCircle( xc-y, xc+y, yc-x, &cmd ); - AddPixelFilledCircle( xc-x, xc+x, yc+y, &cmd ); - AddPixelFilledCircle( xc-y, xc+y, yc+x, &cmd ); - - if (m > 0) - { - y--; - m -= 8*y; - } - x++; - m += 8*x + 4; - } - - azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count); + // 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(ymin, 0); + int ybot = min(ymax, azrp_height - 1); + + int frag_first = ytop / azrp_frag_height; + int frag_last = ybot / azrp_frag_height; + int frag_count = frag_last - frag_first + 1; + + struct command cmd; + cmd.shader_id = AZRP_SHADER_FILLEDCIRCLE; + cmd.color = color; + cmd.curr_frag = frag_first; + + // reset the point counters in each cell of the table + for (int i = 0; i < 224; i++) { + cmd.DataFilling[2 * i] = -1; // reset with value equels -1 + cmd.DataFilling[2 * i + 1] = -1; // reset with value equals -1 + } + + int x = 0; + int y = rad; + int m = 5 - 4 * rad; + + while (x <= y) { + AddPixelFilledCircle(xc - x, xc + x, yc - y, &cmd); + AddPixelFilledCircle(xc - y, xc + y, yc - x, &cmd); + AddPixelFilledCircle(xc - x, xc + x, yc + y, &cmd); + AddPixelFilledCircle(xc - y, xc + y, yc + x, &cmd); + + if (m > 0) { + y--; + m -= 8 * y; + } + x++; + m += 8 * x + 4; + } + + azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count); + prof_leave(azrp_perf_cmdgen); } -void azrp_shader_filledcircle( void *uniforms, void *comnd, void *fragment ) -{ - struct command *cmd = (struct command *) comnd; - uint16_t *frag = (uint16_t *) fragment; +void azrp_shader_filledcircle(void *uniforms, void *comnd, void *fragment) { + struct command *cmd = (struct command *)comnd; + uint16_t *frag = (uint16_t *)fragment; - int16_t* data = (int16_t *) cmd->DataFilling; - int BaseAdress = cmd->curr_frag * azrp_frag_height * 2; + int16_t *data = (int16_t *)cmd->DataFilling; + int BaseAdress = cmd->curr_frag * azrp_frag_height * 2; - for( int i = 0; i < azrp_frag_height; i++ ) - { - int16_t Xmin = data[ BaseAdress + 2*i ]; - int16_t Xmax = data[ BaseAdress + 2*i+1 ]; - - if (Xmin!=-1 && Xmax !=-1) - for (int j=Xmin ; j<=Xmax ; j++) - frag[ azrp_width * i + j ] = cmd->color; - } + for (int i = 0; i < azrp_frag_height; i++) { + int16_t Xmin = data[BaseAdress + 2 * i]; + int16_t Xmax = data[BaseAdress + 2 * i + 1]; - cmd->curr_frag++; + if (Xmin != -1 && Xmax != -1) + for (int j = Xmin; j <= Xmax; j++) + frag[azrp_width * i + j] = cmd->color; + } + + cmd->curr_frag++; } \ No newline at end of file diff --git a/azur/src/gint/shaders/filledpoly.c b/azur/src/gint/shaders/filledpoly.c new file mode 100644 index 0000000..016317d --- /dev/null +++ b/azur/src/gint/shaders/filledpoly.c @@ -0,0 +1,162 @@ +#include + +uint8_t AZRP_SHADER_FILLEDPOLY = -1; + +__attribute__((constructor)) static void register_shader(void) { + extern azrp_shader_t azrp_shader_filledpoly; + AZRP_SHADER_FILLEDPOLY = azrp_register_shader(azrp_shader_filledpoly); +} + +void azrp_shader_filledpoly_configure(void) { + azrp_set_uniforms(AZRP_SHADER_FILLEDPOLY, (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; } + +//--- + +#define TABLE_WIDTH + +struct command { + uint8_t shader_id; + uint16_t color; + uint8_t curr_frag; + int16_t xmin[224]; + int16_t xmax[224]; + uint8_t empty[224]; +}; + + +void AddPixelFilledPoly(int16_t xpmin, int16_t xpmax, int16_t yp, + struct command *cmd) { + if (yp >= 0 && yp < azrp_height) { + if (xpmin >= 0) + cmd->xmin[yp] = xpmin; + else + cmd->xmin[yp] = 0; + + if (xpmax < azrp_width) + cmd->xmax[yp] = xpmax; + else + cmd->xmax[yp] = azrp_width - 1; + } +} + + +void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color) { + prof_enter(azrp_perf_cmdgen); + + int i, ymin, ymax, xmin2, xmax2, *xmin, *xmax; + char *empty; + + if(nb_vertices < 3) { + prof_leave(azrp_perf_cmdgen); + return; + } + + ymin = ymax = y[0]; + xmin2 = xmax2 = x[0]; + + for(i=0 ; i ymax) ymax = y[i]; + if(x[i] < xmin2) xmin2 = x[i]; + if(x[i] > xmax2) xmax2 = x[i]; + } + + // The polygon is fully outside the screen + if ((xmax2 < 0) || (xmin2 >= azrp_width) || (ymax < 0) || + (ymin >= azrp_height)) { + prof_leave(azrp_perf_cmdgen); + return; + } + + xmin = malloc((ymax-ymin+1)*sizeof(int)); + xmax = malloc((ymax-ymin+1)*sizeof(int)); + empty = malloc(ymax-ymin+1); + + + int ytop = max(ymin, 0); + int ybot = min(ymax, azrp_height - 1); + + int frag_first = ytop / azrp_frag_height; + int frag_last = ybot / azrp_frag_height; + int frag_count = frag_last - frag_first + 1; + + struct command cmd; + cmd.shader_id = AZRP_SHADER_FILLEDPOLY; + cmd.color = color; + cmd.curr_frag = frag_first; + + // reset the point counters in each cell of the table + for (int i = 0; i < 224; i++) { + cmd.xmin[i] = -1; // reset with value equels -1 + cmd.xmax[i] = -1; // reset with value equals -1 + } + + if(xmin && xmax && empty) { + for(i=0 ; i 0) ? 1 : -1; + sy = (dy > 0) ? 1 : -1; + dx = (dx > 0) ? dx : -dx; + dy = (dy > 0) ? dy : -dy; + if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px; + if(dx > dy) { + cumul = dx >> 1; + for(j=1 ; j dx) cumul -= dx, py += sy; + if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px; + } + } else { + cumul = dy >> 1; + for(j=1 ; j dy) cumul -= dy, px += sx; + if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px; + } + } + } + for(i=0 ; ixmin; + int16_t *Xmaxdata = (int16_t *)cmd->xmax; + + int BaseAdress = cmd->curr_frag * azrp_frag_height; + + for (int i = 0; i < azrp_frag_height; i++) + { + int16_t Xmin = Xmindata[BaseAdress + i]; + int16_t Xmax = Xmaxdata[BaseAdress + i]; + + if (Xmin != -1 && Xmax != -1) + if (Xmin<=Xmax) + for (int j = Xmin; j <= Xmax; j++) frag[azrp_width * i + j] = cmd->color; + else + for (int j = Xmax; j <= Xmin; j++) frag[azrp_width * i + j] = cmd->color; + } + + cmd->curr_frag++; +} \ No newline at end of file diff --git a/azur/src/gint/shaders/poly.c b/azur/src/gint/shaders/poly.c new file mode 100644 index 0000000..cd71d1a --- /dev/null +++ b/azur/src/gint/shaders/poly.c @@ -0,0 +1,15 @@ +#include + +void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color) { + prof_enter(azrp_perf_cmdgen); + + for( int i=0 ; i