#include "pxl8_lightmap.h" #include #include pxl8_lightmap* pxl8_lightmap_create(u32 width, u32 height, u32 scale) { pxl8_lightmap* lm = calloc(1, sizeof(pxl8_lightmap)); if (!lm) return NULL; lm->width = width; lm->height = height; lm->scale = scale; lm->data = calloc(width * height * 3, sizeof(u8)); if (!lm->data) { free(lm); return NULL; } pxl8_lightmap_clear(lm, PXL8_LIGHTMAP_NEUTRAL, PXL8_LIGHTMAP_NEUTRAL, PXL8_LIGHTMAP_NEUTRAL); return lm; } void pxl8_lightmap_destroy(pxl8_lightmap* lm) { if (!lm) return; free(lm->data); free(lm); } void pxl8_lightmap_clear(pxl8_lightmap* lm, u8 r, u8 g, u8 b) { if (!lm || !lm->data) return; u32 count = lm->width * lm->height; for (u32 i = 0; i < count; i++) { lm->data[i * 3 + 0] = r; lm->data[i * 3 + 1] = g; lm->data[i * 3 + 2] = b; } } void pxl8_lightmap_set(pxl8_lightmap* lm, u32 x, u32 y, u8 r, u8 g, u8 b) { if (!lm || !lm->data || x >= lm->width || y >= lm->height) return; u32 idx = (y * lm->width + x) * 3; lm->data[idx + 0] = r; lm->data[idx + 1] = g; lm->data[idx + 2] = b; } void pxl8_lightmap_get(const pxl8_lightmap* lm, u32 x, u32 y, u8* r, u8* g, u8* b) { if (!lm || !lm->data || x >= lm->width || y >= lm->height) { *r = *g = *b = PXL8_LIGHTMAP_NEUTRAL; return; } u32 idx = (y * lm->width + x) * 3; *r = lm->data[idx + 0]; *g = lm->data[idx + 1]; *b = lm->data[idx + 2]; } void pxl8_lightmap_add_point( pxl8_lightmap* lm, f32 lx, f32 ly, u8 r, u8 g, u8 b, f32 radius, f32 intensity ) { if (!lm || !lm->data || radius <= 0.0f) return; f32 radius_sq = radius * radius; f32 inv_radius_sq = 1.0f / radius_sq; i32 cx = (i32)(lx * (f32)lm->width); i32 cy = (i32)(ly * (f32)lm->height); i32 rad_pixels = (i32)(radius * (f32)lm->width) + 1; i32 x0 = cx - rad_pixels; i32 y0 = cy - rad_pixels; i32 x1 = cx + rad_pixels; i32 y1 = cy + rad_pixels; if (x0 < 0) x0 = 0; if (y0 < 0) y0 = 0; if (x1 >= (i32)lm->width) x1 = (i32)lm->width - 1; if (y1 >= (i32)lm->height) y1 = (i32)lm->height - 1; f32 scale_x = 1.0f / (f32)lm->width; f32 scale_y = 1.0f / (f32)lm->height; for (i32 y = y0; y <= y1; y++) { f32 dy = ((f32)y * scale_y) - ly; for (i32 x = x0; x <= x1; x++) { f32 dx = ((f32)x * scale_x) - lx; f32 dist_sq = dx * dx + dy * dy; if (dist_sq >= radius_sq) continue; f32 falloff = 1.0f - dist_sq * inv_radius_sq; f32 contrib = falloff * falloff * intensity; u32 idx = ((u32)y * lm->width + (u32)x) * 3; i32 nr = (i32)lm->data[idx + 0] + (i32)((f32)(r - 128) * contrib); i32 ng = (i32)lm->data[idx + 1] + (i32)((f32)(g - 128) * contrib); i32 nb = (i32)lm->data[idx + 2] + (i32)((f32)(b - 128) * contrib); if (nr < 0) nr = 0; if (nr > 255) nr = 255; if (ng < 0) ng = 0; if (ng > 255) ng = 255; if (nb < 0) nb = 0; if (nb > 255) nb = 255; lm->data[idx + 0] = (u8)nr; lm->data[idx + 1] = (u8)ng; lm->data[idx + 2] = (u8)nb; } } }