[mtl canvas] Fix artifacts on tiger that was due to epsilon comparison for cubics equation in draw kernel. Removed that (now do <= 0), but then we need to weed out false negatives for solid triangles. So we compute if the triangle is solid in the triangle kernel and store it in the mg_triangle_data struct for now.

This commit is contained in:
Martin Fouilleul 2023-03-22 15:02:04 +01:00
parent b0be21795e
commit e9ecd9d521
5 changed files with 38 additions and 23 deletions

View File

@ -65,7 +65,7 @@ int main()
//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_BACKEND_DEFAULT);
mg_surface_swap_interval(surface, 0); mg_surface_swap_interval(surface, 1);
//TODO: create canvas //TODO: create canvas
mg_canvas canvas = mg_canvas_create(surface); mg_canvas canvas = mg_canvas_create(surface);
@ -85,7 +85,7 @@ int main()
bool tracked = false; bool tracked = false;
vec2 trackPoint = {0}; vec2 trackPoint = {0};
f32 zoom = 1; f32 zoom = 1;
f32 startX = 0, startY = 0; f32 startX = 300, startY = 200;
f64 frameTime = 0; f64 frameTime = 0;
@ -112,8 +112,8 @@ int main()
{ {
tracked = true; tracked = true;
vec2 mousePos = mp_mouse_position(); vec2 mousePos = mp_mouse_position();
trackPoint.x = mousePos.x/zoom - startX; trackPoint.x = (mousePos.x - startX)/zoom;
trackPoint.y = mousePos.y/zoom - startY; trackPoint.y = (mousePos.y - startY)/zoom;
} }
else else
{ {
@ -125,14 +125,14 @@ int main()
case MP_EVENT_MOUSE_WHEEL: case MP_EVENT_MOUSE_WHEEL:
{ {
vec2 mousePos = mp_mouse_position(); vec2 mousePos = mp_mouse_position();
f32 trackX = mousePos.x/zoom - startX; f32 pinX = (mousePos.x - startX)/zoom;
f32 trackY = mousePos.y/zoom - startY; f32 pinY = (mousePos.y - startY)/zoom;
zoom *= 1 + event.move.deltaY * 0.01; zoom *= 1 + event.move.deltaY * 0.01;
zoom = Clamp(zoom, 0.2, 10); zoom = Clamp(zoom, 0.5, 5);
startX = mousePos.x/zoom - trackX; startX = mousePos.x - pinX*zoom;
startY = mousePos.y/zoom - trackY; startY = mousePos.y - pinY*zoom;
} break; } break;
default: default:
@ -143,8 +143,8 @@ int main()
if(tracked) if(tracked)
{ {
vec2 mousePos = mp_mouse_position(); vec2 mousePos = mp_mouse_position();
startX = mousePos.x/zoom - trackPoint.x; startX = mousePos.x - trackPoint.x*zoom;
startY = mousePos.y/zoom - trackPoint.y; startY = mousePos.y - trackPoint.y*zoom;
} }
mg_surface_prepare(surface); mg_surface_prepare(surface);
@ -152,8 +152,8 @@ int main()
mg_set_color_rgba(1, 0, 1, 1); mg_set_color_rgba(1, 0, 1, 1);
mg_clear(); mg_clear();
mg_matrix_push((mg_mat2x3){zoom, 0, 300+startX*zoom, mg_matrix_push((mg_mat2x3){zoom, 0, startX,
0, zoom, 200+startY*zoom}); 0, zoom, startY});
draw_tiger(); draw_tiger();

View File

@ -208,10 +208,13 @@ for g in tree.iter('{http://www.w3.org/2000/svg}g'):
print("\tmg_set_color_rgba(" + f2s(r) + ", " + f2s(g) + ", " + f2s(b) + ", 1);") print("\tmg_set_color_rgba(" + f2s(r) + ", " + f2s(g) + ", " + f2s(b) + ", 1);")
print("\tmg_fill();") print("\tmg_fill();")
if stroke_width != None:
print("\tmg_set_width(" + stroke_width + ");");
if stroke != None and stroke != "none": if stroke != None and stroke != "none":
if stroke_width != None:
print("\tmg_set_width(" + stroke_width + ");");
else:
print("\tmg_set_width(1);");
(r, g, b) = parse_color(stroke) (r, g, b) = parse_color(stroke)
if fill != None: if fill != None:
ctx.reset() ctx.reset()

View File

@ -284,6 +284,7 @@ void draw_tiger()
mg_close_path(); mg_close_path();
mg_set_color_rgba(1.000, 1.000, 1.000, 1); mg_set_color_rgba(1.000, 1.000, 1.000, 1);
mg_fill(); mg_fill();
mg_set_width(1);
mg_move_to(-129.830, 103.060); mg_move_to(-129.830, 103.060);
mg_cubic_to(-129.330, 109.110, -128.340, 115.680, -126.600, 118.800); mg_cubic_to(-129.330, 109.110, -128.340, 115.680, -126.600, 118.800);
mg_cubic_to(-126.600, 118.800, -130.200, 131.200, -121.400, 144.400); mg_cubic_to(-126.600, 118.800, -130.200, 131.200, -121.400, 144.400);
@ -422,6 +423,7 @@ void draw_tiger()
mg_close_path(); mg_close_path();
mg_set_color_rgba(0.800, 0.447, 0.149, 1); mg_set_color_rgba(0.800, 0.447, 0.149, 1);
mg_fill(); mg_fill();
mg_set_width(1);
mg_move_to(299.720, 80.245); mg_move_to(299.720, 80.245);
mg_cubic_to(300.340, 80.426, 302.550, 81.550, 303.800, 83.200); mg_cubic_to(300.340, 80.426, 302.550, 81.550, 303.800, 83.200);
mg_cubic_to(303.800, 83.200, 310.600, 94.000, 305.400, 75.600); mg_cubic_to(303.800, 83.200, 310.600, 94.000, 305.400, 75.600);
@ -909,6 +911,7 @@ void draw_tiger()
mg_close_path(); mg_close_path();
mg_set_color_rgba(1.000, 0.447, 0.498, 1); mg_set_color_rgba(1.000, 0.447, 0.498, 1);
mg_fill(); mg_fill();
mg_set_width(1);
mg_move_to(-9.800, 174.400); mg_move_to(-9.800, 174.400);
mg_cubic_to(-9.800, 174.400, -12.600, 196.800, -9.400, 205.200); mg_cubic_to(-9.800, 174.400, -12.600, 196.800, -9.400, 205.200);
mg_cubic_to(-6.200, 213.600, -7.000, 215.600, -7.800, 219.600); mg_cubic_to(-6.200, 213.600, -7.000, 215.600, -7.800, 219.600);
@ -3879,21 +3882,25 @@ void draw_tiger()
mg_move_to(-89.250, 169.000); mg_move_to(-89.250, 169.000);
mg_move_to(-67.250, 173.750); mg_move_to(-67.250, 173.750);
mg_set_width(1);
mg_set_color_rgba(0.000, 0.000, 0.000, 1); mg_set_color_rgba(0.000, 0.000, 0.000, 1);
mg_stroke(); mg_stroke();
mg_move_to(-39.000, 331.000); mg_move_to(-39.000, 331.000);
mg_cubic_to(-39.000, 331.000, -39.500, 327.500, -48.500, 338.000); mg_cubic_to(-39.000, 331.000, -39.500, 327.500, -48.500, 338.000);
mg_set_width(1);
mg_set_color_rgba(0.000, 0.000, 0.000, 1); mg_set_color_rgba(0.000, 0.000, 0.000, 1);
mg_stroke(); mg_stroke();
mg_move_to(-33.500, 336.000); mg_move_to(-33.500, 336.000);
mg_cubic_to(-33.500, 336.000, -31.500, 329.500, -38.000, 334.000); mg_cubic_to(-33.500, 336.000, -31.500, 329.500, -38.000, 334.000);
mg_set_width(1);
mg_set_color_rgba(0.000, 0.000, 0.000, 1); mg_set_color_rgba(0.000, 0.000, 0.000, 1);
mg_stroke(); mg_stroke();
mg_move_to(20.500, 344.500); mg_move_to(20.500, 344.500);
mg_cubic_to(20.500, 344.500, 22.000, 333.500, 10.500, 346.500); mg_cubic_to(20.500, 344.500, 22.000, 333.500, 10.500, 346.500);
mg_set_width(1);
mg_set_color_rgba(0.000, 0.000, 0.000, 1); mg_set_color_rgba(0.000, 0.000, 0.000, 1);
mg_stroke(); mg_stroke();

View File

@ -13,7 +13,7 @@
#define RENDERER_TILE_SIZE 16 #define RENDERER_TILE_SIZE 16
#define RENDERER_MAX_TILES 65536 #define RENDERER_MAX_TILES 65536
#define RENDERER_TILE_BUFFER_COUNT 4*(1<<10) #define RENDERER_TILE_BUFFER_COUNT 8*(1<<10)
#define RENDERER_DEBUG_TILE_VISITED 0xf00d #define RENDERER_DEBUG_TILE_VISITED 0xf00d
#define RENDERER_DEBUG_TILE_BUFFER_OVERFLOW 0xdead #define RENDERER_DEBUG_TILE_BUFFER_OVERFLOW 0xdead
@ -38,6 +38,7 @@ typedef struct mg_triangle_data
matrix_float3x3 uvTransform; matrix_float3x3 uvTransform;
vector_float4 color; vector_float4 color;
bool full;
vector_float4 cubic0; vector_float4 cubic0;
vector_float4 cubic1; vector_float4 cubic1;
vector_float4 cubic2; vector_float4 cubic2;

View File

@ -158,6 +158,12 @@ kernel void TriangleKernel(constant mg_vertex* vertexBuffer [[buffer(0)]],
triangleArray[gid].bias1 = is_top_left(p2, p0) ? -(1-cw)/2 : -(1+cw)/2; triangleArray[gid].bias1 = is_top_left(p2, p0) ? -(1-cw)/2 : -(1+cw)/2;
triangleArray[gid].bias2 = is_top_left(p0, p1) ? -(1-cw)/2 : -(1+cw)/2; triangleArray[gid].bias2 = is_top_left(p0, p1) ? -(1-cw)/2 : -(1+cw)/2;
bool triangleFull = all( triangleArray[gid].cubic0 == float4(1, 1, 1, 1)
&& triangleArray[gid].cubic1 == float4(1, 1, 1, 1)
&& triangleArray[gid].cubic2 == float4(1, 1, 1, 1));
triangleArray[gid].full = triangleFull;
int4 coarseBox = int4(fbox)/RENDERER_TILE_SIZE; int4 coarseBox = int4(fbox)/RENDERER_TILE_SIZE;
//NOTE: bucket triangle into tiles //NOTE: bucket triangle into tiles
@ -172,10 +178,6 @@ kernel void TriangleKernel(constant mg_vertex* vertexBuffer [[buffer(0)]],
//NOTE(martin): it's important to do the computation with signed int, so that we can have negative xMax/yMax //NOTE(martin): it's important to do the computation with signed int, so that we can have negative xMax/yMax
// otherwise all triangles on the left or below the x/y axis are attributed to tiles on row/column 0. // otherwise all triangles on the left or below the x/y axis are attributed to tiles on row/column 0.
bool triangleFull = all( triangleArray[gid].cubic0 == float4(1, 1, 1, 1)
&& triangleArray[gid].cubic1 == float4(1, 1, 1, 1)
&& triangleArray[gid].cubic2 == float4(1, 1, 1, 1));
int2 edges[3][2] = {{ip0, ip1}, {ip1, ip2}, {ip2, ip0}}; int2 edges[3][2] = {{ip0, ip1}, {ip1, ip2}, {ip2, ip0}};
for(int y = yMin; y <= yMax; y++) for(int y = yMin; y <= yMax; y++)
@ -450,6 +452,8 @@ kernel void RenderKernel(const device uint* tileCounters [[buffer(0)]],
float4 cubic1 = triangle->cubic1; float4 cubic1 = triangle->cubic1;
float4 cubic2 = triangle->cubic2; float4 cubic2 = triangle->cubic2;
bool fullTriangle = triangle->full;
int shapeIndex = triangle->shapeIndex; int shapeIndex = triangle->shapeIndex;
float4 color = triangle->color; float4 color = triangle->color;
color.rgb *= color.a; color.rgb *= color.a;
@ -478,8 +482,8 @@ kernel void RenderKernel(const device uint* tileCounters [[buffer(0)]],
{ {
float4 cubic = (cubic0*w0 + cubic1*w1 + cubic2*w2)/(w0+w1+w2); float4 cubic = (cubic0*w0 + cubic1*w1 + cubic2*w2)/(w0+w1+w2);
float eps = 0.0001; if( fullTriangle
if(cubic.w*(cubic.x*cubic.x*cubic.x - cubic.y*cubic.z) <= eps) ||(cubic.w*(cubic.x*cubic.x*cubic.x - cubic.y*cubic.z) <= 0))
{ {
if(shapeIndex == currentShapeIndex[sampleIndex]) if(shapeIndex == currentShapeIndex[sampleIndex])
{ {