diff --git a/example b/example index 2fceecc..051c198 100755 Binary files a/example and b/example differ diff --git a/example.cpp b/example.cpp index 89c41c2..3366573 100644 --- a/example.cpp +++ b/example.cpp @@ -75,7 +75,7 @@ int main(void) { timeAvg /= BATCH; printf("Elapsed: %ld ns\n", timeAvg); - triangle.draw(surface.buffer, blue); + triangle.draw(surface.buffer, fuchsia); point.draw(surface.buffer, green); diff --git a/primatives/trapezoid.cpp b/primatives/trapezoid.cpp index 9724d45..b1bf444 100644 --- a/primatives/trapezoid.cpp +++ b/primatives/trapezoid.cpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "../datatypes.cpp" #include "../helpers.cpp" @@ -47,17 +48,8 @@ namespace UwU { } else if (shader.shaderType == HGRADIENT) { // find left-right boundaries - uint16_t leftmost, rightmost; - if (xl0 < xl1) { - leftmost = xl0; - } else { - leftmost = xl1; - } - if (xr0 > xr1) { - rightmost = xr0; - } else { - rightmost = xr1; - } + uint16_t leftmost = std::min(xl0, xl1); + uint16_t rightmost = std::max(xr0, xr1); // precompute gradient LUT Color cols[rightmost - leftmost]; diff --git a/primatives/triangle.cpp b/primatives/triangle.cpp index e0400f1..7456d0d 100644 --- a/primatives/triangle.cpp +++ b/primatives/triangle.cpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "../datatypes.cpp" #include "../helpers.cpp" @@ -9,7 +10,6 @@ namespace UwU { class Triangle { private: - public: Triangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { @@ -29,95 +29,133 @@ namespace UwU { uint16_t y2; // Draw a triangle - void draw (Buffer buffer, Color color) { - Coord2 top = Coord2(); - Coord2 mid = Coord2(); - Coord2 btm = Coord2(); - // cases: left-handed, right-handed + void draw (Buffer buffer, Shader shader) { + uint16_t topX, topY, midX, midY, btmX, btmY; + // Find top, middle and bottom points of triangle if (y0 <= y1 && y0 <= y2) { - top.x = x0; - top.y = y0; + topX = x0; + topY = y0; if (y1 < y2) { - mid.x = x1; - mid.y = y1; - btm.x = x2; - btm.y = y2; + midX = x1; + midY = y1; + btmX = x2; + btmY = y2; } else { - mid.x = x2; - mid.y = y2; - btm.x = x1; - btm.y = y1; + midX = x2; + midY = y2; + btmX = x1; + btmY = y1; } } else if (y1 <= y0 && y1 <= y2) { - top.x = x1; - top.y = y1; + topX = x1; + topY = y1; if (y0 < y2) { - mid.x = x0; - mid.y = y0; - btm.x = x2; - btm.y = y2; + midX = x0; + midY = y0; + btmX = x2; + btmY = y2; } else { - mid.x = x2; - mid.y = y2; - btm.x = x0; - btm.y = y0; + midX = x2; + midY = y2; + btmX = x0; + btmY = y0; } } else { - top.x = x2; - top.y = y2; + topX = x2; + topY = y2; if (y0 < y1) { - mid.y = y0; - mid.x = x0; - btm.x = x1; - btm.y = y1; + midY = y0; + midX = x0; + btmX = x1; + btmY = y1; } else { - mid.x = x1; - mid.y = y1; - btm.x = x0; - btm.y = y0; + midX = x1; + midY = y1; + btmX = x0; + btmY = y0; } } - // printf("top: (%u, %u)\n", top.x, top.y); - // printf("mid: (%u, %u)\n", mid.x, mid.y); - // printf("btm: (%u, %u)\n", btm.x, btm.y); + + - uint16_t height = 1 + btm.y - top.y; + uint16_t height = 1 + btmY - topY; int16_t longBound[height]; int16_t splitBound[height]; - // int16_t rightBound[height]; - Helpers::bresenham(0, top.x, height - 1, btm.x, longBound); - // printf("longBound\n"); - if ((int16_t)mid.x < longBound[mid.y - top.y]) { - // left-handed triangle - // printf("left-handed\n"); - // rightBound = longBound; - Helpers::bresenham(0, top.x, mid.y - top.y, mid.x, splitBound); - // printf("splitTop\n"); - Helpers::bresenham(mid.y - top.y, mid.x, height - 1, btm.x, splitBound); - // printf("splitBtm\n"); - // for (uint16_t i = 0; i < height; i++) { - // printf("(%u, %u)\n", i, splitBound[i]); - // } - for (uint16_t i = 0; i < height; i++) { - for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) { - // Helpers::putPixel(buffer, x, i + (uint32_t)top.y, color.r, color.g, color.b, color.a); - buffer.drawPixel(x, i + (uint16_t)top.y, color); + + // Calculate LUT for longest vertical line (from top to bottom) + Helpers::bresenham(0, topX, height - 1, btmX, longBound); + + // Calculate LUT for short two lines + Helpers::bresenham(0, topX, midY - topY, midX, splitBound); + Helpers::bresenham(midY - topY, midX, height - 1, btmX, splitBound); + + if (shader.shaderType == COLOR) { + // Left-handed triangle case (midpoint is left of triangle) + if ((int16_t)midX < longBound[midY - topY]) { + for (uint16_t i = 0; i < height; i++) { + for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) { + buffer.drawPixel(x, i + (uint16_t)topY, shader.c0); + } + } + // Right-handed triangle case (midpoint is right of triangle) + } else { + for (uint16_t i = 0; i < height; i++) { + for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) { + buffer.drawPixel(x, i + (uint16_t)topY, shader.c0); + } } } - } else { - // right-handed triangle - // printf("right-handed\n"); - // leftBound = longBound; - Helpers::bresenham(0, top.x, mid.y - top.y, mid.x, splitBound); - // printf("splitTop\n"); - Helpers::bresenham(mid.y - top.y, mid.x, height - 1, btm.x, splitBound); - // printf("splitBtm\n"); - for (uint16_t i = 0; i < height; i++) { - for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) { - // Helpers::putPixel(buffer, x, i + (uint32_t)top.y, color.r, color.g, color.b, color.a); - buffer.drawPixel(x, i + (uint16_t)top.y, color); + return; + + } else if (shader.shaderType == HGRADIENT) { + // find left and right bounds + uint16_t leftmost = std::min(x0, std::min(x1, x2)); + uint16_t rightmost = std::max(x0, std::max(x1, x2)); + + // precompute gradient LUT + Color cols[rightmost - leftmost]; + for (uint16_t x = leftmost; x < rightmost; x++) { + cols[x - leftmost] = ShaderMethods::gradient(shader.u0, shader.scale, shader.c0, shader.c1, x); + } + + // Left-handed triangle case (midpoint is left of triangle) + if ((int16_t)midX < longBound[midY - topY]) { + for (uint16_t i = 0; i < height; i++) { + for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) { + buffer.drawPixel(x, i + (uint16_t)topY, cols[x - leftmost]); + } + } + // Right-handed triangle case (midpoint is right of triangle) + } else { + for (uint16_t i = 0; i < height; i++) { + for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) { + buffer.drawPixel(x, i + (uint16_t)topY, cols[x - leftmost]); + } } } + return; + + } else if (shader.shaderType == VGRADIENT) { + Color c; + + // Left-handed triangle case (midpoint is left of triangle) + if ((int16_t)midX < longBound[midY - topY]) { + for (uint16_t i = 0; i < height; i++) { + c = ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, i + topY); + for (uint16_t x = (uint16_t)splitBound[i]; x <= (uint16_t)longBound[i]; x++) { + buffer.drawPixel(x, i + (uint16_t)topY, c); + } + } + // Right-handed triangle case (midpoint is right of triangle) + } else { + for (uint16_t i = 0; i < height; i++) { + c = ShaderMethods::gradient(shader.v0, shader.scale, shader.c0, shader.c1, i + topY); + for (uint16_t x = (uint16_t)longBound[i]; x <= (uint16_t)splitBound[i]; x++) { + buffer.drawPixel(x, i + (uint16_t)topY, c); + } + } + } + return; } return; }