improve lighting system

This commit is contained in:
asrael 2026-01-23 12:09:35 -06:00
parent 27c6fa628d
commit f18652dc97
15 changed files with 193 additions and 119 deletions

View file

@ -71,8 +71,8 @@ static pxl8_light_result calc_vertex_light(
if (sky_factor < 0.0f) sky_factor = 0.0f;
intensity += sky_factor * frame->uniforms.celestial_intensity * 0.3f;
for (u32 i = 0; i < frame->uniforms.num_lights; i++) {
const pxl8_light* light = &frame->uniforms.lights[i];
for (u32 i = 0; i < frame->lights_count; i++) {
const pxl8_light* light = &frame->lights[i];
f32 contrib = calc_light_intensity(light, world_pos, normal);
if (contrib > 0.0f) {
intensity += contrib;
@ -1329,7 +1329,7 @@ u32* pxl8_cpu_get_output(pxl8_cpu_backend* cpu) {
void pxl8_cpu_render_glows(
pxl8_cpu_backend* cpu,
const pxl8_glow_source* glows,
const pxl8_glow* glows,
u32 glow_count
) {
if (!cpu || cpu->target_stack_depth == 0) return;
@ -1344,7 +1344,7 @@ void pxl8_cpu_render_glows(
u32* light_accum = target->light_accum;
for (u32 gi = 0; gi < glow_count; gi++) {
const pxl8_glow_source* glow = &glows[gi];
const pxl8_glow* glow = &glows[gi];
i32 cx = glow->x;
i32 cy = glow->y;
i32 radius = glow->radius;

View file

@ -64,7 +64,7 @@ u32 pxl8_cpu_get_width(const pxl8_cpu_backend* cpu);
void pxl8_cpu_render_glows(
pxl8_cpu_backend* cpu,
const pxl8_glow_source* glows,
const pxl8_glow* glows,
u32 glow_count
);

View file

@ -607,10 +607,12 @@ pxl8_3d_frame pxl8_3d_frame_from_camera(const pxl8_3d_camera* camera, const pxl8
return frame;
}
void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8_3d_uniforms* uniforms) {
void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8_lights* lights, const pxl8_3d_uniforms* uniforms) {
if (!gfx || !camera) return;
pxl8_3d_frame frame = pxl8_3d_frame_from_camera(camera, uniforms);
frame.lights = lights ? pxl8_lights_data(lights) : NULL;
frame.lights_count = lights ? pxl8_lights_count(lights) : 0;
pxl8_mat4 vp = pxl8_mat4_multiply(frame.projection, frame.view);
@ -802,7 +804,7 @@ void pxl8_gfx_apply_effect(pxl8_gfx* gfx, pxl8_gfx_effect effect, const void* pa
switch (effect) {
case PXL8_GFX_EFFECT_GLOWS: {
const pxl8_glow_source* glows = (const pxl8_glow_source*)params;
const pxl8_glow* glows = (const pxl8_glow*)params;
switch (gfx->backend.type) {
case PXL8_GFX_BACKEND_CPU:
pxl8_cpu_render_glows(gfx->backend.cpu, glows, count);

View file

@ -2,6 +2,7 @@
#include "pxl8_gfx2d.h"
#include "pxl8_gfx3d.h"
#include "pxl8_glows.h"
#include "pxl8_hal.h"
#include "pxl8_colormap.h"
#include "pxl8_palette.h"
@ -14,53 +15,6 @@ typedef enum pxl8_gfx_effect {
PXL8_GFX_EFFECT_GLOWS = 0,
} pxl8_gfx_effect;
#define PXL8_MAX_GLOWS 256
typedef enum pxl8_glow_shape {
PXL8_GLOW_CIRCLE = 0,
PXL8_GLOW_DIAMOND = 1,
PXL8_GLOW_SHAFT = 2,
} pxl8_glow_shape;
typedef struct pxl8_glow_source {
u8 color;
u16 depth;
u8 height;
u16 intensity;
u8 radius;
pxl8_glow_shape shape;
i16 x;
i16 y;
} pxl8_glow_source;
static inline pxl8_glow_source pxl8_glow_create(i32 x, i32 y, u8 radius, u16 intensity, u8 color) {
return (pxl8_glow_source){
.color = color,
.depth = 0xFFFF,
.height = 0,
.intensity = intensity,
.radius = radius,
.shape = PXL8_GLOW_CIRCLE,
.x = (i16)x,
.y = (i16)y,
};
}
static inline pxl8_glow_source pxl8_glow_with_depth(pxl8_glow_source g, u16 depth) {
g.depth = depth;
return g;
}
static inline pxl8_glow_source pxl8_glow_with_shape(pxl8_glow_source g, pxl8_glow_shape shape) {
g.shape = shape;
return g;
}
static inline pxl8_glow_source pxl8_glow_with_height(pxl8_glow_source g, u8 height) {
g.height = height;
return g;
}
#ifdef __cplusplus
extern "C" {
#endif

View file

@ -1,53 +1,31 @@
#pragma once
#include "pxl8_3d_camera.h"
#include "pxl8_lights.h"
#include "pxl8_math.h"
#include "pxl8_mesh.h"
#include "pxl8_types.h"
typedef struct pxl8_gfx pxl8_gfx;
#define PXL8_MAX_LIGHTS 16
typedef struct pxl8_light {
pxl8_vec3 position;
u8 r, g, b;
u8 intensity;
f32 radius;
f32 radius_sq;
f32 inv_radius_sq;
} pxl8_light;
static inline pxl8_light pxl8_light_create(pxl8_vec3 pos, u8 r, u8 g, u8 b, u8 intensity, f32 radius) {
f32 radius_sq = radius * radius;
return (pxl8_light){
.position = pos,
.r = r, .g = g, .b = b,
.intensity = intensity,
.radius = radius,
.radius_sq = radius_sq,
.inv_radius_sq = radius_sq > 0.0f ? 1.0f / radius_sq : 0.0f,
};
}
typedef struct pxl8_3d_uniforms {
u8 ambient;
pxl8_vec3 celestial_dir;
f32 celestial_intensity;
u8 fog_color;
f32 fog_density;
pxl8_light lights[PXL8_MAX_LIGHTS];
u32 num_lights;
f32 time;
} pxl8_3d_uniforms;
typedef struct pxl8_3d_frame {
pxl8_3d_uniforms uniforms;
pxl8_vec3 camera_dir;
pxl8_vec3 camera_pos;
f32 far_clip;
const pxl8_light* lights;
u32 lights_count;
f32 near_clip;
pxl8_mat4 projection;
pxl8_3d_uniforms uniforms;
pxl8_mat4 view;
} pxl8_3d_frame;
@ -55,7 +33,7 @@ typedef struct pxl8_3d_frame {
extern "C" {
#endif
void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8_3d_uniforms* uniforms);
void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8_lights* lights, const pxl8_3d_uniforms* uniforms);
void pxl8_3d_clear(pxl8_gfx* gfx, u8 color);
void pxl8_3d_clear_depth(pxl8_gfx* gfx);
void pxl8_3d_draw_line(pxl8_gfx* gfx, pxl8_vec3 v0, pxl8_vec3 v1, u8 color);

View file

@ -1,9 +1,11 @@
#include "pxl8_glows.h"
#include "pxl8_gfx.h"
#include <stdlib.h>
struct pxl8_glows {
pxl8_glow_source* data;
pxl8_glow* data;
u32 capacity;
u32 count;
};
@ -12,7 +14,7 @@ pxl8_glows* pxl8_glows_create(u32 capacity) {
pxl8_glows* glows = calloc(1, sizeof(pxl8_glows));
if (!glows) return NULL;
glows->data = calloc(capacity, sizeof(pxl8_glow_source));
glows->data = calloc(capacity, sizeof(pxl8_glow));
if (!glows->data) {
free(glows);
return NULL;
@ -33,7 +35,7 @@ void pxl8_glows_destroy(pxl8_glows* glows) {
void pxl8_glows_add(pxl8_glows* glows, i16 x, i16 y, u8 radius, u16 intensity, u8 color, u8 shape) {
if (!glows || glows->count >= glows->capacity) return;
pxl8_glow_source* g = &glows->data[glows->count++];
pxl8_glow* g = &glows->data[glows->count++];
g->x = x;
g->y = y;
g->radius = radius;

View file

@ -1,8 +1,27 @@
#pragma once
#include "pxl8_gfx.h"
#include "pxl8_types.h"
#define PXL8_GLOWS_MAX 16384
typedef enum pxl8_glow_shape {
PXL8_GLOW_CIRCLE = 0,
PXL8_GLOW_DIAMOND = 1,
PXL8_GLOW_SHAFT = 2,
} pxl8_glow_shape;
typedef struct pxl8_glow {
u8 color;
u16 depth;
u8 height;
u16 intensity;
u8 radius;
pxl8_glow_shape shape;
i16 x;
i16 y;
} pxl8_glow;
typedef struct pxl8_gfx pxl8_gfx;
typedef struct pxl8_glows pxl8_glows;
#ifdef __cplusplus
@ -15,6 +34,7 @@ void pxl8_glows_destroy(pxl8_glows* glows);
void pxl8_glows_add(pxl8_glows* glows, i16 x, i16 y, u8 radius, u16 intensity, u8 color, u8 shape);
void pxl8_glows_clear(pxl8_glows* glows);
u32 pxl8_glows_count(const pxl8_glows* glows);
const pxl8_glow* pxl8_glows_data(const pxl8_glows* glows);
void pxl8_glows_render(pxl8_glows* glows, pxl8_gfx* gfx);
#ifdef __cplusplus

63
src/gfx/pxl8_lights.c Normal file
View file

@ -0,0 +1,63 @@
#include "pxl8_lights.h"
#include <stdlib.h>
struct pxl8_lights {
pxl8_light* data;
u32 capacity;
u32 count;
};
pxl8_lights* pxl8_lights_create(u32 capacity) {
if (capacity > PXL8_LIGHTS_MAX) capacity = PXL8_LIGHTS_MAX;
pxl8_lights* lights = calloc(1, sizeof(pxl8_lights));
if (!lights) return NULL;
lights->data = calloc(capacity, sizeof(pxl8_light));
if (!lights->data) {
free(lights);
return NULL;
}
lights->capacity = capacity;
lights->count = 0;
return lights;
}
void pxl8_lights_destroy(pxl8_lights* lights) {
if (!lights) return;
free(lights->data);
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) {
if (!lights || lights->count >= lights->capacity) return;
f32 radius_sq = radius * radius;
pxl8_light* l = &lights->data[lights->count++];
l->position.x = x;
l->position.y = y;
l->position.z = z;
l->r = r;
l->g = g;
l->b = b;
l->intensity = intensity;
l->radius = radius;
l->radius_sq = radius_sq;
l->inv_radius_sq = radius_sq > 0.0f ? 1.0f / radius_sq : 0.0f;
}
void pxl8_lights_clear(pxl8_lights* lights) {
if (!lights) return;
lights->count = 0;
}
u32 pxl8_lights_count(const pxl8_lights* lights) {
return lights ? lights->count : 0;
}
const pxl8_light* pxl8_lights_data(const pxl8_lights* lights) {
return lights ? lights->data : NULL;
}

33
src/gfx/pxl8_lights.h Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include "pxl8_math.h"
#include "pxl8_types.h"
#define PXL8_LIGHTS_MAX 256
typedef struct pxl8_light {
pxl8_vec3 position;
f32 inv_radius_sq;
u8 r, g, b;
u8 intensity;
f32 radius;
f32 radius_sq;
} pxl8_light;
typedef struct pxl8_lights pxl8_lights;
#ifdef __cplusplus
extern "C" {
#endif
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_clear(pxl8_lights* lights);
u32 pxl8_lights_count(const pxl8_lights* lights);
const pxl8_light* pxl8_lights_data(const pxl8_lights* lights);
#ifdef __cplusplus
}
#endif