From 03777764b7f84109995e3a28c863816c6ca9b578 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 20 Feb 2022 20:02:33 +0100 Subject: [PATCH] nearest neighbour blending and gamma --- main.cpp | 17 +- raster_functions.cpp | 265 ---------------------------- rasterization_feature_selection.cpp | 165 ----------------- test.txt | 249 -------------------------- 4 files changed, 12 insertions(+), 684 deletions(-) delete mode 100644 raster_functions.cpp delete mode 100644 rasterization_feature_selection.cpp delete mode 100644 test.txt diff --git a/main.cpp b/main.cpp index d5aae3f..51ec1e2 100644 --- a/main.cpp +++ b/main.cpp @@ -231,7 +231,14 @@ void draw_triangle(Image* dst, float *depth_buffer, Image *src, #endif // GAMMA_CORRECT_BLENDING U32 color32 = color_to_u32abgr(result_color); #else // BILINEAR_BLEND - U32 color32 = *pixel; + Vec4 result_color = srgb_to_almost_linear(vec4abgr(*pixel)); + Vec4 dst_color = srgb_to_almost_linear(vec4abgr(*dst_pixel)); + result_color.r = result_color.r + (1-result_color.a) * dst_color.r; + result_color.g = result_color.g + (1-result_color.a) * dst_color.g; + result_color.b = result_color.b + (1-result_color.a) * dst_color.b; + result_color.a = result_color.a + dst_color.a - result_color.a*dst_color.a; + result_color = almost_linear_to_srgb(result_color); + U32 color32 = color_to_u32abgr(result_color); #endif // BILINEAR_BLEND *dst_pixel = color32; @@ -306,16 +313,16 @@ int main() { float rotation = 0; Vec3 camera_pos = {0,0,-5}; - Obj obj = load_obj("assets/f22.obj"); + Obj obj = load_obj("assets/cube.obj"); Vec3* vertices = (Vec3 *)obj.vertices; Vec2* tex_coords = (Vec2*)obj.texture; FaceA* faces = (FaceA*)obj.indices; I64 face_count = obj.indices_count; - Image img = load_image("assets/bricksx64.png"); - int screen_x = 320; - int screen_y = 60; + Image img = load_image("assets/cat.png"); + int screen_x = 160; + int screen_y = 90; Image screen320 = {(U32 *)malloc(screen_x*screen_y*sizeof(U32)), screen_x, screen_y}; float* depth320 = (float *)malloc(sizeof(float) * screen_x * screen_y); while (os.game_loop()) { diff --git a/raster_functions.cpp b/raster_functions.cpp deleted file mode 100644 index d1a19cb..0000000 --- a/raster_functions.cpp +++ /dev/null @@ -1,265 +0,0 @@ - -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_off_BILINEAR_BLEND_off (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * w1 + tex1.x * w2 + tex2.x * w3; - float v = tex0.y * w1 + tex1.y * w2 + tex2.y * w3; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - U32 color32 = *pixel; - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_on_BILINEAR_BLEND_on (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * (w1 / p0.w) + tex1.x * (w2 / p1.w) + tex2.x * (w3 / p2.w); - float v = tex0.y * (w1 / p0.w) + tex1.y * (w2 / p1.w) + tex2.y * (w3 / p2.w); - u /= interpolated_z; - v /= interpolated_z; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - Vec4 pixelx1y1 = v4abgr(*pixel); - if (pixelx1y1.a < 0.2) continue; - Vec4 pixelx2y1 = v4abgr(*(pixel + 1)); - Vec4 pixelx1y2 = v4abgr(*(pixel - src->x)); - Vec4 pixelx2y2 = v4abgr(*(pixel + 1 - src->x)); - - pixelx1y1 = srgb_to_almost_linear(pixelx1y1); - pixelx2y1 = srgb_to_almost_linear(pixelx2y1); - pixelx1y2 = srgb_to_almost_linear(pixelx1y2); - pixelx2y2 = srgb_to_almost_linear(pixelx2y2); - - Vec4 blendx1 = lerp(pixelx1y1, pixelx2y1, udiff); - Vec4 blendx2 = lerp(pixelx1y2, pixelx2y2, udiff); - Vec4 result_color = lerp(blendx1, blendx2, vdiff); - result_color = almost_linear_to_srgb(result_color); - ASSERT(result_color.r <= 1 && result_color.g <= 1 && result_color.b <= 1); - U32 color32 = color_to_u32abgr(result_color); - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_off_BILINEAR_BLEND_on (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * w1 + tex1.x * w2 + tex2.x * w3; - float v = tex0.y * w1 + tex1.y * w2 + tex2.y * w3; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - Vec4 pixelx1y1 = v4abgr(*pixel); - if (pixelx1y1.a < 0.2) continue; - Vec4 pixelx2y1 = v4abgr(*(pixel + 1)); - Vec4 pixelx1y2 = v4abgr(*(pixel - src->x)); - Vec4 pixelx2y2 = v4abgr(*(pixel + 1 - src->x)); - - pixelx1y1 = srgb_to_almost_linear(pixelx1y1); - pixelx2y1 = srgb_to_almost_linear(pixelx2y1); - pixelx1y2 = srgb_to_almost_linear(pixelx1y2); - pixelx2y2 = srgb_to_almost_linear(pixelx2y2); - - Vec4 blendx1 = lerp(pixelx1y1, pixelx2y1, udiff); - Vec4 blendx2 = lerp(pixelx1y2, pixelx2y2, udiff); - Vec4 result_color = lerp(blendx1, blendx2, vdiff); - result_color = almost_linear_to_srgb(result_color); - ASSERT(result_color.r <= 1 && result_color.g <= 1 && result_color.b <= 1); - U32 color32 = color_to_u32abgr(result_color); - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_on_BILINEAR_BLEND_off (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * (w1 / p0.w) + tex1.x * (w2 / p1.w) + tex2.x * (w3 / p2.w); - float v = tex0.y * (w1 / p0.w) + tex1.y * (w2 / p1.w) + tex2.y * (w3 / p2.w); - u /= interpolated_z; - v /= interpolated_z; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - U32 color32 = *pixel; - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} \ No newline at end of file diff --git a/rasterization_feature_selection.cpp b/rasterization_feature_selection.cpp deleted file mode 100644 index cb27ed0..0000000 --- a/rasterization_feature_selection.cpp +++ /dev/null @@ -1,165 +0,0 @@ -struct Token { - char* s; - int len; -}; - -FUNCTION bool is_alphabetic(char w) { - bool result = (w >= 'a' && w <= 'z') || (w >= 'A' && w <= 'Z'); - return result; -} - -FUNCTION bool is_number(char w) { - bool result = w >= '0' && w <= '9'; - return result; -} - -FUNCTION bool is_whitespace(char w) { - bool result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r'; - return result; -} - -FUNCTION int string_len(char* a) { - int result = 0; - while (*a++ != 0) result++; - return result; -} - -FUNCTION bool equals(Token a, const char* b) { - int len = string_len((char*)b); - if (a.len != len) return false; - for (int i = 0; i < len; i++) { - if (a.s[i] != b[i]) return false; - } - return true; -} - -bool combinations[64][8] = { { 0, 0 }, { 1, 1 }, { 0, 1 }, { 1, 0 } }; -int combinations_to_make = 4; - -struct Lexer { - char* stream; - char* data; - char output[10000]; - - Token next() { - while (is_whitespace(*stream)) stream++; - Token result = {}; - result.s = stream++; - if (is_alphabetic(*result.s)) { - while (is_alphabetic(*stream) || *stream == '_') stream++; - } - result.len = (int)(stream - result.s); - return result; - } - - bool match(const char* str, Token* out = 0) { - Lexer l = *this; - Token token = next(); - if (out) *out = token; - if (equals(token, str)) { - return true; - } - *this = l; - return false; - } -}; - -struct Section { - char* begin, * end; - char* name, * name_end; - int if_clause_i; - bool is_else; -}; - -FUNCTION void generate_stuff() { - char* data = os.read_file("main.cpp"); - FILE* f = fopen("raster_functions.cpp", "w"); - ASSERT(f); - Section sections[100] = {}; - int sections_count = 0; - int if_clause_count = 0; - Lexer lexer = { data, data }; - for (;;) { - Token token = lexer.next(); - if (*token.s == 0) break; - - if (equals(token, "FUNCTION") && - lexer.match("void") && - lexer.match("draw_triangle", &token)) { - Section* section = sections + sections_count++; - section->begin = token.s + token.len; - int indent = 1; - while (lexer.next().s[0] != '{'); - for (; ; ) { - token = lexer.next(); - if (token.s[0] == '{') indent++; - else if (token.s[0] == '}') indent--; - else if (token.s[0] == '#') { - if (lexer.match("if")) { - section->end = token.s; - - if_clause_count++; - token = lexer.next(); - section = sections + sections_count++; - section->if_clause_i = if_clause_count; - section->is_else = false; - section->name = token.s; - section->name_end = token.s + token.len; - section->begin = section->name_end; - } - else if (lexer.match("else")) { - section->end = token.s; - char* name = section->name; - char* name_end = section->name_end; - - section = sections + sections_count++; - section->is_else = true; - section->if_clause_i = if_clause_count; - section->name = name; - section->name_end = name_end; - section->begin = token.s + 5; - } - else if (lexer.match("endif")) { - section->end = token.s; - section = sections + sections_count++; - section->begin = token.s + 6; - } - } - - if (indent == 0) { - section->end = token.s + 1; - break; - } - } - - for (int ci = 0; ci < combinations_to_make; ci++) { - // @Note: Figure out function name - fprintf(f, "\nFUNCTION void draw_triangle"); - for (int i = 0; i < sections_count; i++) { - section = sections + i; - if (section->name && section->is_else == !combinations[ci][section->if_clause_i - 1]) { - fprintf(f, "_%.*s_", (int)(section->name_end - section->name), section->name); - fprintf(f, "%s", section->is_else ? "off" : "on"); - } - } - // @Note: Figure out function content - for (int i = 0; i < sections_count; i++) { - section = sections + i; - if (!section->name) { - fprintf(f, "%.*s %.*s", (int)(section->name_end - section->name), section->name, (int)(section->end - section->begin), section->begin); - } - else { - if (section->is_else == !combinations[ci][section->if_clause_i - 1]) { - fprintf(f, "// %.*s %.*s", (int)(section->name_end - section->name), section->name, (int)(section->end - section->begin), section->begin); - } - } - } - } - - - - - fclose(f); - } - } -} \ No newline at end of file diff --git a/test.txt b/test.txt deleted file mode 100644 index aa1c36b..0000000 --- a/test.txt +++ /dev/null @@ -1,249 +0,0 @@ - -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_off_BILINEAR_BLEND_off (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * w1 + tex1.x * w2 + tex2.x * w3; - float v = tex0.y * w1 + tex1.y * w2 + tex2.y * w3; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - U32 color32 = *pixel; - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_on_BILINEAR_BLEND_on (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * (w1 / p0.w) + tex1.x * (w2 / p1.w) + tex2.x * (w3 / p2.w); - float v = tex0.y * (w1 / p0.w) + tex1.y * (w2 / p1.w) + tex2.y * (w3 / p2.w); - u /= interpolated_z; - v /= interpolated_z; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - Vec4 pixelx1y1 = v4abgr(*pixel); - Vec4 pixelx2y1 = v4abgr(*(pixel + 1)); - Vec4 pixelx1y2 = v4abgr(*(pixel - src->x)); - Vec4 pixelx2y2 = v4abgr(*(pixel + 1 - src->x)); - - Vec4 blendx1 = lerp(pixelx1y1, pixelx2y1, udiff); - Vec4 blendx2 = lerp(pixelx1y2, pixelx2y2, udiff); - Vec4 result_color = lerp(blendx1, blendx2, vdiff); - U32 color32 = color_to_u32abgr(result_color); - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_off_BILINEAR_BLEND_on (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * w1 + tex1.x * w2 + tex2.x * w3; - float v = tex0.y * w1 + tex1.y * w2 + tex2.y * w3; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - Vec4 pixelx1y1 = v4abgr(*pixel); - Vec4 pixelx2y1 = v4abgr(*(pixel + 1)); - Vec4 pixelx1y2 = v4abgr(*(pixel - src->x)); - Vec4 pixelx2y2 = v4abgr(*(pixel + 1 - src->x)); - - Vec4 blendx1 = lerp(pixelx1y1, pixelx2y1, udiff); - Vec4 blendx2 = lerp(pixelx1y2, pixelx2y2, udiff); - Vec4 result_color = lerp(blendx1, blendx2, vdiff); - U32 color32 = color_to_u32abgr(result_color); - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} -FUNCTION void draw_triangle_PERSPECTIVE_CORRECT_INTERPOLATION_on_BILINEAR_BLEND_off (Image* dst, float *depth_buffer, Image *src, - Vec4 p0, Vec4 p1, Vec4 p2, - Vec2 tex0, Vec2 tex1, Vec2 tex2) { - float min_x1 = (float)(MIN(p0.x, MIN(p1.x, p2.x))); - float min_y1 = (float)(MIN(p0.y, MIN(p1.y, p2.y))); - float max_x1 = (float)(MAX(p0.x, MAX(p1.x, p2.x))); - float max_y1 = (float)(MAX(p0.y, MAX(p1.y, p2.y))); - I64 min_x = (I64)MAX(0, floor(min_x1)); - I64 min_y = (I64)MAX(0, floor(min_y1)); - I64 max_x = (I64)MIN(dst->x, ceil(max_x1)); - I64 max_y = (I64)MIN(dst->y, ceil(max_y1)); - - float area = edge_function(p0, p1, p2); - for (I64 y = min_y; y < max_y; y++) { - for (I64 x = min_x; x < max_x; x++) { - float edge1 = edge_function(p0, p1, { (float)x,(float)y }); - float edge2 = edge_function(p1, p2, { (float)x,(float)y }); - float edge3 = edge_function(p2, p0, { (float)x,(float)y }); - - if (edge1 >= 0 && edge2 >= 0 && edge3 >= 0) { - float w1 = edge2 / area; - float w2 = edge3 / area; - float w3 = edge1 / area; - float interpolated_z = (1.f / p0.w) * w1 + (1.f / p1.w) * w2 + (1.f / p2.w) * w3; -// PERSPECTIVE_CORRECT_INTERPOLATION - float u = tex0.x * (w1 / p0.w) + tex1.x * (w2 / p1.w) + tex2.x * (w3 / p2.w); - float v = tex0.y * (w1 / p0.w) + tex1.y * (w2 / p1.w) + tex2.y * (w3 / p2.w); - u /= interpolated_z; - v /= interpolated_z; - - // @Note: We could do: interpolated_z = 1.f / interpolated_z to get proper depth - // but why waste an instruction, the smaller the depth value the farther the object - float* depth = depth_buffer + (x + y * dst->x); - if (*depth < interpolated_z) { - *depth = interpolated_z; - u = u * (src->x - 2); - v = v * (src->y - 2); - I64 ui = (I64)(u); - I64 vi = (I64)(v); - float udiff = u - (float)ui; - float vdiff = v - (float)vi; - // Origin UV (0,0) is in bottom left - U32* pixel = src->pixels + (ui + (src->y - 1ll - vi) * src->x); - -// BILINEAR_BLEND - U32 color32 = *pixel; - - - dst->pixels[x + y * dst->x] = color32; - } - } - } - } - if (draw_rects) { - draw_rect(dst, p0.x-4, p0.y-4, 8,8, 0x00ff0000); - draw_rect(dst, p1.x-4, p1.y-4, 8,8, 0x0000ff00); - draw_rect(dst, p2.x-4, p2.y-4, 8,8, 0x000000ff); - } -} \ No newline at end of file