From ba9f06f29b96126b9cca5c01e664942b2ce7fbb7 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Jul 24 2020 03:08:49 +0000 Subject: opengl drawing --- diff --git a/demo/src/SConstruct b/demo/src/SConstruct index 2d51a2c..893fc46 100644 --- a/demo/src/SConstruct +++ b/demo/src/SConstruct @@ -14,6 +14,7 @@ flags = ' -O0 -g -lm -Wall -fmessage-length=0 ' # files sources = [ + 'drawing.c', 'font.c', 'main.c', 'phisics.c', diff --git a/demo/src/drawing.c b/demo/src/drawing.c new file mode 100644 index 0000000..1e9220e --- /dev/null +++ b/demo/src/drawing.c @@ -0,0 +1,59 @@ + +#include + +#include + +#include "drawing.h" + + + +void drawingInit() { + background("yellow"); +} + + +void drawingDraw() { + double x = 512; + double y = 512 - 64; + + strokeWeight(5); + + fill("red"); stroke("blue"); + rect(x, y, 48*2, 48); + x += 48*2 + 16; + + fill("#C71585AA"); stroke("0.5 0.5 0.5 0.5"); + ellipse(x, y, 48*2, 48); + x += 48*2 + 16; + + fill("green"); stroke("magenta"); + regularPolygon(x + 24, y + 24, 6, 48); + x += 64; + + stroke("brown"); + point(x, y); + stroke("cyan"); + line(x, y + 48, x + 48, y); + stroke("brown"); + arc(x, y, 48, 48, 0, 90); + x += 64; + + stroke("gray"); + moveTo(x, y + 24); + arcPath(x, y, 48, 48, 180, 360); + lineTo(x + 48, y + 48); + lineTo(x, y + 48); + strokePath(); + x += 64; + + fill("blue"); stroke("transparent"); + moveTo(x, y + 24); + arcPath(x, y, 48, 48, 180, 360); + lineTo(x + 48, y + 48); + lineTo(x, y + 48); + lineTo(x + 24, y + 24); + closePath(); + stroke("black"); +} + + diff --git a/demo/src/drawing.h b/demo/src/drawing.h new file mode 100644 index 0000000..7be1652 --- /dev/null +++ b/demo/src/drawing.h @@ -0,0 +1,11 @@ +#ifndef DRAWING_H +#define DRAWING_H + + +void drawingInit(); +void drawingDraw(); + + +#endif + + diff --git a/demo/src/main.c b/demo/src/main.c index 4e00fe8..9d4f080 100644 --- a/demo/src/main.c +++ b/demo/src/main.c @@ -4,15 +4,18 @@ #include "phisics.h" #include "sprites.h" #include "font.h" +#include "drawing.h" void init() { phisicsInit(); spritesInit(); fontInit(); + drawingInit(); } void draw() { + drawingDraw(); phisicsDraw(); spritesDraw(); fontDraw(); @@ -22,6 +25,7 @@ void draw() { } int main() { + worldSetHeight(512); worldSetWidth(1024); worldSetInit(&init); worldSetDraw(&draw); diff --git a/src/common.c b/src/common.c index 24d3959..c16cbdf 100644 --- a/src/common.c +++ b/src/common.c @@ -26,10 +26,6 @@ static char *colors[][2] = { { "magenta", "1 0 1 1" }, { "cyan", "0 1 1 1" }, - { "yellow", "1 1 0 1" }, - { "magenta", "1 0 1 1" }, - { "cyan", "0 1 1 1" }, - { "brown", "0.5 0.5 0 1" }, }; diff --git a/src/drawing.c b/src/drawing.c index f7fe979..b700145 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -1,5 +1,6 @@ #include "private.h" +#include "world.h" #include "drawing.h" @@ -14,6 +15,13 @@ static size_t pathSize; static size_t pathAllocated; + +static void endPath(int close, int stroke, int fill, int fillSimple); + +static void closePathSimple() + { endPath(TRUE, TRUE, FALSE, TRUE); } + + void background(const char *color) { heliParseColor(color, colorBack); } void fill(const char *color) @@ -43,7 +51,7 @@ void rect(double x, double y, double width, double height) { lineTo(x + width, y); lineTo(x + width, y + height); lineTo(x, y + height); - closePath(); + closePathSimple(); } void line(double x1, double y1, double x2, double y2) { @@ -56,21 +64,40 @@ void line(double x1, double y1, double x2, double y2) { void ellipse(double x, double y, double width, double height) { resetPath(); arcPath(x, y, width, height, 0, 360); - closePath(); + closePathSimple(); } -void point(double x, double y) - { ellipse(x - lineWidth*0.25, y - lineWidth*0.25, lineWidth*0.5, lineWidth*0.5); } +void point(double x, double y) { + double color[4]; + memcpy(color, colorFill, sizeof(color)); + memcpy(colorFill, colorStroke, sizeof(colorFill)); + colorStroke[3] = 0; + ellipse(x - lineWidth*0.5, y - lineWidth*0.5, lineWidth, lineWidth); + colorStroke[3] = colorFill[3]; + memcpy(colorFill, color, sizeof(colorFill)); +} void arcPath(double x, double y, double w, double h, double start, double stop) { - double step = PI/180; + const double step = PI/180; + w *= 0.5; x += w; + h *= 0.5; y += h; start *= PI/180; stop *= PI/180; - if (start < stop) { double s = start; stop = start; start = s; } - for(double a = start; a < stop; a += step) { - double lx = x + cos(a)*w; - double ly = y + sin(a)*h; - lineTo(lx, ly); + double a = start; + if (start < stop) { + while(1) { + if (a > stop) a = stop; + lineTo(x + cos(a)*w, y + sin(a)*h); + if (a == stop) break; + a += step; + } + } else { + while(1) { + if (a < stop) a = stop; + lineTo(x + cos(a)*w, y + sin(a)*h); + if (a == stop) break; + a -= step; + } } } @@ -85,39 +112,94 @@ void regularPolygon(double x, double y, int sides, double size) { size *= 0.5; moveTo(x + size, y); for(int i = 1; i < sides; ++i) { - double a = i*PI/sides; + double a = i*2*PI/sides; lineTo(x + size*cos(a), y + size*sin(a)); } - closePath(); + closePathSimple(); } void resetPath() { pathSize = 0; } -static void endPath(int close, int stroke, int fill) { - /* TODO:bw - cairo_t *cr = heliCairo; - if (cr && pathSize >= 8) { - cairo_save(cr); - cairo_move_to(cr, path[0], path[1]); - for(int i = 2; i < pathSize; i += 2) - cairo_line_to(cr, path[i], path[i+1]); - if (close) - cairo_close_path(cr); - if (fill) { - cairo_set_source_rgba(cr, colorFill[0], colorFill[1], colorFill[2], colorFill[3]); - if (stroke) cairo_fill_preserve(cr); else cairo_fill(cr); - } - if (stroke) { - cairo_set_line_width(cr, lineWidth); - cairo_set_source_rgba(cr, colorStroke[0], colorStroke[1], colorStroke[2], colorStroke[3]); - cairo_stroke(cr); - } - cairo_restore(cr); +static void drawFillSimple() { + if (colorFill[3] <= HELI_PRECISION) return; + if (pathSize < 6) return; + + glColor4dv(colorFill); + glEnable(GL_MULTISAMPLE); + glBegin(GL_TRIANGLE_FAN); + for(int i = 0; i < pathSize; i += 2) + glVertex2dv(&path[i]); + glEnd(); + glDisable(GL_MULTISAMPLE); + glColor4d(1, 1, 1, 1); +} + +static void drawFill() { + if (colorFill[3] <= HELI_PRECISION) return; + if (pathSize < 6) return; + + double l = path[0], r = l; + double t = path[1], b = t; + for(int i = 2; i < pathSize; i += 2) { + if (l > path[i]) l = path[i]; + if (r < path[i]) r = path[i]; + if (t > path[i + 1]) t = path[i + 1]; + if (b < path[i + 1]) b = path[i + 1]; } - */ - resetPath(); + if ( r - l <= HELI_PRECISION + || b - t <= HELI_PRECISION) return; + l -= 1; r += 1; + t -= 1; b += 1; + + glEnable(GL_MULTISAMPLE); + glColor4dv(colorFill); + glEnable(GL_STENCIL_TEST); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + glBegin(GL_QUADS); + glVertex2d(l, t); + glVertex2d(r, t); + glVertex2d(r, b); + glVertex2d(l, b); + glEnd(); + + glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); + glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP); + glBegin(GL_TRIANGLE_FAN); + for(int i = 0; i < pathSize; i += 2) + glVertex2dv(&path[i]); + glEnd(); + + glStencilFunc(GL_NOTEQUAL, 0, -1u); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glBegin(GL_QUADS); + glVertex2d(l, t); + glVertex2d(r, t); + glVertex2d(r, b); + glVertex2d(l, b); + glEnd(); + + glStencilFunc(GL_ALWAYS, 0, -1u); + glDisable(GL_STENCIL_TEST); + glDisable(GL_MULTISAMPLE); + glColor4d(1, 1, 1, 1); +} + +static void drawStroke() { + if (colorStroke[3] <= HELI_PRECISION) return; + if (pathSize < 4) return; + + glColor4dv(colorStroke); + glLineWidth(lineWidth); + glBegin(GL_LINE_STRIP); + for(int i = 0; i < pathSize; i += 2) + glVertex2dv(&path[i]); + glEnd(); + glColor4d(1, 1, 1, 1); } static void pushPathPoint(double x, double y) { @@ -130,10 +212,27 @@ static void pushPathPoint(double x, double y) { path[pathSize++] = y; } +static void endPath(int close, int stroke, int fill, int fillSimple) { + if (pathSize >= 4) { + if (fillSimple) drawFillSimple(); + else if (fill) drawFill(); + if (stroke) { + if ( close + && ( fabs(path[0] - path[pathSize - 2]) > HELI_PRECISION + || fabs(path[1] - path[pathSize - 1]) > HELI_PRECISION )) + { + pushPathPoint(path[0], path[1]); + } + drawStroke(); + } + } + resetPath(); +} + void closePath() - { endPath(TRUE, TRUE, TRUE); } + { endPath(TRUE, TRUE, TRUE, FALSE); } void strokePath() - { endPath(FALSE, TRUE, FALSE); } + { endPath(FALSE, TRUE, FALSE, FALSE); } void lineTo(double x, double y) { pushPathPoint(x, y); } void moveTo(double x, double y) @@ -148,11 +247,15 @@ void heliDrawingClearFrame() { void heliDrawingPrepareFrame() { resetPath(); heliDrawingClearFrame(); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); glDisable(GL_MULTISAMPLE); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); } void heliDrawingFinish() { diff --git a/src/private.h b/src/private.h index a563fb7..95d9ebf 100644 --- a/src/private.h +++ b/src/private.h @@ -6,6 +6,7 @@ #include #include +#define GL_GLEXT_PROTOTYPES #include #include "common.h" diff --git a/src/sprite.c b/src/sprite.c index 1a5b301..5c63b32 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -541,7 +541,8 @@ static void drawSprite(Sprite s) { glEnd(); } } - + + glColor4d(1, 1, 1, 1); glPopMatrix(); } diff --git a/src/world.c b/src/world.c index b7e63f2..16dae1c 100644 --- a/src/world.c +++ b/src/world.c @@ -23,8 +23,8 @@ static Callback initCallback; static Callback drawCallback; static Callback deinitCallback; -static int width = 400; -static int height = 400; +static int width = 512; +static int height = 512; static int resizable; static char title[1000]; static int titleSize = (int)(sizeof(title)/sizeof(*title)); @@ -257,6 +257,7 @@ static int init() { SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);