add ui module
This commit is contained in:
parent
1744e689b5
commit
6008ebf5ed
12 changed files with 703 additions and 215 deletions
364
src/pxl8_gfx.c
364
src/pxl8_gfx.c
|
|
@ -6,11 +6,37 @@
|
|||
|
||||
#include "pxl8_ase.h"
|
||||
#include "pxl8_blit.h"
|
||||
#include "pxl8_font.h"
|
||||
#include "pxl8_gfx.h"
|
||||
#include "pxl8_macros.h"
|
||||
#include "pxl8_math.h"
|
||||
#include "pxl8_types.h"
|
||||
|
||||
static inline void pxl8_color_unpack(u32 color, u8* r, u8* g, u8* b, u8* a) {
|
||||
*r = color & 0xFF;
|
||||
*g = (color >> 8) & 0xFF;
|
||||
*b = (color >> 16) & 0xFF;
|
||||
*a = (color >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
static inline u32 pxl8_color_pack(u8 r, u8 g, u8 b, u8 a) {
|
||||
return r | (g << 8) | (b << 16) | (a << 24);
|
||||
}
|
||||
|
||||
static inline u8 pxl8_color_lerp_channel(u8 c1, u8 c2, f32 t) {
|
||||
return c1 + (i32)((c2 - c1) * t);
|
||||
}
|
||||
|
||||
pxl8_viewport pxl8_gfx_viewport(pxl8_bounds bounds, i32 width, i32 height) {
|
||||
pxl8_viewport vp = {0};
|
||||
vp.scale = fminf(bounds.w / (f32)width, bounds.h / (f32)height);
|
||||
vp.scaled_width = (i32)(width * vp.scale);
|
||||
vp.scaled_height = (i32)(height * vp.scale);
|
||||
vp.offset_x = (bounds.w - vp.scaled_width) / 2;
|
||||
vp.offset_y = (bounds.h - vp.scaled_height) / 2;
|
||||
return vp;
|
||||
}
|
||||
|
||||
typedef struct pxl8_atlas_entry {
|
||||
char path[256];
|
||||
u32 sprite_id;
|
||||
|
|
@ -44,10 +70,7 @@ struct pxl8_gfx {
|
|||
u32 sprite_frame_width;
|
||||
u32 sprite_frames_per_row;
|
||||
|
||||
i32 viewport_height;
|
||||
i32 viewport_width;
|
||||
i32 viewport_x;
|
||||
i32 viewport_y;
|
||||
pxl8_viewport viewport;
|
||||
|
||||
bool backface_culling;
|
||||
pxl8_mat4 model;
|
||||
|
|
@ -191,10 +214,11 @@ pxl8_gfx* pxl8_gfx_create(pxl8_color_mode mode, pxl8_resolution resolution, cons
|
|||
}
|
||||
}
|
||||
|
||||
gfx->viewport_x = 0;
|
||||
gfx->viewport_y = 0;
|
||||
gfx->viewport_width = gfx->framebuffer_width;
|
||||
gfx->viewport_height = gfx->framebuffer_height;
|
||||
gfx->viewport.offset_x = 0;
|
||||
gfx->viewport.offset_y = 0;
|
||||
gfx->viewport.scaled_width = gfx->framebuffer_width;
|
||||
gfx->viewport.scaled_height = gfx->framebuffer_height;
|
||||
gfx->viewport.scale = 1.0f;
|
||||
|
||||
gfx->backface_culling = true;
|
||||
gfx->model = pxl8_mat4_identity();
|
||||
|
|
@ -241,7 +265,6 @@ void pxl8_gfx_destroy(pxl8_gfx* gfx) {
|
|||
SDL_free(gfx);
|
||||
}
|
||||
|
||||
// resource loading
|
||||
pxl8_result pxl8_gfx_init_atlas(pxl8_gfx* gfx, u32 width, u32 height) {
|
||||
if (!gfx || !gfx->initialized) return PXL8_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
|
|
@ -417,55 +440,53 @@ pxl8_result pxl8_gfx_load_font_atlas(pxl8_gfx* gfx) {
|
|||
return PXL8_OK;
|
||||
}
|
||||
|
||||
// rendering pipeline
|
||||
static void pxl8_upload_indexed_texture(SDL_Texture* texture, const u8* indexed, const u32* palette, u32 palette_size, i32 width, i32 height, u32 default_color) {
|
||||
static u32* rgba_buffer = NULL;
|
||||
static size_t buffer_size = 0;
|
||||
size_t needed_size = width * height;
|
||||
|
||||
if (buffer_size < needed_size) {
|
||||
rgba_buffer = (u32*)SDL_realloc(rgba_buffer, needed_size * 4);
|
||||
buffer_size = needed_size;
|
||||
}
|
||||
|
||||
if (!rgba_buffer) return;
|
||||
|
||||
for (i32 i = 0; i < width * height; i++) {
|
||||
u8 index = indexed[i];
|
||||
rgba_buffer[i] = (index < palette_size) ? palette[index] : default_color;
|
||||
}
|
||||
|
||||
SDL_UpdateTexture(texture, NULL, rgba_buffer, width * 4);
|
||||
}
|
||||
|
||||
void pxl8_gfx_upload_framebuffer(pxl8_gfx* gfx) {
|
||||
if (!gfx || !gfx->initialized || !gfx->framebuffer_texture) return;
|
||||
|
||||
|
||||
if (gfx->color_mode == PXL8_COLOR_MODE_HICOLOR) {
|
||||
SDL_UpdateTexture(gfx->framebuffer_texture, NULL, gfx->framebuffer,
|
||||
SDL_UpdateTexture(gfx->framebuffer_texture, NULL, gfx->framebuffer,
|
||||
gfx->framebuffer_width * 4);
|
||||
} else {
|
||||
static u32* rgba_buffer = NULL;
|
||||
static size_t buffer_size = 0;
|
||||
size_t needed_size = gfx->framebuffer_width * gfx->framebuffer_height;
|
||||
|
||||
if (buffer_size < needed_size) {
|
||||
rgba_buffer = (u32*)SDL_realloc(rgba_buffer, needed_size * 4);
|
||||
buffer_size = needed_size;
|
||||
}
|
||||
|
||||
if (!rgba_buffer) return;
|
||||
|
||||
for (i32 i = 0; i < gfx->framebuffer_width * gfx->framebuffer_height; i++) {
|
||||
u8 index = gfx->framebuffer[i];
|
||||
rgba_buffer[i] = (index < gfx->palette_size) ? gfx->palette[index] : 0xFF000000;
|
||||
}
|
||||
|
||||
SDL_UpdateTexture(gfx->framebuffer_texture, NULL, rgba_buffer,
|
||||
gfx->framebuffer_width * 4);
|
||||
pxl8_upload_indexed_texture(gfx->framebuffer_texture, gfx->framebuffer,
|
||||
gfx->palette, gfx->palette_size,
|
||||
gfx->framebuffer_width, gfx->framebuffer_height,
|
||||
0xFF000000);
|
||||
}
|
||||
}
|
||||
|
||||
void pxl8_gfx_upload_atlas(pxl8_gfx* gfx) {
|
||||
if (!gfx || !gfx->initialized || !gfx->sprite_atlas_texture || !gfx->atlas_dirty) return;
|
||||
|
||||
|
||||
if (gfx->color_mode == PXL8_COLOR_MODE_HICOLOR) {
|
||||
SDL_UpdateTexture(gfx->sprite_atlas_texture, NULL, gfx->atlas,
|
||||
SDL_UpdateTexture(gfx->sprite_atlas_texture, NULL, gfx->atlas,
|
||||
gfx->sprite_atlas_width * 4);
|
||||
} else {
|
||||
u32* rgba_buffer = (u32*)SDL_malloc(gfx->sprite_atlas_width * gfx->sprite_atlas_height * 4);
|
||||
if (!rgba_buffer) return;
|
||||
|
||||
for (u32 i = 0; i < gfx->sprite_atlas_width * gfx->sprite_atlas_height; i++) {
|
||||
u8 index = gfx->atlas[i];
|
||||
rgba_buffer[i] = (index < gfx->palette_size) ? gfx->palette[index] : 0x00000000;
|
||||
}
|
||||
|
||||
SDL_UpdateTexture(gfx->sprite_atlas_texture, NULL, rgba_buffer,
|
||||
gfx->sprite_atlas_width * 4);
|
||||
SDL_free(rgba_buffer);
|
||||
pxl8_upload_indexed_texture(gfx->sprite_atlas_texture, gfx->atlas,
|
||||
gfx->palette, gfx->palette_size,
|
||||
gfx->sprite_atlas_width, gfx->sprite_atlas_height,
|
||||
0x00000000);
|
||||
}
|
||||
|
||||
|
||||
gfx->atlas_dirty = false;
|
||||
pxl8_debug("Atlas uploaded to GPU");
|
||||
}
|
||||
|
|
@ -483,19 +504,15 @@ void pxl8_gfx_present(pxl8_gfx* gfx) {
|
|||
SDL_RenderPresent(gfx->renderer);
|
||||
}
|
||||
|
||||
void pxl8_gfx_viewport(pxl8_gfx* gfx, i32 x, i32 y, i32 width, i32 height) {
|
||||
void pxl8_gfx_set_viewport(pxl8_gfx* gfx, pxl8_viewport vp) {
|
||||
if (!gfx) return;
|
||||
gfx->viewport_x = x;
|
||||
gfx->viewport_y = y;
|
||||
gfx->viewport_width = width;
|
||||
gfx->viewport_height = height;
|
||||
gfx->viewport = vp;
|
||||
}
|
||||
|
||||
void pxl8_gfx_project(pxl8_gfx* gfx, f32 left, f32 right, f32 top, f32 bottom) {
|
||||
(void)gfx; (void)left; (void)right; (void)top; (void)bottom;
|
||||
}
|
||||
|
||||
// drawing primitives
|
||||
void pxl8_clr(pxl8_gfx* gfx, u32 color) {
|
||||
if (!gfx || !gfx->framebuffer) return;
|
||||
|
||||
|
|
@ -571,12 +588,26 @@ void pxl8_rect(pxl8_gfx* gfx, i32 x, i32 y, i32 w, i32 h, u32 color) {
|
|||
pxl8_line(gfx, x, y + h - 1, x, y, color);
|
||||
}
|
||||
|
||||
static inline void pxl8_pixel_unchecked(pxl8_gfx* gfx, i32 x, i32 y, u32 color) {
|
||||
i32 idx = y * gfx->framebuffer_width + x;
|
||||
if (gfx->color_mode == PXL8_COLOR_MODE_HICOLOR) {
|
||||
((u32*)gfx->framebuffer)[idx] = color;
|
||||
} else {
|
||||
gfx->framebuffer[idx] = color & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void pxl8_rect_fill(pxl8_gfx* gfx, i32 x, i32 y, i32 w, i32 h, u32 color) {
|
||||
if (!gfx) return;
|
||||
|
||||
for (i32 py = y; py < y + h; py++) {
|
||||
for (i32 px = x; px < x + w; px++) {
|
||||
pxl8_pixel(gfx, px, py, color);
|
||||
if (!gfx || !gfx->framebuffer) return;
|
||||
|
||||
i32 x0 = (x < 0) ? 0 : x;
|
||||
i32 y0 = (y < 0) ? 0 : y;
|
||||
i32 x1 = (x + w > gfx->framebuffer_width) ? gfx->framebuffer_width : x + w;
|
||||
i32 y1 = (y + h > gfx->framebuffer_height) ? gfx->framebuffer_height : y + h;
|
||||
|
||||
for (i32 py = y0; py < y1; py++) {
|
||||
for (i32 px = x0; px < x1; px++) {
|
||||
pxl8_pixel_unchecked(gfx, px, py, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -609,20 +640,65 @@ void pxl8_circle(pxl8_gfx* gfx, i32 cx, i32 cy, i32 radius, u32 color) {
|
|||
}
|
||||
|
||||
void pxl8_circle_fill(pxl8_gfx* gfx, i32 cx, i32 cy, i32 radius, u32 color) {
|
||||
if (!gfx) return;
|
||||
|
||||
for (i32 y = -radius; y <= radius; y++) {
|
||||
for (i32 x = -radius; x <= radius; x++) {
|
||||
if (!gfx || !gfx->framebuffer) return;
|
||||
|
||||
i32 x0 = (cx - radius < 0) ? -cx : -radius;
|
||||
i32 y0 = (cy - radius < 0) ? -cy : -radius;
|
||||
i32 x1 = (cx + radius >= gfx->framebuffer_width) ? gfx->framebuffer_width - cx - 1 : radius;
|
||||
i32 y1 = (cy + radius >= gfx->framebuffer_height) ? gfx->framebuffer_height - cy - 1 : radius;
|
||||
|
||||
for (i32 y = y0; y <= y1; y++) {
|
||||
for (i32 x = x0; x <= x1; x++) {
|
||||
if (x * x + y * y <= radius * radius) {
|
||||
pxl8_pixel(gfx, cx + x, cy + y, color);
|
||||
pxl8_pixel_unchecked(gfx, cx + x, cy + y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pxl8_text(pxl8_gfx* gfx, const char* text, i32 x, i32 y, u32 color) {
|
||||
if (!gfx || !text) return;
|
||||
(void)x; (void)y; (void)color;
|
||||
if (!gfx || !text || !gfx->framebuffer) return;
|
||||
|
||||
const pxl8_font* font = &pxl8_default_font;
|
||||
i32 cursor_x = x;
|
||||
i32 cursor_y = y;
|
||||
|
||||
for (const char* c = text; *c; c++) {
|
||||
const pxl8_glyph* glyph = pxl8_font_find_glyph(font, (u32)*c);
|
||||
if (!glyph) continue;
|
||||
|
||||
for (i32 gy = 0; gy < glyph->height; gy++) {
|
||||
for (i32 gx = 0; gx < glyph->width; gx++) {
|
||||
i32 px = cursor_x + gx;
|
||||
i32 py = cursor_y + gy;
|
||||
|
||||
if (px < 0 || px >= gfx->framebuffer_width ||
|
||||
py < 0 || py >= gfx->framebuffer_height) continue;
|
||||
|
||||
u8 pixel_bit = 0;
|
||||
|
||||
if (glyph->format == PXL8_FONT_FORMAT_INDEXED) {
|
||||
u8 pixel_byte = glyph->data.indexed[gy];
|
||||
pixel_bit = (pixel_byte >> gx) & 1;
|
||||
} else {
|
||||
i32 glyph_idx = gy * 8 + gx;
|
||||
u32 rgba_pixel = glyph->data.rgba[glyph_idx];
|
||||
pixel_bit = ((rgba_pixel >> 24) & 0xFF) > 128 ? 1 : 0;
|
||||
}
|
||||
|
||||
if (pixel_bit) {
|
||||
i32 fb_idx = py * gfx->framebuffer_width + px;
|
||||
if (gfx->color_mode == PXL8_COLOR_MODE_HICOLOR) {
|
||||
((u32*)gfx->framebuffer)[fb_idx] = color;
|
||||
} else {
|
||||
gfx->framebuffer[fb_idx] = (u8)color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cursor_x += font->default_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -681,7 +757,6 @@ void pxl8_sprite(pxl8_gfx* gfx, u32 sprite_id, i32 x, i32 y, i32 w, i32 h) {
|
|||
}
|
||||
}
|
||||
|
||||
// palette effects
|
||||
void pxl8_gfx_cycle_palette(pxl8_gfx* gfx, u8 start, u8 count, i32 step) {
|
||||
if (!gfx || !gfx->palette || count == 0) return;
|
||||
|
||||
|
|
@ -707,82 +782,63 @@ void pxl8_gfx_swap_palette(pxl8_gfx* gfx, u8 start, u8 count, u32* new_colors) {
|
|||
|
||||
void pxl8_gfx_fade_palette(pxl8_gfx* gfx, u8 start, u8 count, f32 amount, u32 target_color) {
|
||||
if (!gfx || !gfx->palette || count == 0) return;
|
||||
|
||||
|
||||
if (amount < 0.0f) amount = 0.0f;
|
||||
if (amount > 1.0f) amount = 1.0f;
|
||||
|
||||
u8 target_r = target_color & 0xFF;
|
||||
u8 target_g = (target_color >> 8) & 0xFF;
|
||||
u8 target_b = (target_color >> 16) & 0xFF;
|
||||
u8 target_a = (target_color >> 24) & 0xFF;
|
||||
|
||||
|
||||
u8 target_r, target_g, target_b, target_a;
|
||||
pxl8_color_unpack(target_color, &target_r, &target_g, &target_b, &target_a);
|
||||
|
||||
for (u8 i = 0; i < count && (start + i) < gfx->palette_size; i++) {
|
||||
u32 current = gfx->palette[start + i];
|
||||
u8 cur_r = current & 0xFF;
|
||||
u8 cur_g = (current >> 8) & 0xFF;
|
||||
u8 cur_b = (current >> 16) & 0xFF;
|
||||
u8 cur_a = (current >> 24) & 0xFF;
|
||||
|
||||
u8 new_r = cur_r + (i32)((target_r - cur_r) * amount);
|
||||
u8 new_g = cur_g + (i32)((target_g - cur_g) * amount);
|
||||
u8 new_b = cur_b + (i32)((target_b - cur_b) * amount);
|
||||
u8 new_a = cur_a + (i32)((target_a - cur_a) * amount);
|
||||
|
||||
gfx->palette[start + i] = new_r | (new_g << 8) | (new_b << 16) | (new_a << 24);
|
||||
u8 cur_r, cur_g, cur_b, cur_a;
|
||||
pxl8_color_unpack(gfx->palette[start + i], &cur_r, &cur_g, &cur_b, &cur_a);
|
||||
|
||||
u8 new_r = pxl8_color_lerp_channel(cur_r, target_r, amount);
|
||||
u8 new_g = pxl8_color_lerp_channel(cur_g, target_g, amount);
|
||||
u8 new_b = pxl8_color_lerp_channel(cur_b, target_b, amount);
|
||||
u8 new_a = pxl8_color_lerp_channel(cur_a, target_a, amount);
|
||||
|
||||
gfx->palette[start + i] = pxl8_color_pack(new_r, new_g, new_b, new_a);
|
||||
}
|
||||
}
|
||||
|
||||
void pxl8_gfx_interpolate_palettes(pxl8_gfx* gfx, u32* palette1, u32* palette2, u8 start, u8 count, f32 t) {
|
||||
if (!gfx || !gfx->palette || !palette1 || !palette2 || count == 0) return;
|
||||
|
||||
|
||||
if (t < 0.0f) t = 0.0f;
|
||||
if (t > 1.0f) t = 1.0f;
|
||||
|
||||
|
||||
for (u8 i = 0; i < count && (start + i) < gfx->palette_size; i++) {
|
||||
u32 col1 = palette1[i];
|
||||
u32 col2 = palette2[i];
|
||||
|
||||
u8 r1 = col1 & 0xFF;
|
||||
u8 g1 = (col1 >> 8) & 0xFF;
|
||||
u8 b1 = (col1 >> 16) & 0xFF;
|
||||
u8 a1 = (col1 >> 24) & 0xFF;
|
||||
|
||||
u8 r2 = col2 & 0xFF;
|
||||
u8 g2 = (col2 >> 8) & 0xFF;
|
||||
u8 b2 = (col2 >> 16) & 0xFF;
|
||||
u8 a2 = (col2 >> 24) & 0xFF;
|
||||
|
||||
u8 r = r1 + (i32)((r2 - r1) * t);
|
||||
u8 g = g1 + (i32)((g2 - g1) * t);
|
||||
u8 b = b1 + (i32)((b2 - b1) * t);
|
||||
u8 a = a1 + (i32)((a2 - a1) * t);
|
||||
|
||||
gfx->palette[start + i] = r | (g << 8) | (b << 16) | (a << 24);
|
||||
u8 r1, g1, b1, a1, r2, g2, b2, a2;
|
||||
pxl8_color_unpack(palette1[i], &r1, &g1, &b1, &a1);
|
||||
pxl8_color_unpack(palette2[i], &r2, &g2, &b2, &a2);
|
||||
|
||||
u8 r = pxl8_color_lerp_channel(r1, r2, t);
|
||||
u8 g = pxl8_color_lerp_channel(g1, g2, t);
|
||||
u8 b = pxl8_color_lerp_channel(b1, b2, t);
|
||||
u8 a = pxl8_color_lerp_channel(a1, a2, t);
|
||||
|
||||
gfx->palette[start + i] = pxl8_color_pack(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
void pxl8_gfx_color_ramp(pxl8_gfx* gfx, u8 start, u8 count, u32 from_color, u32 to_color) {
|
||||
if (!gfx || !gfx->palette || count <= 1) return;
|
||||
|
||||
u8 from_r = from_color & 0xFF;
|
||||
u8 from_g = (from_color >> 8) & 0xFF;
|
||||
u8 from_b = (from_color >> 16) & 0xFF;
|
||||
u8 from_a = (from_color >> 24) & 0xFF;
|
||||
|
||||
u8 to_r = to_color & 0xFF;
|
||||
u8 to_g = (to_color >> 8) & 0xFF;
|
||||
u8 to_b = (to_color >> 16) & 0xFF;
|
||||
u8 to_a = (to_color >> 24) & 0xFF;
|
||||
|
||||
|
||||
u8 from_r, from_g, from_b, from_a;
|
||||
u8 to_r, to_g, to_b, to_a;
|
||||
pxl8_color_unpack(from_color, &from_r, &from_g, &from_b, &from_a);
|
||||
pxl8_color_unpack(to_color, &to_r, &to_g, &to_b, &to_a);
|
||||
|
||||
for (u8 i = 0; i < count && (start + i) < gfx->palette_size; i++) {
|
||||
f32 t = (f32)i / (f32)(count - 1);
|
||||
|
||||
u8 r = from_r + (i32)((to_r - from_r) * t);
|
||||
u8 g = from_g + (i32)((to_g - from_g) * t);
|
||||
u8 b = from_b + (i32)((to_b - from_b) * t);
|
||||
u8 a = from_a + (i32)((to_a - from_a) * t);
|
||||
|
||||
gfx->palette[start + i] = r | (g << 8) | (b << 16) | (a << 24);
|
||||
|
||||
u8 r = pxl8_color_lerp_channel(from_r, to_r, t);
|
||||
u8 g = pxl8_color_lerp_channel(from_g, to_g, t);
|
||||
u8 b = pxl8_color_lerp_channel(from_b, to_b, t);
|
||||
u8 a = pxl8_color_lerp_channel(from_a, to_a, t);
|
||||
|
||||
gfx->palette[start + i] = pxl8_color_pack(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -895,6 +951,26 @@ void pxl8_3d_draw_line_3d(pxl8_gfx* gfx, pxl8_vec3 p0, pxl8_vec3 p1, u32 color)
|
|||
pxl8_line(gfx, x0, y0, x1, y1, color);
|
||||
}
|
||||
|
||||
static inline void pxl8_fill_scanline(pxl8_gfx* gfx, i32 y, i32 xs, i32 xe, f32 z0, f32 z1, u32 color) {
|
||||
if (y < 0 || y >= gfx->framebuffer_height) return;
|
||||
if (xs > xe) {
|
||||
i32 tmp = xs; xs = xe; xe = tmp;
|
||||
}
|
||||
|
||||
for (i32 x = xs; x <= xe; x++) {
|
||||
if (x >= 0 && x < gfx->framebuffer_width) {
|
||||
f32 t = (xe == xs) ? 0.0f : (f32)(x - xs) / (f32)(xe - xs);
|
||||
f32 z = z0 + t * (z1 - z0);
|
||||
|
||||
i32 idx = y * gfx->zbuffer_width + x;
|
||||
if (z <= gfx->zbuffer[idx]) {
|
||||
gfx->zbuffer[idx] = z;
|
||||
pxl8_pixel(gfx, x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pxl8_draw_flat_bottom_triangle(
|
||||
pxl8_gfx* gfx,
|
||||
i32 x0, i32 y0, f32 z0,
|
||||
|
|
@ -912,28 +988,7 @@ static void pxl8_draw_flat_bottom_triangle(
|
|||
f32 cur_x2 = (f32)x0;
|
||||
|
||||
for (i32 y = y0; y <= y1; y++) {
|
||||
if (y >= 0 && y < gfx->framebuffer_height) {
|
||||
i32 xs = (i32)cur_x1;
|
||||
i32 xe = (i32)cur_x2;
|
||||
|
||||
if (xs > xe) {
|
||||
i32 tmp = xs; xs = xe; xe = tmp;
|
||||
}
|
||||
|
||||
for (i32 x = xs; x <= xe; x++) {
|
||||
if (x >= 0 && x < gfx->framebuffer_width) {
|
||||
f32 t = (xe == xs) ? 0.0f : (f32)(x - xs) / (f32)(xe - xs);
|
||||
f32 z = z0 + t * (z1 - z0);
|
||||
|
||||
i32 idx = y * gfx->zbuffer_width + x;
|
||||
if (z <= gfx->zbuffer[idx]) {
|
||||
gfx->zbuffer[idx] = z;
|
||||
pxl8_pixel(gfx, x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_fill_scanline(gfx, y, (i32)cur_x1, (i32)cur_x2, z0, z1, color);
|
||||
cur_x1 += inv_slope_1;
|
||||
cur_x2 += inv_slope_2;
|
||||
}
|
||||
|
|
@ -956,28 +1011,7 @@ static void pxl8_draw_flat_top_triangle(
|
|||
f32 cur_x2 = (f32)x2;
|
||||
|
||||
for (i32 y = y2; y > y0; y--) {
|
||||
if (y >= 0 && y < gfx->framebuffer_height) {
|
||||
i32 xs = (i32)cur_x1;
|
||||
i32 xe = (i32)cur_x2;
|
||||
|
||||
if (xs > xe) {
|
||||
i32 tmp = xs; xs = xe; xe = tmp;
|
||||
}
|
||||
|
||||
for (i32 x = xs; x <= xe; x++) {
|
||||
if (x >= 0 && x < gfx->framebuffer_width) {
|
||||
f32 t = (xe == xs) ? 0.0f : (f32)(x - xs) / (f32)(xe - xs);
|
||||
f32 z = z0 + t * (z1 - z0);
|
||||
|
||||
i32 idx = y * gfx->zbuffer_width + x;
|
||||
if (z <= gfx->zbuffer[idx]) {
|
||||
gfx->zbuffer[idx] = z;
|
||||
pxl8_pixel(gfx, x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_fill_scanline(gfx, y, (i32)cur_x1, (i32)cur_x2, z0, z1, color);
|
||||
cur_x1 -= inv_slope_1;
|
||||
cur_x2 -= inv_slope_2;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue