diff --git a/demo/mod/first_person3d.fnl b/demo/mod/first_person3d.fnl index fefa7ec..c0051dd 100644 --- a/demo/mod/first_person3d.fnl +++ b/demo/mod/first_person3d.fnl @@ -349,11 +349,12 @@ r2 (* 0.04 (math.sin (+ (* real-time 3.2) phase))) light-radius (* 150 (+ 0.95 r1 r2))] (lights:clear) - (lights:add light-x light-y light-z 0xFFB888 light-intensity light-radius) + (lights:add light-x light-y light-z 2 light-intensity light-radius) (pxl8.push_target) (pxl8.begin_frame_3d camera lights { :ambient 25 + :dither true :fog_density 0.0 :celestial_dir [0.5 -0.8 0.3] :celestial_intensity 0.3}) diff --git a/src/core/pxl8.c b/src/core/pxl8.c index bf3b9a8..ac06e7d 100644 --- a/src/core/pxl8.c +++ b/src/core/pxl8.c @@ -340,7 +340,6 @@ pxl8_result pxl8_update(pxl8* sys) { if (game->fps_accumulator >= 1.0f) { game->fps = (f32)game->fps_frame_count / game->fps_accumulator; - pxl8_info("FPS: %.1f", game->fps); game->fps_accumulator = 0.0f; game->fps_frame_count = 0; } diff --git a/src/gfx/pxl8_colormap.h b/src/gfx/pxl8_colormap.h index fb9f714..584e448 100644 --- a/src/gfx/pxl8_colormap.h +++ b/src/gfx/pxl8_colormap.h @@ -37,7 +37,7 @@ typedef struct { static const pxl8_rgb pxl8_light_colors[PXL8_LIGHT_COLORS] = { {255, 255, 255}, {255, 64, 64}, - {255, 160, 64}, + {255, 192, 64}, {255, 255, 64}, {64, 255, 64}, {64, 255, 255}, diff --git a/src/gfx/pxl8_gfx.c b/src/gfx/pxl8_gfx.c index 1dadd12..42642af 100644 --- a/src/gfx/pxl8_gfx.c +++ b/src/gfx/pxl8_gfx.c @@ -53,7 +53,6 @@ struct pxl8_gfx { pxl8_renderer* renderer; pxl8_gfx_texture color_target; pxl8_gfx_texture depth_target; - pxl8_gfx_texture light_target; pxl8_gfx_cmdbuf* cmdbuf; pxl8_target_entry target_stack[PXL8_MAX_TARGET_STACK]; u32 target_stack_depth; @@ -115,11 +114,6 @@ i32 pxl8_gfx_get_height(const pxl8_gfx* gfx) { return gfx ? gfx->framebuffer_height : 0; } -u32* pxl8_gfx_get_light_accum(pxl8_gfx* gfx) { - if (!gfx) return NULL; - return (u32*)pxl8_texture_get_data(gfx->renderer, gfx->light_target); -} - u32* pxl8_gfx_get_output(pxl8_gfx* gfx) { if (!gfx) return NULL; return gfx->output; @@ -137,7 +131,6 @@ void pxl8_gfx_resolve(pxl8_gfx* gfx) { pxl8_resolve_to_rgba( gfx->renderer, gfx->color_target, - gfx->light_target, pal, gfx->output ); @@ -246,14 +239,6 @@ pxl8_gfx* pxl8_gfx_create( }; gfx->depth_target = pxl8_create_texture(gfx->renderer, &depth_desc); - pxl8_gfx_texture_desc light_desc = { - .width = (u32)gfx->framebuffer_width, - .height = (u32)gfx->framebuffer_height, - .format = PXL8_GFX_FORMAT_LIGHT_ACCUM, - .render_target = true, - }; - gfx->light_target = pxl8_create_texture(gfx->renderer, &light_desc); - u32 pixel_count = (u32)gfx->framebuffer_width * (u32)gfx->framebuffer_height; gfx->output = pxl8_calloc(pixel_count, sizeof(u32)); if (!gfx->output) { @@ -276,7 +261,6 @@ pxl8_gfx* pxl8_gfx_create( gfx->target_stack[0] = (pxl8_target_entry){ .color = gfx->color_target, .depth = gfx->depth_target, - .light = gfx->light_target, }; gfx->target_stack_depth = 1; @@ -469,16 +453,6 @@ void pxl8_gfx_present(pxl8_gfx* gfx) { gfx->hal->present(gfx->platform_data); } -void pxl8_gfx_reset_stats(pxl8_gfx* gfx) { - if (!gfx || !gfx->renderer) return; - pxl8_renderer_reset_stats(gfx->renderer); -} - -const pxl8_gfx_stats* pxl8_gfx_get_stats(pxl8_gfx* gfx) { - if (!gfx || !gfx->renderer) return NULL; - return pxl8_renderer_get_stats(gfx->renderer); -} - 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); @@ -508,11 +482,6 @@ static pxl8_gfx_texture gfx_current_depth(pxl8_gfx* gfx) { return gfx->target_stack[gfx->target_stack_depth - 1].depth; } -static pxl8_gfx_texture gfx_current_light(pxl8_gfx* gfx) { - if (gfx->target_stack_depth == 0) return gfx->light_target; - return gfx->target_stack[gfx->target_stack_depth - 1].light; -} - static void gfx_composite_over(pxl8_gfx* gfx, const pxl8_target_entry* src, pxl8_target_entry* dst) { if (!gfx || !src || !dst) return; @@ -546,7 +515,6 @@ static void gfx_composite_over(pxl8_gfx* gfx, const pxl8_target_entry* src, pxl8 void pxl8_2d_clear(pxl8_gfx* gfx, u32 color) { if (!gfx) return; pxl8_clear(gfx->renderer, gfx_current_color(gfx), (u8)color); - pxl8_clear_light(gfx->renderer, gfx_current_light(gfx)); } void pxl8_2d_pixel(pxl8_gfx* gfx, i32 x, i32 y, u32 color) { @@ -745,7 +713,6 @@ void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8 pxl8_gfx_pass_desc pass_desc = { .color = { .texture = gfx_current_color(gfx), .load = PXL8_GFX_LOAD_CLEAR, .clear_value = 0 }, .depth = { .texture = gfx_current_depth(gfx), .load = PXL8_GFX_LOAD_CLEAR, .clear_value = 0xFFFF }, - .light_accum = { .texture = gfx_current_light(gfx), .load = PXL8_GFX_LOAD_CLEAR }, }; gfx->frame_pass = pxl8_create_pass(gfx->renderer, &pass_desc); pxl8_begin_pass(gfx->cmdbuf, gfx->frame_pass); @@ -791,7 +758,6 @@ u32 pxl8_3d_project_points(pxl8_gfx* gfx, const pxl8_vec3* in, pxl8_vec3* out, u void pxl8_3d_clear(pxl8_gfx* gfx, u8 color) { if (!gfx) return; pxl8_clear(gfx->renderer, gfx_current_color(gfx), color); - pxl8_clear_light(gfx->renderer, gfx_current_light(gfx)); } void pxl8_3d_clear_depth(pxl8_gfx* gfx) { @@ -1001,18 +967,9 @@ bool pxl8_gfx_push_target(pxl8_gfx* gfx) { }; pxl8_gfx_texture new_depth = pxl8_create_texture(gfx->renderer, &depth_desc); - pxl8_gfx_texture_desc light_desc = { - .width = (u32)gfx->framebuffer_width, - .height = (u32)gfx->framebuffer_height, - .format = PXL8_GFX_FORMAT_LIGHT_ACCUM, - .render_target = true, - }; - pxl8_gfx_texture new_light = pxl8_create_texture(gfx->renderer, &light_desc); - gfx->target_stack[gfx->target_stack_depth] = (pxl8_target_entry){ .color = new_color, .depth = new_depth, - .light = new_light, }; gfx->target_stack_depth++; diff --git a/src/gfx/pxl8_gfx.h b/src/gfx/pxl8_gfx.h index 8a09a33..c9141c7 100644 --- a/src/gfx/pxl8_gfx.h +++ b/src/gfx/pxl8_gfx.h @@ -10,7 +10,19 @@ #include "pxl8_gui_palette.h" typedef struct pxl8_gfx pxl8_gfx; -typedef struct pxl8_gfx_stats pxl8_gfx_stats; + +typedef struct pxl8_gfx_stats { + u64 draw_calls; + u64 triangles; + u64 clipped_triangles; + u64 depth_tests; + u64 depth_passes; + u64 shader_calls; + u64 pixels_written; + u64 submit_ns; + u64 execute_draw_ns; + u64 raster_ns; +} pxl8_gfx_stats; typedef enum pxl8_gfx_effect { PXL8_GFX_EFFECT_GLOWS = 0, @@ -26,8 +38,6 @@ void pxl8_gfx_destroy(pxl8_gfx* gfx); void pxl8_gfx_present(pxl8_gfx* gfx); void pxl8_gfx_update(pxl8_gfx* gfx, f32 dt); void pxl8_gfx_upload_framebuffer(pxl8_gfx* gfx); -void pxl8_gfx_reset_stats(pxl8_gfx* gfx); -const pxl8_gfx_stats* pxl8_gfx_get_stats(pxl8_gfx* gfx); u8 pxl8_gfx_find_color(pxl8_gfx* gfx, u32 color); @@ -35,7 +45,6 @@ pxl8_bounds pxl8_gfx_get_bounds(pxl8_gfx* gfx); u8* pxl8_gfx_get_framebuffer_indexed(pxl8_gfx* gfx); u16* pxl8_gfx_get_framebuffer_hicolor(pxl8_gfx* gfx); i32 pxl8_gfx_get_height(const pxl8_gfx* gfx); -u32* pxl8_gfx_get_light_accum(pxl8_gfx* gfx); const u32* pxl8_gfx_palette_colors(pxl8_gfx* gfx); u16* pxl8_gfx_get_zbuffer(pxl8_gfx* gfx); pxl8_palette* pxl8_gfx_palette(pxl8_gfx* gfx); diff --git a/src/gfx/pxl8_lights.c b/src/gfx/pxl8_lights.c index 7180e6a..de3d304 100644 --- a/src/gfx/pxl8_lights.c +++ b/src/gfx/pxl8_lights.c @@ -33,16 +33,16 @@ void pxl8_lights_destroy(pxl8_lights* lights) { pxl8_free(lights); } -void pxl8_lights_add(pxl8_lights* lights, f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, u8 intensity, f32 radius) { - (void)r; (void)g; (void)b; +void pxl8_lights_add(pxl8_lights* lights, f32 x, f32 y, f32 z, u8 color, u8 intensity, f32 radius) { if (!lights || lights->count >= lights->capacity) return; f32 radius_sq = radius * radius; pxl8_light* l = &lights->data[lights->count++]; + l->color = color; + l->intensity = (f32)intensity / 255.0f; + l->inv_radius_sq = radius_sq > 0.0f ? 1.0f / radius_sq : 0.0f; l->position = (pxl8_vec3){{x, y, z}}; l->radius_sq = radius_sq; - l->inv_radius_sq = radius_sq > 0.0f ? 1.0f / radius_sq : 0.0f; - l->intensity = (f32)intensity / 255.0f; } void pxl8_lights_clear(pxl8_lights* lights) { diff --git a/src/gfx/pxl8_lights.h b/src/gfx/pxl8_lights.h index 5763410..15d861a 100644 --- a/src/gfx/pxl8_lights.h +++ b/src/gfx/pxl8_lights.h @@ -6,10 +6,11 @@ #define PXL8_LIGHTS_MAX 256 typedef struct pxl8_light { + u8 color; + f32 intensity; + f32 inv_radius_sq; pxl8_vec3 position; f32 radius_sq; - f32 inv_radius_sq; - f32 intensity; } pxl8_light; typedef struct pxl8_lights pxl8_lights; @@ -21,7 +22,7 @@ extern "C" { pxl8_lights* pxl8_lights_create(u32 capacity); void pxl8_lights_destroy(pxl8_lights* lights); -void pxl8_lights_add(pxl8_lights* lights, f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, u8 intensity, f32 radius); +void pxl8_lights_add(pxl8_lights* lights, f32 x, f32 y, f32 z, u8 color, u8 intensity, f32 radius); void pxl8_lights_clear(pxl8_lights* lights); u32 pxl8_lights_count(const pxl8_lights* lights); const pxl8_light* pxl8_lights_data(const pxl8_lights* lights); diff --git a/src/gfx/pxl8_render.c b/src/gfx/pxl8_render.c index 0135da8..7fca76d 100644 --- a/src/gfx/pxl8_render.c +++ b/src/gfx/pxl8_render.c @@ -12,16 +12,6 @@ #include #include -#if PXL8_GFX_ENABLE_STATS -#define STATS_INC(stats, field, val) do { (stats)->field += (val); } while (0) -#define STATS_START() pxl8_get_ticks_ns() -#define STATS_ADD(stats, field, start) do { (stats)->field += pxl8_get_ticks_ns() - (start); } while (0) -#else -#define STATS_INC(stats, field, val) do { (void)(stats); } while (0) -#define STATS_START() 0 -#define STATS_ADD(stats, field, start) do { (void)(stats); (void)(start); } while (0) -#endif - typedef struct { pxl8_vec4 clip_pos; pxl8_vec3 world_pos; @@ -300,8 +290,7 @@ static void rasterize_triangle( pxl8_shader_fn shader, const pxl8_gfx_pipeline_desc* pipeline, const pxl8_shader_bindings* bindings, - const pxl8_shader_uniforms* uniforms, - pxl8_gfx_stats* stats + const pxl8_shader_uniforms* uniforms ) { const i32 SUBDIV = 16; @@ -490,8 +479,6 @@ static void rasterize_triangle( pxl8_i32_simd zbuf = pxl8_i32_simd_set4((i32)zrow[px], (i32)zrow[px+1], (i32)zrow[px+2], (i32)zrow[px+3]); i32 mask = pxl8_i32_simd_movemask(pxl8_i32_simd_cmpgt(zbuf, z16_4)); - STATS_INC(stats, depth_tests, 4); - if (mask) { pxl8_shader_ctx frag_ctx = { .color_count = 4, @@ -517,20 +504,16 @@ static void rasterize_triangle( u8 colors[4]; shader(&frag_ctx, bindings, uniforms, colors); - STATS_INC(stats, shader_calls, 1); i32 z16_arr[4]; pxl8_i32_simd_store(z16_arr, z16_4); for (i32 i = 0; i < 4; i++) { if (!(mask & (0x8 << (i * 4)))) continue; - STATS_INC(stats, depth_passes, 1); - u8 color = colors[i]; if (!(alpha_test && color <= alpha_ref) && color != 0) { prow[px + i] = color; if (depth_write) zrow[px + i] = (u16)z16_arr[i]; - STATS_INC(stats, pixels_written, 1); } } } @@ -540,16 +523,12 @@ static void rasterize_triangle( z4 = pxl8_f32_simd_add(z4, dz4_simd); } } -#endif - for (; px <= span_end; px++) { f32 depth_norm = pxl8_clamp((z_a + 1.0f) * 0.5f, 0.0f, 1.0f); u16 z16 = (u16)(depth_norm * 65535.0f); - STATS_INC(stats, depth_tests, 1); bool depth_pass = !depth_test || depth_test_pass(depth_compare, z16, zrow[px]); if (depth_pass) { - STATS_INC(stats, depth_passes, 1); pxl8_shader_ctx frag_ctx = { .color_count = 1, .x = pxl8_i32_simd_set(px), @@ -564,7 +543,6 @@ static void rasterize_triangle( u8 color; shader(&frag_ctx, bindings, uniforms, &color); - STATS_INC(stats, shader_calls, 1); if (!(alpha_test && color <= alpha_ref)) { if (color != 0) { @@ -577,7 +555,6 @@ static void rasterize_triangle( if (depth_write) { zrow[px] = z16; } - STATS_INC(stats, pixels_written, 1); } } } @@ -591,6 +568,53 @@ static void rasterize_triangle( wy_a += dwy; wz_a += dwz; } +#else + for (; px <= span_end; px++) { + f32 depth_norm = pxl8_clamp((z_a + 1.0f) * 0.5f, 0.0f, 1.0f); + u16 z16 = (u16)(depth_norm * 65535.0f); + + bool depth_pass = !depth_test || depth_test_pass(depth_compare, z16, zrow[px]); + if (depth_pass) { + pxl8_shader_ctx frag_ctx = { + .color_count = 1, + .x = px, + .y = y, + .v_uv = { u_a, v_a }, + .v_world = { wx_a, wy_a, wz_a }, + .v_normal = setup->normal, + .v_light = l_a / 255.0f, + .v_color = c_a, + .v_depth = z_a, + }; + + u8 color; + shader(&frag_ctx, bindings, uniforms, &color); + + if (!(alpha_test && color <= alpha_ref)) { + if (color != 0) { + u8 out_color = color; + if (blend_enabled) { + out_color = blend_indexed(pipeline, color, prow[px], palette, colormap); + } + + prow[px] = out_color; + if (depth_write) { + zrow[px] = z16; + } + } + } + } + + u_a += du; + v_a += dv; + l_a += dl; + c_a += dc; + z_a += dz; + wx_a += dwx; + wy_a += dwy; + wz_a += dwz; + } +#endif wr += dwr * (f32)span_len; uw += duw * (f32)span_len; @@ -618,8 +642,7 @@ static void draw_line_clipped( i32 clip_min_x, i32 clip_min_y, i32 clip_max_x, - i32 clip_max_y, - pxl8_gfx_stats* stats + i32 clip_max_y ) { i32 dx = abs(x1 - x0); i32 dy = -abs(y1 - y0); @@ -631,7 +654,6 @@ static void draw_line_clipped( if (x0 >= clip_min_x && x0 <= clip_max_x && y0 >= clip_min_y && y0 <= clip_max_y) { if (x0 >= 0 && y0 >= 0 && x0 < (i32)fb_w && y0 < (i32)fb_h) { fb[y0 * (i32)fb_w + x0] = color; - STATS_INC(stats, pixels_written, 1); } } if (x0 == x1 && y0 == y1) break; @@ -718,7 +740,6 @@ struct pxl8_renderer { u32 scissor_w, scissor_h; pxl8_shader_fn shader; - pxl8_gfx_stats stats; }; struct pxl8_gfx_cmdbuf { @@ -735,7 +756,6 @@ pxl8_renderer* pxl8_renderer_create(u32 width, u32 height) { r->viewport_h = height; r->scissor_w = width; r->scissor_h = height; - pxl8_renderer_reset_stats(r); return r; } @@ -762,20 +782,10 @@ void pxl8_renderer_set_shader(pxl8_renderer* r, pxl8_shader_fn fn) { if (r) r->shader = fn; } -void pxl8_renderer_reset_stats(pxl8_renderer* r) { - if (!r) return; - memset(&r->stats, 0, sizeof(r->stats)); -} - -const pxl8_gfx_stats* pxl8_renderer_get_stats(const pxl8_renderer* r) { - return r ? &r->stats : NULL; -} - static u32 texture_byte_size(pxl8_gfx_texture_format fmt, u32 w, u32 h) { switch (fmt) { case PXL8_GFX_FORMAT_INDEXED8: return w * h; case PXL8_GFX_FORMAT_DEPTH16: return w * h * 2; - case PXL8_GFX_FORMAT_LIGHT_ACCUM: return w * h * 4; } return 0; } @@ -1085,9 +1095,6 @@ static void execute_draw( if (!VALID_PASS(r, r->current_pass)) return; if (!VALID_PIPELINE(r, r->current_pipeline)) return; - u64 exec_start = STATS_START(); - STATS_INC(&r->stats, draw_calls, 1); - buffer_slot* vb = &r->buffers[SLOT_INDEX(cmd->vertex_buffer.id)]; buffer_slot* ib = use_indices ? &r->buffers[SLOT_INDEX(cmd->index_buffer.id)] : NULL; pass_slot* pass = &r->passes[SLOT_INDEX(r->current_pass.id)]; @@ -1095,12 +1102,10 @@ static void execute_draw( if (!VALID_TEX(r, pass->desc.color.texture)) { pxl8_error("draw: invalid color texture"); - STATS_ADD(&r->stats, execute_draw_ns, exec_start); return; } if (!VALID_TEX(r, pass->desc.depth.texture)) { pxl8_error("draw: invalid depth texture"); - STATS_ADD(&r->stats, execute_draw_ns, exec_start); return; } @@ -1112,10 +1117,7 @@ static void execute_draw( u32 fb_w = color_tex->width; u32 fb_h = color_tex->height; - if (r->viewport_w == 0 || r->viewport_h == 0) { - STATS_ADD(&r->stats, execute_draw_ns, exec_start); - return; - } + if (r->viewport_w == 0 || r->viewport_h == 0) return; i32 vp_x = r->viewport_x; i32 vp_y = r->viewport_y; @@ -1143,10 +1145,7 @@ static void execute_draw( if (clip_min_y < 0) clip_min_y = 0; if (clip_max_x >= (i32)fb_w) clip_max_x = (i32)fb_w - 1; if (clip_max_y >= (i32)fb_h) clip_max_y = (i32)fb_h - 1; - if (clip_min_x > clip_max_x || clip_min_y > clip_max_y) { - STATS_ADD(&r->stats, execute_draw_ns, exec_start); - return; - } + if (clip_min_x > clip_max_x || clip_min_y > clip_max_y) return; const pxl8_vertex* vertices = vb->data; const u16* indices = use_indices ? ib->data : NULL; @@ -1156,10 +1155,7 @@ static void execute_draw( f32 near = 0.1f; pxl8_shader_fn shader = pip->desc.shader; - if (!shader) { - STATS_ADD(&r->stats, execute_draw_ns, exec_start); - return; - } + if (!shader) return; pxl8_shader_bindings shader_bindings = {0}; pxl8_shader_uniforms shader_uniforms = r->current_draw_params.shader; @@ -1190,8 +1186,8 @@ static void execute_draw( bool is_wireframe = pip->desc.rasterizer.fill == PXL8_GFX_FILL_WIREFRAME; for (u32 i = cmd->first_index; i < cmd->first_index + cmd->index_count; i += 3) { - STATS_INC(&r->stats, triangles, 1); u16 i0, i1, i2; + if (use_indices) { if (i + 2 >= ib->size / sizeof(u16)) break; i0 = indices[i] + cmd->base_vertex; @@ -1262,7 +1258,6 @@ static void execute_draw( i32 clipped_count = clip_triangle_near(&rv0, &rv1, &rv2, near, clipped); for (i32 t = 0; t < clipped_count; t += 3) { - STATS_INC(&r->stats, clipped_triangles, 1); if (is_wireframe) { f32 hw = (f32)vp_w * 0.5f; f32 hh = (f32)vp_h * 0.5f; @@ -1286,11 +1281,11 @@ static void execute_draw( u8 wire_color = v0->color ? v0->color : 15; draw_line_clipped(fb, fb_w, fb_h, sx0, sy0, sx1, sy1, wire_color, - clip_min_x, clip_min_y, clip_max_x, clip_max_y, &r->stats); + clip_min_x, clip_min_y, clip_max_x, clip_max_y); draw_line_clipped(fb, fb_w, fb_h, sx1, sy1, sx2, sy2, wire_color, - clip_min_x, clip_min_y, clip_max_x, clip_max_y, &r->stats); + clip_min_x, clip_min_y, clip_max_x, clip_max_y); draw_line_clipped(fb, fb_w, fb_h, sx2, sy2, sx0, sy0, wire_color, - clip_min_x, clip_min_y, clip_max_x, clip_max_y, &r->stats); + clip_min_x, clip_min_y, clip_max_x, clip_max_y); } else { tri_setup setup; if (!setup_tri(&setup, &clipped[t], &clipped[t+1], &clipped[t+2], @@ -1300,19 +1295,14 @@ static void execute_draw( continue; } - u64 raster_start = STATS_START(); rasterize_triangle(&setup, fb, zb, fb_w, shader, &pip->desc, - &shader_bindings, &shader_uniforms, &r->stats); - STATS_ADD(&r->stats, raster_ns, raster_start); + &shader_bindings, &shader_uniforms); } } } - - STATS_ADD(&r->stats, execute_draw_ns, exec_start); } void pxl8_gfx_submit(pxl8_renderer* r, pxl8_gfx_cmdbuf* cb) { - u64 submit_start = STATS_START(); for (u32 i = 0; i < cb->count; i++) { pxl8_gfx_cmd* cmd = &cb->commands[i]; switch (cmd->type) { @@ -1322,13 +1312,8 @@ void pxl8_gfx_submit(pxl8_renderer* r, pxl8_gfx_cmdbuf* cb) { pass_slot* p = &r->passes[SLOT_INDEX(cmd->begin_pass.pass.id)]; if (p->desc.color.load == PXL8_GFX_LOAD_CLEAR) { pxl8_clear(r, p->desc.color.texture, p->desc.color.clear_value); - } - if (p->desc.depth.load == PXL8_GFX_LOAD_CLEAR) { pxl8_clear_depth(r, p->desc.depth.texture); } - if (p->desc.light_accum.load == PXL8_GFX_LOAD_CLEAR) { - pxl8_clear_light(r, p->desc.light_accum.texture); - } } break; case PXL8_GFX_CMD_END_PASS: @@ -1368,7 +1353,6 @@ void pxl8_gfx_submit(pxl8_renderer* r, pxl8_gfx_cmdbuf* cb) { r->buffers[i].append_pos = 0; } } - STATS_ADD(&r->stats, submit_ns, submit_start); } void pxl8_clear(pxl8_renderer* r, pxl8_gfx_texture target, u8 color) { @@ -1387,14 +1371,6 @@ void pxl8_clear_depth(pxl8_renderer* r, pxl8_gfx_texture target) { } } -void pxl8_clear_light(pxl8_renderer* r, pxl8_gfx_texture target) { - if (!VALID_TEX(r, target)) return; - texture_slot* s = &r->textures[SLOT_INDEX(target.id)]; - if (s->format == PXL8_GFX_FORMAT_LIGHT_ACCUM) { - memset(s->data, 0, s->width * s->height * 4); - } -} - void pxl8_draw_pixel(pxl8_renderer* r, pxl8_gfx_texture target, i32 x, i32 y, u8 color) { if (!VALID_TEX(r, target)) return; texture_slot* s = &r->textures[SLOT_INDEX(target.id)]; @@ -1516,8 +1492,7 @@ void pxl8_draw_circle_fill(pxl8_renderer* r, pxl8_gfx_texture target, i32 cx, i3 } } -void pxl8_resolve_to_rgba(pxl8_renderer* r, pxl8_gfx_texture color, pxl8_gfx_texture light_accum, - const u32* palette, u32* output) { +void pxl8_resolve_to_rgba(pxl8_renderer* r, pxl8_gfx_texture color, const u32* palette, u32* output) { if (!VALID_TEX(r, color)) return; texture_slot* cs = &r->textures[SLOT_INDEX(color.id)]; @@ -1525,12 +1500,10 @@ void pxl8_resolve_to_rgba(pxl8_renderer* r, pxl8_gfx_texture color, pxl8_gfx_tex u32 w = cs->width; u32 h = cs->height; u32 total = w * h; - - (void)light_accum; + u32 i = 0; #if defined(PXL8_SIMD_SSE) || defined(PXL8_SIMD_NEON) pxl8_i32_simd alpha_mask = pxl8_i32_simd_set((i32)0xFF000000); - u32 i = 0; for (; i + 4 <= total; i += 4) { pxl8_i32_simd base = pxl8_i32_simd_set4( (i32)palette[fb[i + 0]], (i32)palette[fb[i + 1]], @@ -1539,12 +1512,10 @@ void pxl8_resolve_to_rgba(pxl8_renderer* r, pxl8_gfx_texture color, pxl8_gfx_tex base = pxl8_i32_simd_or(base, alpha_mask); pxl8_i32_simd_store((i32*)&output[i], base); } +#endif + for (; i < total; i++) { output[i] = palette[fb[i]] | 0xFF000000; } -#else - for (u32 i = 0; i < total; i++) { - output[i] = palette[fb[i]] | 0xFF000000; - } -#endif + } diff --git a/src/gfx/pxl8_render.h b/src/gfx/pxl8_render.h index 906def2..f3a43df 100644 --- a/src/gfx/pxl8_render.h +++ b/src/gfx/pxl8_render.h @@ -4,10 +4,6 @@ #include "pxl8_render_types.h" #include "pxl8_shader.h" -#ifndef PXL8_GFX_ENABLE_STATS -#define PXL8_GFX_ENABLE_STATS 1 -#endif - #ifdef __cplusplus extern "C" { #endif @@ -15,25 +11,9 @@ extern "C" { typedef struct pxl8_renderer pxl8_renderer; typedef struct pxl8_gfx_cmdbuf pxl8_gfx_cmdbuf; -typedef struct pxl8_gfx_stats { - u64 draw_calls; - u64 triangles; - u64 clipped_triangles; - u64 depth_tests; - u64 depth_passes; - u64 shader_calls; - u64 pixels_written; - u64 light_writes; - u64 submit_ns; - u64 execute_draw_ns; - u64 raster_ns; -} pxl8_gfx_stats; - pxl8_renderer* pxl8_renderer_create(u32 width, u32 height); void pxl8_renderer_destroy(pxl8_renderer* r); void pxl8_renderer_set_shader(pxl8_renderer* r, pxl8_shader_fn fn); -void pxl8_renderer_reset_stats(pxl8_renderer* r); -const pxl8_gfx_stats* pxl8_renderer_get_stats(const pxl8_renderer* r); u32 pxl8_renderer_get_width(const pxl8_renderer* r); u32 pxl8_renderer_get_height(const pxl8_renderer* r); @@ -73,14 +53,12 @@ void pxl8_set_draw_params(pxl8_gfx_cmdbuf* cb, const pxl8_gfx_cmd_draw_params* p void pxl8_set_pipeline(pxl8_gfx_cmdbuf* cb, pxl8_gfx_pipeline pipeline); void pxl8_set_scissor(pxl8_gfx_cmdbuf* cb, i32 x, i32 y, u32 w, u32 h); void pxl8_set_viewport(pxl8_gfx_cmdbuf* cb, i32 x, i32 y, u32 w, u32 h); - void pxl8_draw(pxl8_gfx_cmdbuf* cb, pxl8_gfx_buffer vb, pxl8_gfx_buffer ib, u32 first, u32 count, u32 base_vertex); void pxl8_gfx_submit(pxl8_renderer* r, pxl8_gfx_cmdbuf* cb); void pxl8_clear(pxl8_renderer* r, pxl8_gfx_texture target, u8 color); void pxl8_clear_depth(pxl8_renderer* r, pxl8_gfx_texture target); -void pxl8_clear_light(pxl8_renderer* r, pxl8_gfx_texture target); void pxl8_draw_pixel(pxl8_renderer* r, pxl8_gfx_texture target, i32 x, i32 y, u8 color); u8 pxl8_get_pixel(pxl8_renderer* r, pxl8_gfx_texture target, i32 x, i32 y); @@ -90,8 +68,7 @@ void pxl8_draw_rect_fill(pxl8_renderer* r, pxl8_gfx_texture target, i32 x, i32 y void pxl8_draw_circle(pxl8_renderer* r, pxl8_gfx_texture target, i32 cx, i32 cy, i32 radius, u8 color); void pxl8_draw_circle_fill(pxl8_renderer* r, pxl8_gfx_texture target, i32 cx, i32 cy, i32 radius, u8 color); -void pxl8_resolve_to_rgba(pxl8_renderer* r, pxl8_gfx_texture color, pxl8_gfx_texture light_accum, - const u32* palette, u32* output); +void pxl8_resolve_to_rgba(pxl8_renderer* r, pxl8_gfx_texture color, const u32* palette, u32* output); #ifdef __cplusplus } diff --git a/src/gfx/pxl8_render_types.h b/src/gfx/pxl8_render_types.h index d100c26..c3d3836 100644 --- a/src/gfx/pxl8_render_types.h +++ b/src/gfx/pxl8_render_types.h @@ -48,7 +48,6 @@ typedef enum pxl8_gfx_usage { typedef enum pxl8_gfx_texture_format { PXL8_GFX_FORMAT_INDEXED8, PXL8_GFX_FORMAT_DEPTH16, - PXL8_GFX_FORMAT_LIGHT_ACCUM, } pxl8_gfx_texture_format; typedef enum pxl8_gfx_cull_mode { diff --git a/src/gfx/pxl8_shader_builtins.h b/src/gfx/pxl8_shader_builtins.h index 4efb9bd..a4eaf5f 100644 --- a/src/gfx/pxl8_shader_builtins.h +++ b/src/gfx/pxl8_shader_builtins.h @@ -43,11 +43,22 @@ static inline u8 pxl8_sample_indexed(const pxl8_shader_bindings* b, pxl8_vec2 uv } } -static inline u8 pxl8_colormap_lookup(const pxl8_shader_bindings* b, u8 color, u8 light) { +static inline u8 pxl8_colormap_lookup(const pxl8_shader_bindings* b, u8 color, u8 light_color, u8 intensity) { if (!b) return color; const u8* cm = b->colormap; if (!cm) return color; - u32 row = light >> 5; + u32 row = ((u32)light_color << 3) + (intensity >> 5); + return cm[(row << 8) | (u32)color]; +} + +static inline u8 pxl8_colormap_lookup_dithered(const pxl8_shader_bindings* b, u8 color, u8 light_color, u8 intensity, u32 x, u32 y) { + if (!b) return color; + const u8* cm = b->colormap; + if (!cm) return color; + u32 base_row = intensity >> 5; + u32 frac = intensity & 31; + u32 threshold = PXL8_BAYER_4X4[(y & 3) * 4 + (x & 3)] * 2; + u32 row = ((u32)light_color << 3) + (frac > threshold && base_row < 7 ? base_row + 1 : base_row); return cm[(row << 8) | (u32)color]; } diff --git a/src/gfx/pxl8_shader_registry.c b/src/gfx/pxl8_shader_registry.c index 370f183..0461b4e 100644 --- a/src/gfx/pxl8_shader_registry.c +++ b/src/gfx/pxl8_shader_registry.c @@ -2,14 +2,14 @@ #include -extern u8 pxl8_shader_lit(pxl8_shader_ctx* ctx, const pxl8_shader_bindings* bindings, const pxl8_shader_uniforms* uniforms); -extern u8 pxl8_shader_unlit(pxl8_shader_ctx* ctx, const pxl8_shader_bindings* bindings, const pxl8_shader_uniforms* uniforms); +extern void pxl8_shader_lit(const pxl8_shader_ctx* ctx, const pxl8_shader_bindings* bindings, const pxl8_shader_uniforms* uniforms, u8* colors_out); +extern void pxl8_shader_unlit(const pxl8_shader_ctx* ctx, const pxl8_shader_bindings* bindings, const pxl8_shader_uniforms* uniforms, u8* colors_out); void pxl8_shader_registry_init(void) {} void pxl8_shader_registry_reload(void) {} pxl8_shader_fn pxl8_shader_registry_get(const char* name) { - if (strcmp(name, "lit") == 0) return (pxl8_shader_fn)pxl8_shader_lit; - if (strcmp(name, "unlit") == 0) return (pxl8_shader_fn)pxl8_shader_unlit; + if (strcmp(name, "lit") == 0) return pxl8_shader_lit; + if (strcmp(name, "unlit") == 0) return pxl8_shader_unlit; return NULL; } diff --git a/src/gfx/shaders/cpu/lit.c b/src/gfx/shaders/cpu/lit.c index 58aaf5a..b776fef 100644 --- a/src/gfx/shaders/cpu/lit.c +++ b/src/gfx/shaders/cpu/lit.c @@ -32,6 +32,8 @@ void pxl8_shader_lit( } pxl8_f32_simd light = ctx->v_light; + f32 max_strength[4] = {0, 0, 0, 0}; + u8 dominant_color[4] = {0, 0, 0, 0}; if (uniforms) { pxl8_f32_simd ambient = pxl8_f32_simd_set((f32)uniforms->ambient / 255.0f); @@ -72,11 +74,32 @@ void pxl8_shader_lit( ); falloff = pxl8_f32_simd_max(falloff, pxl8_f32_simd_zero()); + if (uniforms->dither) { + f32 falloff_arr[4]; + pxl8_f32_simd_store(falloff_arr, falloff); + for (u32 j = 0; j < 4; j++) { + if (falloff_arr[j] < 0.5f) { + f32 threshold = (PXL8_BAYER_4X4[((u32)py[j] & 3) * 4 + ((u32)px[j] & 3)] + 0.5f) * (1.0f / 16.0f); + if (falloff_arr[j] < threshold * 0.5f) falloff_arr[j] = 0.0f; + } + } + falloff = pxl8_f32_simd_load(falloff_arr); + } + pxl8_f32_simd strength = pxl8_f32_simd_mul( pxl8_f32_simd_mul(pxl8_f32_simd_set(l->intensity), falloff), ndotl ); + f32 strength_arr[4]; + pxl8_f32_simd_store(strength_arr, strength); + for (u32 j = 0; j < 4; j++) { + if (strength_arr[j] > max_strength[j]) { + max_strength[j] = strength_arr[j]; + dominant_color[j] = l->color; + } + } + light = pxl8_f32_simd_add(light, strength); } } @@ -88,13 +111,12 @@ void pxl8_shader_lit( pxl8_f32_simd_store(light_arr, light_f); for (u32 i = 0; i < ctx->color_count; i++) { - u8 light_u8; + u8 light_u8 = (u8)light_arr[i]; if (uniforms && uniforms->dither) { - light_u8 = pxl8_gfx_dither(light_arr[i], (u32)px[i], (u32)py[i]); + colors_out[i] = pxl8_colormap_lookup_dithered(bindings, tex_idx[i], dominant_color[i], light_u8, (u32)px[i], (u32)py[i]); } else { - light_u8 = (u8)light_arr[i]; + colors_out[i] = pxl8_colormap_lookup(bindings, tex_idx[i], dominant_color[i], light_u8); } - colors_out[i] = pxl8_colormap_lookup(bindings, tex_idx[i], light_u8); } #else @@ -111,6 +133,8 @@ void pxl8_shader_lit( } f32 light = ctx->v_light; + f32 max_strength = 0; + u8 dominant_color = 0; if (uniforms) { f32 ambient = (f32)uniforms->ambient / 255.0f; @@ -143,8 +167,16 @@ void pxl8_shader_lit( f32 falloff = 1.0f - dist_sq * l->inv_radius_sq; if (falloff <= 0.0f) continue; + if (uniforms->dither && falloff < 0.5f) { + f32 threshold = (PXL8_BAYER_4X4[((u32)ctx->y & 3) * 4 + ((u32)ctx->x & 3)] + 0.5f) * (1.0f / 16.0f); + if (falloff < threshold * 0.5f) continue; + } f32 strength = l->intensity * falloff * ndotl; + if (strength > max_strength) { + max_strength = strength; + dominant_color = l->color; + } light += strength; } } @@ -155,9 +187,9 @@ void pxl8_shader_lit( f32 light_f = light * 255.0f; u8 light_u8 = (u8)light_f; if (uniforms && uniforms->dither) { - light_u8 = pxl8_gfx_dither(light_f, (u32)ctx->x, (u32)ctx->y); + colors_out[0] = pxl8_colormap_lookup_dithered(bindings, tex_idx, dominant_color, light_u8, (u32)ctx->x, (u32)ctx->y); + } else { + colors_out[0] = pxl8_colormap_lookup(bindings, tex_idx, dominant_color, light_u8); } - - colors_out[0] = pxl8_colormap_lookup(bindings, tex_idx, light_u8); #endif } diff --git a/src/lua/pxl8/effects.lua b/src/lua/pxl8/effects.lua index f38381d..567d64c 100644 --- a/src/lua/pxl8/effects.lua +++ b/src/lua/pxl8/effects.lua @@ -14,16 +14,8 @@ function Lights.new(capacity) return setmetatable({ _ptr = ptr }, Lights) end -function Lights:add(x, y, z, r, g, b, intensity, radius) - if r and r > 255 then - local rgb = r - intensity = g - radius = b - r = bit.band(bit.rshift(rgb, 16), 0xFF) - g = bit.band(bit.rshift(rgb, 8), 0xFF) - b = bit.band(rgb, 0xFF) - end - C.pxl8_lights_add(self._ptr, x, y, z, r or 255, g or 255, b or 255, intensity or 255, radius or 10) +function Lights:add(x, y, z, color, intensity, radius) + C.pxl8_lights_add(self._ptr, x, y, z, color or 0, intensity or 255, radius or 10) end function Lights:clear() diff --git a/src/math/pxl8_math_scalar.h b/src/math/pxl8_math_scalar.h deleted file mode 100644 index 27f9da1..0000000 --- a/src/math/pxl8_math_scalar.h +++ /dev/null @@ -1,265 +0,0 @@ -#pragma once - -static inline f32 pxl8_fast_inv_sqrt(f32 x) { - f32 half = 0.5f * x; - i32 i = *(i32*)&x; - i = 0x5f3759df - (i >> 1); - x = *(f32*)&i; - x = x * (1.5f - half * x * x); - return x; -} - -static inline u32 pxl8_hash32(u32 x) { - x ^= x >> 16; - x *= 0x85EBCA6Bu; - x ^= x >> 13; - x *= 0xC2B2AE35u; - x ^= x >> 16; - return x; -} - -static inline u64 pxl8_hash64(u64 x) { - x ^= x >> 33; - x *= 0xff51afd7ed558ccdULL; - x ^= x >> 33; - x *= 0xc4ceb9fe1a85ec53ULL; - x ^= x >> 33; - return x; -} - -static inline f32 pxl8_smoothstep(f32 t) { - return t * t * (3.0f - 2.0f * t); -} - -static inline pxl8_vec2 pxl8_vec2_add(pxl8_vec2 a, pxl8_vec2 b) { - return (pxl8_vec2){ .x = a.x + b.x, .y = a.y + b.y }; -} - -static inline pxl8_vec2 pxl8_vec2_sub(pxl8_vec2 a, pxl8_vec2 b) { - return (pxl8_vec2){ .x = a.x - b.x, .y = a.y - b.y }; -} - -static inline pxl8_vec2 pxl8_vec2_scale(pxl8_vec2 v, f32 s) { - return (pxl8_vec2){ .x = v.x * s, .y = v.y * s }; -} - -static inline f32 pxl8_vec2_cross(pxl8_vec2 a, pxl8_vec2 b) { - return a.x * b.y - a.y * b.x; -} - -static inline f32 pxl8_vec2_dot(pxl8_vec2 a, pxl8_vec2 b) { - return a.x * b.x + a.y * b.y; -} - -static inline f32 pxl8_vec2_length(pxl8_vec2 v) { - return sqrtf(v.x * v.x + v.y * v.y); -} - -static inline pxl8_vec2 pxl8_vec2_normalize(pxl8_vec2 v) { - f32 len_sq = pxl8_vec2_dot(v, v); - if (len_sq < 1e-12f) return (pxl8_vec2){0}; - return pxl8_vec2_scale(v, pxl8_fast_inv_sqrt(len_sq)); -} - -static inline pxl8_vec3 pxl8_vec3_add(pxl8_vec3 a, pxl8_vec3 b) { - return (pxl8_vec3){ .x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z }; -} - -static inline pxl8_vec3 pxl8_vec3_sub(pxl8_vec3 a, pxl8_vec3 b) { - return (pxl8_vec3){ .x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z }; -} - -static inline pxl8_vec3 pxl8_vec3_scale(pxl8_vec3 v, f32 s) { - return (pxl8_vec3){ .x = v.x * s, .y = v.y * s, .z = v.z * s }; -} - -static inline f32 pxl8_vec3_dot(pxl8_vec3 a, pxl8_vec3 b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -} - -static inline pxl8_vec3 pxl8_vec3_cross(pxl8_vec3 a, pxl8_vec3 b) { - return (pxl8_vec3){ - .x = a.y * b.z - a.z * b.y, - .y = a.z * b.x - a.x * b.z, - .z = a.x * b.y - a.y * b.x, - }; -} - -static inline f32 pxl8_vec3_length(pxl8_vec3 v) { - return sqrtf(pxl8_vec3_dot(v, v)); -} - -static inline pxl8_vec3 pxl8_vec3_lerp(pxl8_vec3 a, pxl8_vec3 b, f32 t) { - return (pxl8_vec3){ - a.x + (b.x - a.x) * t, - a.y + (b.y - a.y) * t, - a.z + (b.z - a.z) * t - }; -} - -static inline pxl8_vec3 pxl8_vec3_normalize(pxl8_vec3 v) { - f32 len_sq = pxl8_vec3_dot(v, v); - if (len_sq < 1e-12f) return (pxl8_vec3){0}; - return pxl8_vec3_scale(v, pxl8_fast_inv_sqrt(len_sq)); -} - -static inline pxl8_mat4 pxl8_mat4_identity(void) { - pxl8_mat4 mat = {0}; - mat.m[0] = mat.m[5] = mat.m[10] = mat.m[15] = 1.0f; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_multiply(pxl8_mat4 a, pxl8_mat4 b) { - pxl8_mat4 mat = {0}; - for (i32 col = 0; col < 4; col++) { - for (i32 row = 0; row < 4; row++) { - mat.m[col * 4 + row] = - a.m[0 * 4 + row] * b.m[col * 4 + 0] + - a.m[1 * 4 + row] * b.m[col * 4 + 1] + - a.m[2 * 4 + row] * b.m[col * 4 + 2] + - a.m[3 * 4 + row] * b.m[col * 4 + 3]; - } - } - return mat; -} - -static inline pxl8_vec4 pxl8_mat4_multiply_vec4(pxl8_mat4 m, pxl8_vec4 v) { - return (pxl8_vec4){ - .x = m.m[0] * v.x + m.m[4] * v.y + m.m[8] * v.z + m.m[12] * v.w, - .y = m.m[1] * v.x + m.m[5] * v.y + m.m[9] * v.z + m.m[13] * v.w, - .z = m.m[2] * v.x + m.m[6] * v.y + m.m[10] * v.z + m.m[14] * v.w, - .w = m.m[3] * v.x + m.m[7] * v.y + m.m[11] * v.z + m.m[15] * v.w, - }; -} - -static inline pxl8_vec3 pxl8_mat4_multiply_vec3(pxl8_mat4 m, pxl8_vec3 v) { - return (pxl8_vec3){ - .x = m.m[0] * v.x + m.m[4] * v.y + m.m[8] * v.z, - .y = m.m[1] * v.x + m.m[5] * v.y + m.m[9] * v.z, - .z = m.m[2] * v.x + m.m[6] * v.y + m.m[10] * v.z, - }; -} - -static inline pxl8_mat4 pxl8_mat4_translate(f32 x, f32 y, f32 z) { - pxl8_mat4 mat = pxl8_mat4_identity(); - mat.m[12] = x; mat.m[13] = y; mat.m[14] = z; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_rotate_x(f32 angle) { - pxl8_mat4 mat = pxl8_mat4_identity(); - f32 c = cosf(angle), s = sinf(angle); - mat.m[5] = c; mat.m[9] = -s; mat.m[6] = s; mat.m[10] = c; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_rotate_y(f32 angle) { - pxl8_mat4 mat = pxl8_mat4_identity(); - f32 c = cosf(angle), s = sinf(angle); - mat.m[0] = c; mat.m[8] = s; mat.m[2] = -s; mat.m[10] = c; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_rotate_z(f32 angle) { - pxl8_mat4 mat = pxl8_mat4_identity(); - f32 c = cosf(angle), s = sinf(angle); - mat.m[0] = c; mat.m[4] = -s; mat.m[1] = s; mat.m[5] = c; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_scale(f32 x, f32 y, f32 z) { - pxl8_mat4 mat = pxl8_mat4_identity(); - mat.m[0] = x; mat.m[5] = y; mat.m[10] = z; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far) { - pxl8_mat4 mat = {0}; - mat.m[0] = 2.0f / (right - left); - mat.m[5] = 2.0f / (top - bottom); - mat.m[10] = -2.0f / (far - near); - mat.m[12] = -(right + left) / (right - left); - mat.m[13] = -(top + bottom) / (top - bottom); - mat.m[14] = -(far + near) / (far - near); - mat.m[15] = 1.0f; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_perspective(f32 fov, f32 aspect, f32 near, f32 far) { - pxl8_mat4 mat = {0}; - f32 tan_half_fov = tanf(fov / 2.0f); - mat.m[0] = 1.0f / (aspect * tan_half_fov); - mat.m[5] = 1.0f / tan_half_fov; - mat.m[10] = -(far + near) / (far - near); - mat.m[14] = -(2.0f * far * near) / (far - near); - mat.m[11] = -1.0f; - return mat; -} - -static inline pxl8_mat4 pxl8_mat4_lookat(pxl8_vec3 eye, pxl8_vec3 center, pxl8_vec3 up) { - pxl8_mat4 mat = pxl8_mat4_identity(); - pxl8_vec3 f = pxl8_vec3_normalize(pxl8_vec3_sub(center, eye)); - pxl8_vec3 s = pxl8_vec3_normalize(pxl8_vec3_cross(f, up)); - pxl8_vec3 u = pxl8_vec3_cross(s, f); - mat.m[0] = s.x; mat.m[4] = s.y; mat.m[8] = s.z; - mat.m[1] = u.x; mat.m[5] = u.y; mat.m[9] = u.z; - mat.m[2] = -f.x; mat.m[6] = -f.y; mat.m[10] = -f.z; - mat.m[12] = -pxl8_vec3_dot(s, eye); - mat.m[13] = -pxl8_vec3_dot(u, eye); - mat.m[14] = pxl8_vec3_dot(f, eye); - return mat; -} - -static inline pxl8_frustum pxl8_frustum_from_matrix(pxl8_mat4 vp) { - pxl8_frustum frustum; - const f32* m = vp.m; - frustum.planes[0].normal.x = m[3] + m[0]; - frustum.planes[0].normal.y = m[7] + m[4]; - frustum.planes[0].normal.z = m[11] + m[8]; - frustum.planes[0].distance = m[15] + m[12]; - frustum.planes[1].normal.x = m[3] - m[0]; - frustum.planes[1].normal.y = m[7] - m[4]; - frustum.planes[1].normal.z = m[11] - m[8]; - frustum.planes[1].distance = m[15] - m[12]; - frustum.planes[2].normal.x = m[3] + m[1]; - frustum.planes[2].normal.y = m[7] + m[5]; - frustum.planes[2].normal.z = m[11] + m[9]; - frustum.planes[2].distance = m[15] + m[13]; - frustum.planes[3].normal.x = m[3] - m[1]; - frustum.planes[3].normal.y = m[7] - m[5]; - frustum.planes[3].normal.z = m[11] - m[9]; - frustum.planes[3].distance = m[15] - m[13]; - frustum.planes[4].normal.x = m[3] + m[2]; - frustum.planes[4].normal.y = m[7] + m[6]; - frustum.planes[4].normal.z = m[11] + m[10]; - frustum.planes[4].distance = m[15] + m[14]; - frustum.planes[5].normal.x = m[3] - m[2]; - frustum.planes[5].normal.y = m[7] - m[6]; - frustum.planes[5].normal.z = m[11] - m[10]; - frustum.planes[5].distance = m[15] - m[14]; - for (i32 i = 0; i < 6; i++) { - f32 len = pxl8_vec3_length(frustum.planes[i].normal); - if (len > 1e-6f) { - f32 inv_len = 1.0f / len; - frustum.planes[i].normal = pxl8_vec3_scale(frustum.planes[i].normal, inv_len); - frustum.planes[i].distance *= inv_len; - } - } - return frustum; -} - -static inline bool pxl8_frustum_test_aabb(const pxl8_frustum* frustum, pxl8_vec3 min, pxl8_vec3 max) { - const f32 FRUSTUM_EPSILON = -75.0f; - for (i32 i = 0; i < 6; i++) { - pxl8_vec3 normal = frustum->planes[i].normal; - f32 d = frustum->planes[i].distance; - pxl8_vec3 p_vertex = { - (normal.x > 0.0f) ? max.x : min.x, - (normal.y > 0.0f) ? max.y : min.y, - (normal.z > 0.0f) ? max.z : min.z - }; - f32 p_dist = pxl8_vec3_dot(normal, p_vertex) + d; - if (p_dist < FRUSTUM_EPSILON) return false; - } - return true; -} diff --git a/src/script/pxl8_script_ffi.h b/src/script/pxl8_script_ffi.h index 036da56..a7577a3 100644 --- a/src/script/pxl8_script_ffi.h +++ b/src/script/pxl8_script_ffi.h @@ -205,18 +205,17 @@ static const char* pxl8_ffi_cdefs = "typedef struct { float m[16]; } pxl8_mat4;\n" "\n" "typedef struct pxl8_light {\n" -" pxl8_vec3 position;\n" +" u8 color;\n" +" f32 intensity;\n" " f32 inv_radius_sq;\n" -" u8 r, g, b;\n" -" u8 intensity;\n" -" f32 radius;\n" +" pxl8_vec3 position;\n" " f32 radius_sq;\n" "} pxl8_light;\n" "\n" "typedef struct pxl8_lights pxl8_lights;\n" "pxl8_lights* pxl8_lights_create(u32 capacity);\n" "void pxl8_lights_destroy(pxl8_lights* lights);\n" -"void pxl8_lights_add(pxl8_lights* lights, f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, u8 intensity, f32 radius);\n" +"void pxl8_lights_add(pxl8_lights* lights, f32 x, f32 y, f32 z, u8 color, u8 intensity, f32 radius);\n" "void pxl8_lights_clear(pxl8_lights* lights);\n" "u32 pxl8_lights_count(const pxl8_lights* lights);\n" "const pxl8_light* pxl8_lights_data(const pxl8_lights* lights);\n"