[wip, win32, canvas] raster elements directly per pixel
This commit is contained in:
parent
b797f187dc
commit
f76ff94c28
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
|
||||||
|
|
||||||
|
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_poly.exe
|
|
@ -6,6 +6,7 @@
|
||||||
* @revision:
|
* @revision:
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
#include<stdio.h>
|
||||||
#include<stdlib.h>
|
#include<stdlib.h>
|
||||||
#include<string.h>
|
#include<string.h>
|
||||||
#include<errno.h>
|
#include<errno.h>
|
||||||
|
@ -19,8 +20,6 @@
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
LogLevel(LOG_LEVEL_MESSAGE);
|
|
||||||
|
|
||||||
mp_init();
|
mp_init();
|
||||||
mp_clock_init(); //TODO put that in mp_init()?
|
mp_clock_init(); //TODO put that in mp_init()?
|
||||||
|
|
||||||
|
@ -30,11 +29,17 @@ int main()
|
||||||
mp_rect contentRect = mp_window_get_content_rect(window);
|
mp_rect contentRect = mp_window_get_content_rect(window);
|
||||||
|
|
||||||
//NOTE: create surface
|
//NOTE: create surface
|
||||||
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_DEFAULT);
|
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
|
||||||
mg_surface_swap_interval(surface, 0);
|
mg_surface_swap_interval(surface, 0);
|
||||||
|
|
||||||
|
if(mg_surface_is_nil(surface))
|
||||||
|
{
|
||||||
|
printf("Error: couldn't create surface\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: create canvas
|
//TODO: create canvas
|
||||||
mg_canvas canvas = mg_canvas_create(surface);
|
mg_canvas canvas = mg_canvas_create();
|
||||||
|
|
||||||
if(mg_canvas_is_nil(canvas))
|
if(mg_canvas_is_nil(canvas))
|
||||||
{
|
{
|
||||||
|
@ -54,10 +59,10 @@ int main()
|
||||||
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
||||||
|
|
||||||
mp_pump_events(0);
|
mp_pump_events(0);
|
||||||
mp_event event = {0};
|
mp_event* event = 0;
|
||||||
while(mp_next_event(&event))
|
while((event = mp_next_event(mem_scratch())) != 0)
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event->type)
|
||||||
{
|
{
|
||||||
case MP_EVENT_WINDOW_CLOSE:
|
case MP_EVENT_WINDOW_CLOSE:
|
||||||
{
|
{
|
||||||
|
@ -66,21 +71,21 @@ int main()
|
||||||
|
|
||||||
case MP_EVENT_KEYBOARD_KEY:
|
case MP_EVENT_KEYBOARD_KEY:
|
||||||
{
|
{
|
||||||
if(event.key.action == MP_KEY_PRESS)
|
if(event->key.action == MP_KEY_PRESS)
|
||||||
{
|
{
|
||||||
if(event.key.code == MP_KEY_LEFT)
|
if(event->key.code == MP_KEY_LEFT)
|
||||||
{
|
{
|
||||||
x-=1;
|
x-=1;
|
||||||
}
|
}
|
||||||
if(event.key.code == MP_KEY_RIGHT)
|
if(event->key.code == MP_KEY_RIGHT)
|
||||||
{
|
{
|
||||||
x+=1;
|
x+=1;
|
||||||
}
|
}
|
||||||
if(event.key.code == MP_KEY_UP)
|
if(event->key.code == MP_KEY_UP)
|
||||||
{
|
{
|
||||||
y-=1;
|
y-=1;
|
||||||
}
|
}
|
||||||
if(event.key.code == MP_KEY_DOWN)
|
if(event->key.code == MP_KEY_DOWN)
|
||||||
{
|
{
|
||||||
y+=1;
|
y+=1;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +102,7 @@ int main()
|
||||||
// background
|
// background
|
||||||
mg_set_color_rgba(0, 1, 1, 1);
|
mg_set_color_rgba(0, 1, 1, 1);
|
||||||
mg_clear();
|
mg_clear();
|
||||||
/*
|
|
||||||
mg_move_to(100, 100);
|
mg_move_to(100, 100);
|
||||||
mg_line_to(150, 150);
|
mg_line_to(150, 150);
|
||||||
mg_line_to(100, 200);
|
mg_line_to(100, 200);
|
||||||
|
@ -106,6 +111,7 @@ int main()
|
||||||
mg_set_color_rgba(1, 0, 0, 1);
|
mg_set_color_rgba(1, 0, 0, 1);
|
||||||
mg_fill();
|
mg_fill();
|
||||||
|
|
||||||
|
/*
|
||||||
mg_move_to(200, 100);
|
mg_move_to(200, 100);
|
||||||
mg_line_to(410, 100);
|
mg_line_to(410, 100);
|
||||||
mg_line_to(410, 200);
|
mg_line_to(410, 200);
|
||||||
|
@ -151,11 +157,10 @@ int main()
|
||||||
mg_close_path();
|
mg_close_path();
|
||||||
mg_set_color_rgba(0, 0, 1, 1);
|
mg_set_color_rgba(0, 0, 1, 1);
|
||||||
mg_stroke();
|
mg_stroke();
|
||||||
*/
|
|
||||||
mg_set_color_rgba(1, 0, 0, 1);
|
mg_set_color_rgba(1, 0, 0, 1);
|
||||||
mg_rounded_rectangle_fill(100, 100, 200, 300, 20);
|
mg_rounded_rectangle_fill(100, 100, 200, 300, 20);
|
||||||
|
|
||||||
/*
|
|
||||||
mg_move_to(x+8, y+8);
|
mg_move_to(x+8, y+8);
|
||||||
mg_line_to(x+33, y+8);
|
mg_line_to(x+33, y+8);
|
||||||
mg_line_to(x+33, y+19);
|
mg_line_to(x+33, y+19);
|
||||||
|
@ -168,7 +173,7 @@ int main()
|
||||||
frameTime,
|
frameTime,
|
||||||
1./frameTime);
|
1./frameTime);
|
||||||
|
|
||||||
mg_flush();
|
mg_render(surface, canvas);
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
|
||||||
mem_arena_clear(mem_scratch());
|
mem_arena_clear(mem_scratch());
|
||||||
|
|
|
@ -17,34 +17,43 @@ typedef struct mg_gl_image
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
} mg_gl_image;
|
} mg_gl_image;
|
||||||
|
|
||||||
typedef enum {
|
enum _mg_gl_cmd {
|
||||||
MG_GL_FILL,
|
MG_GL_FILL,
|
||||||
MG_GL_STROKE,
|
MG_GL_STROKE,
|
||||||
} mg_gl_cmd;
|
};
|
||||||
|
typedef int mg_gl_cmd;
|
||||||
|
|
||||||
typedef struct mg_gl_path
|
typedef struct mg_gl_path
|
||||||
{
|
{
|
||||||
mg_gl_cmd cmd;
|
float uvTransform[12];
|
||||||
float uvTransform[9];
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec4 box;
|
vec4 box;
|
||||||
vec4 clip;
|
vec4 clip;
|
||||||
|
mg_gl_cmd cmd;
|
||||||
|
u8 pad[12];
|
||||||
} mg_gl_path;
|
} mg_gl_path;
|
||||||
|
|
||||||
typedef enum {
|
enum _mg_gl_seg_kind{
|
||||||
MG_GL_LINE = 1,
|
MG_GL_LINE = 1,
|
||||||
MG_GL_QUADRATIC,
|
MG_GL_QUADRATIC,
|
||||||
MG_GL_CUBIC,
|
MG_GL_CUBIC,
|
||||||
} mg_gl_seg_kind;
|
};
|
||||||
|
typedef int mg_gl_seg_kind;
|
||||||
|
|
||||||
typedef struct mg_gl_path_elt
|
typedef struct mg_gl_path_elt
|
||||||
{
|
{
|
||||||
|
vec2 p[4];
|
||||||
int pathIndex;
|
int pathIndex;
|
||||||
int localEltIndex;
|
int localEltIndex;
|
||||||
mg_gl_seg_kind kind;
|
mg_gl_seg_kind kind;
|
||||||
vec2 p[4];
|
u8 pad[4];
|
||||||
} mg_gl_path_elt;
|
} mg_gl_path_elt;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LAYOUT_PATH_SIZE = sizeof(mg_gl_path),
|
||||||
|
LAYOUT_PATH_ELT_SIZE = sizeof(mg_gl_path_elt),
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//NOTE: these are just here for the sizes...
|
//NOTE: these are just here for the sizes...
|
||||||
|
|
||||||
|
@ -115,10 +124,12 @@ typedef struct mg_gl_canvas_backend
|
||||||
|
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
|
|
||||||
|
/*
|
||||||
GLuint pathSetup;
|
GLuint pathSetup;
|
||||||
GLuint segmentSetup;
|
GLuint segmentSetup;
|
||||||
GLuint backprop;
|
GLuint backprop;
|
||||||
GLuint merge;
|
GLuint merge;
|
||||||
|
*/
|
||||||
GLuint raster;
|
GLuint raster;
|
||||||
GLuint blit;
|
GLuint blit;
|
||||||
|
|
||||||
|
@ -211,6 +222,13 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
vec2 viewportSize,
|
vec2 viewportSize,
|
||||||
f32 scale)
|
f32 scale)
|
||||||
{
|
{
|
||||||
|
//NOTE: send the buffers
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->pathBuffer);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, LAYOUT_PATH_SIZE*pathCount, backend->pathBufferData, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->elementBuffer);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, LAYOUT_PATH_ELT_SIZE*eltCount, backend->elementBufferData, GL_STREAM_DRAW);
|
||||||
|
|
||||||
//NOTE: clear counters
|
//NOTE: clear counters
|
||||||
int zero = 0;
|
int zero = 0;
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->segmentCountBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->segmentCountBuffer);
|
||||||
|
@ -222,6 +240,7 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileOpCountBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileOpCountBuffer);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), &zero, GL_DYNAMIC_COPY);
|
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), &zero, GL_DYNAMIC_COPY);
|
||||||
|
|
||||||
|
/*
|
||||||
//NOTE: path setup pass
|
//NOTE: path setup pass
|
||||||
glUseProgram(backend->pathSetup);
|
glUseProgram(backend->pathSetup);
|
||||||
|
|
||||||
|
@ -273,10 +292,11 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
glUniform1f(1, scale);
|
glUniform1f(1, scale);
|
||||||
|
|
||||||
glDispatchCompute(nTilesX, nTilesY, 1);
|
glDispatchCompute(nTilesX, nTilesY, 1);
|
||||||
|
*/
|
||||||
|
|
||||||
//NOTE: raster pass
|
//NOTE: raster pass
|
||||||
glUseProgram(backend->raster);
|
glUseProgram(backend->raster);
|
||||||
|
/*
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->screenTilesBuffer);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->screenTilesBuffer);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->tileOpBuffer);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->tileOpBuffer);
|
||||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 2, backend->pathBuffer, backend->pathBufferOffset, pathCount*sizeof(mg_gl_path));
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 2, backend->pathBuffer, backend->pathBufferOffset, pathCount*sizeof(mg_gl_path));
|
||||||
|
@ -285,9 +305,28 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
glUniform1i(0, tileSize);
|
glUniform1i(0, tileSize);
|
||||||
glUniform1f(1, scale);
|
glUniform1f(1, scale);
|
||||||
glUniform1i(2, backend->msaaCount);
|
glUniform1i(2, backend->msaaCount);
|
||||||
|
*/
|
||||||
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, backend->pathBuffer, backend->pathBufferOffset, pathCount*sizeof(mg_gl_path));
|
||||||
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, backend->elementBuffer, backend->elementBufferOffset, eltCount*sizeof(mg_gl_path_elt));
|
||||||
|
|
||||||
|
// glUniform1ui(0, tileSize);
|
||||||
|
glUniform1f(1, scale);
|
||||||
|
glUniform1ui(2, eltCount);
|
||||||
|
|
||||||
|
int err = glGetError();
|
||||||
|
if(err)
|
||||||
|
{
|
||||||
|
log_error("gl error %i\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
log_info("eltCount = %i\n", eltCount);
|
||||||
|
|
||||||
|
ASSERT(eltCount != 0);
|
||||||
|
|
||||||
glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
|
glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
|
||||||
|
|
||||||
|
/*
|
||||||
if(image)
|
if(image)
|
||||||
{
|
{
|
||||||
//TODO: make sure this image belongs to that context
|
//TODO: make sure this image belongs to that context
|
||||||
|
@ -300,6 +339,7 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
{
|
{
|
||||||
glUniform1ui(3, 0);
|
glUniform1ui(3, 0);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
glDispatchCompute(viewportSize.x, viewportSize.y, 1);
|
glDispatchCompute(viewportSize.x, viewportSize.y, 1);
|
||||||
|
|
||||||
|
@ -358,9 +398,6 @@ void mg_gl_canvas_render(mg_canvas_backend* interface,
|
||||||
vec2 currentPos = {0};
|
vec2 currentPos = {0};
|
||||||
mg_image currentImage = mg_image_nil();
|
mg_image currentImage = mg_image_nil();
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//TODO: we must map or allocate elementBufferData and pathBufferData...
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
|
||||||
mg_gl_encoding_context context = {.glEltCount = 0,
|
mg_gl_encoding_context context = {.glEltCount = 0,
|
||||||
.elementBufferData = backend->elementBufferData,
|
.elementBufferData = backend->elementBufferData,
|
||||||
.pathBufferData = backend->pathBufferData };
|
.pathBufferData = backend->pathBufferData };
|
||||||
|
@ -706,10 +743,12 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface)
|
||||||
|
|
||||||
//NOTE: create programs
|
//NOTE: create programs
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
/*
|
||||||
err |= mg_gl_canvas_compile_compute_program(glsl_path_setup, &backend->pathSetup);
|
err |= mg_gl_canvas_compile_compute_program(glsl_path_setup, &backend->pathSetup);
|
||||||
err |= mg_gl_canvas_compile_compute_program(glsl_segment_setup, &backend->segmentSetup);
|
err |= mg_gl_canvas_compile_compute_program(glsl_segment_setup, &backend->segmentSetup);
|
||||||
err |= mg_gl_canvas_compile_compute_program(glsl_backprop, &backend->backprop);
|
err |= mg_gl_canvas_compile_compute_program(glsl_backprop, &backend->backprop);
|
||||||
err |= mg_gl_canvas_compile_compute_program(glsl_merge, &backend->merge);
|
err |= mg_gl_canvas_compile_compute_program(glsl_merge, &backend->merge);
|
||||||
|
*/
|
||||||
err |= mg_gl_canvas_compile_compute_program(glsl_raster, &backend->raster);
|
err |= mg_gl_canvas_compile_compute_program(glsl_raster, &backend->raster);
|
||||||
err |= mg_gl_canvas_compile_render_program("blit", glsl_blit_vertex, glsl_blit_fragment, &backend->blit);
|
err |= mg_gl_canvas_compile_render_program("blit", glsl_blit_vertex, glsl_blit_fragment, &backend->blit);
|
||||||
|
|
||||||
|
|
|
@ -22,19 +22,19 @@ layout(std430) buffer;
|
||||||
|
|
||||||
struct mg_gl_path
|
struct mg_gl_path
|
||||||
{
|
{
|
||||||
int cmd;
|
mat3 uvTransform;
|
||||||
float uvTransform[9];
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec4 box;
|
vec4 box;
|
||||||
vec4 clip;
|
vec4 clip;
|
||||||
|
int cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_path_elt
|
struct mg_gl_path_elt
|
||||||
{
|
{
|
||||||
|
vec2 p[4];
|
||||||
int pathIndex;
|
int pathIndex;
|
||||||
int localEltIndex;
|
int localEltIndex;
|
||||||
int kind;
|
int kind;
|
||||||
vec2 p[4];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_segment
|
struct mg_gl_segment
|
||||||
|
@ -44,8 +44,8 @@ struct mg_gl_segment
|
||||||
int config; //TODO pack these
|
int config; //TODO pack these
|
||||||
int windingIncrement;
|
int windingIncrement;
|
||||||
vec4 box;
|
vec4 box;
|
||||||
float hullMatrix[9];
|
mat3 hullMatrix;
|
||||||
float implicitMatrix[9];
|
mat3 implicitMatrix;
|
||||||
float sign;
|
float sign;
|
||||||
vec2 hullVertex;
|
vec2 hullVertex;
|
||||||
int debugID;
|
int debugID;
|
||||||
|
|
|
@ -1,31 +1,241 @@
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||||
|
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
layout(std430) buffer;
|
layout(std430) buffer;
|
||||||
|
|
||||||
layout(binding = 0) restrict readonly buffer screenTilesBufferSSBO
|
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
||||||
{
|
|
||||||
mg_gl_tile_queue elements[];
|
|
||||||
} screenTilesBuffer;
|
|
||||||
|
|
||||||
layout(binding = 1) restrict readonly buffer tileOpBufferSSBO
|
|
||||||
{
|
|
||||||
mg_gl_tile_op elements[];
|
|
||||||
} tileOpBuffer;
|
|
||||||
|
|
||||||
layout(binding = 2) restrict readonly buffer pathBufferSSBO
|
|
||||||
{
|
{
|
||||||
mg_gl_path elements[];
|
mg_gl_path elements[];
|
||||||
} pathBuffer;
|
} pathBuffer;
|
||||||
|
|
||||||
layout(binding = 3) restrict readonly buffer segmentBufferSSBO
|
layout(binding = 1) restrict readonly buffer elementBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_segment elements[];
|
mg_gl_path_elt elements[];
|
||||||
} segmentBuffer;
|
} elementBuffer;
|
||||||
|
|
||||||
|
//layout(location = 0) uniform uint tileSize; // this has to be commented until it's effectively used!!
|
||||||
|
layout(location = 1) uniform float scale;
|
||||||
|
layout(location = 2) uniform uint eltCount;
|
||||||
|
|
||||||
|
layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;
|
||||||
|
|
||||||
|
void init_segment(in vec2 p[4], int kind, out mg_gl_segment seg)
|
||||||
|
{
|
||||||
|
vec2 s = p[0];
|
||||||
|
vec2 c = p[0];
|
||||||
|
vec2 e = p[1];
|
||||||
|
|
||||||
|
bool goingUp = e.y >= s.y;
|
||||||
|
bool goingRight = e.x >= s.x;
|
||||||
|
|
||||||
|
seg.kind = kind;
|
||||||
|
seg.pathIndex = 0; ///
|
||||||
|
seg.windingIncrement = goingUp ? 1 : -1;
|
||||||
|
seg.box = vec4(min(s.x, e.x),
|
||||||
|
min(s.y, e.y),
|
||||||
|
max(s.x, e.x),
|
||||||
|
max(s.y, e.y));
|
||||||
|
|
||||||
|
float dx = c.x - seg.box.x;
|
||||||
|
float dy = c.y - seg.box.y;
|
||||||
|
float alpha = (seg.box.w - seg.box.y)/(seg.box.z - seg.box.x);
|
||||||
|
float ofs = seg.box.w - seg.box.y;
|
||||||
|
|
||||||
|
if(goingUp == goingRight)
|
||||||
|
{
|
||||||
|
if(seg.kind == MG_GL_LINE)
|
||||||
|
{
|
||||||
|
seg.config = MG_GL_BR;
|
||||||
|
}
|
||||||
|
else if(dy > alpha*dx)
|
||||||
|
{
|
||||||
|
seg.config = MG_GL_TL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
seg.config = MG_GL_BR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(seg.kind == MG_GL_LINE)
|
||||||
|
{
|
||||||
|
seg.config = MG_GL_TR;
|
||||||
|
}
|
||||||
|
else if(dy < ofs - alpha*dx)
|
||||||
|
{
|
||||||
|
seg.config = MG_GL_BL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
seg.config = MG_GL_TR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ccw(vec2 a, vec2 b, vec2 c)
|
||||||
|
{
|
||||||
|
return((b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x));
|
||||||
|
}
|
||||||
|
|
||||||
|
int side_of_segment(vec2 p, mg_gl_segment seg)
|
||||||
|
{
|
||||||
|
int side = 0;
|
||||||
|
if(p.y > seg.box.w || p.y <= seg.box.y)
|
||||||
|
{
|
||||||
|
if(p.x > seg.box.x && p.x <= seg.box.z)
|
||||||
|
{
|
||||||
|
if(p.y > seg.box.w)
|
||||||
|
{
|
||||||
|
side = (seg.config == MG_GL_TL || seg.config == MG_GL_BR)? -1 : 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
side = (seg.config == MG_GL_TL || seg.config == MG_GL_BR)? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(p.x > seg.box.z)
|
||||||
|
{
|
||||||
|
side = 1;
|
||||||
|
}
|
||||||
|
else if(p.x <= seg.box.x)
|
||||||
|
{
|
||||||
|
side = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec2 a, b, c;
|
||||||
|
switch(seg.config)
|
||||||
|
{
|
||||||
|
case MG_GL_TL:
|
||||||
|
a = seg.box.xy;
|
||||||
|
b = seg.box.zw;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MG_GL_BR:
|
||||||
|
a = seg.box.zw;
|
||||||
|
b = seg.box.xy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MG_GL_TR:
|
||||||
|
a = seg.box.xw;
|
||||||
|
b = seg.box.zy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MG_GL_BL:
|
||||||
|
a = seg.box.zy;
|
||||||
|
b = seg.box.xw;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = seg.hullVertex;
|
||||||
|
|
||||||
|
if(ccw(a, b, p) < 0)
|
||||||
|
{
|
||||||
|
// other side of the diagonal
|
||||||
|
side = (seg.config == MG_GL_BR || seg.config == MG_GL_TR) ? -1 : 1;
|
||||||
|
}
|
||||||
|
else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0)
|
||||||
|
{
|
||||||
|
// same side of the diagonal, but outside curve hull
|
||||||
|
side = (seg.config == MG_GL_BL || seg.config == MG_GL_TL) ? -1 : 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// inside curve hull
|
||||||
|
switch(seg.kind)
|
||||||
|
{
|
||||||
|
case MG_GL_LINE:
|
||||||
|
side = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MG_GL_QUADRATIC:
|
||||||
|
{
|
||||||
|
vec3 ph = {p.x, p.y, 1};
|
||||||
|
vec3 klm = seg.implicitMatrix * ph;
|
||||||
|
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MG_GL_CUBIC:
|
||||||
|
{
|
||||||
|
vec3 ph = {p.x, p.y, 1};
|
||||||
|
vec3 klm = seg.implicitMatrix * ph;
|
||||||
|
side = (seg.sign*(klm.x*klm.x*klm.x - klm.y*klm.z) < 0)? -1 : 1;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(side);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
vec2 sampleCoord = vec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy);
|
||||||
|
|
||||||
|
int winding = 0;
|
||||||
|
|
||||||
|
for(int i=0; i<eltCount; i++)
|
||||||
|
{
|
||||||
|
mg_gl_path_elt elt = elementBuffer.elements[i];
|
||||||
|
|
||||||
|
switch(elt.kind)
|
||||||
|
{
|
||||||
|
case MG_GL_LINE:
|
||||||
|
{
|
||||||
|
vec2 p[4] = {elt.p[0]*scale, elt.p[1]*scale, vec2(0), vec2(0)};
|
||||||
|
mg_gl_segment seg;
|
||||||
|
init_segment(p, MG_GL_LINE, seg);
|
||||||
|
seg.hullVertex = p[0];
|
||||||
|
|
||||||
|
if( (sampleCoord.y > seg.box.y)
|
||||||
|
&&(sampleCoord.y <= seg.box.w)
|
||||||
|
&&(side_of_segment(sampleCoord, seg) < 0))
|
||||||
|
{
|
||||||
|
winding += seg.windingIncrement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(op->crossRight)
|
||||||
|
{
|
||||||
|
if( (seg.config == MG_GL_BR || seg.config == MG_GL_TL)
|
||||||
|
&&(sampleCoord.y > seg.box.w))
|
||||||
|
{
|
||||||
|
winding += seg.windingIncrement;
|
||||||
|
}
|
||||||
|
else if( (seg.config == MG_GL_BL || seg.config == MG_GL_TR)
|
||||||
|
&&(sampleCoord.y > seg.box.y))
|
||||||
|
{
|
||||||
|
winding -= seg.windingIncrement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MG_GL_QUADRATIC:
|
||||||
|
case MG_GL_CUBIC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pathIndex = 0;
|
||||||
|
vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
|
||||||
|
|
||||||
|
/* if( sampleCoord.x >= clip.x
|
||||||
|
&& sampleCoord.x < clip.z
|
||||||
|
&& sampleCoord.y >= clip.y
|
||||||
|
&& sampleCoord.y < clip.w)
|
||||||
|
*/ {
|
||||||
|
/*
|
||||||
|
bool filled = (pathBuffer[pathIndex].cmd == MG_GL_FILL && (winding[sampleIndex] & 1))
|
||||||
|
||(pathBuffer[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0));
|
||||||
|
*/
|
||||||
|
bool filled = (winding & 1) != 0;
|
||||||
|
if(filled)
|
||||||
|
{
|
||||||
|
// write to texture
|
||||||
|
imageStore(outTexture, ivec2(sampleCoord), vec4(1, 0, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue