249 lines
10 KiB
Plaintext
249 lines
10 KiB
Plaintext
|
|
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);
|
|
|
|
}
|
|
|
|
} |