glow rendering fixes to bring stars back
This commit is contained in:
parent
657b590b6f
commit
c538641ec8
26 changed files with 773 additions and 1491 deletions
|
|
@ -474,6 +474,32 @@ pxl8_bsp_lightmap pxl8_bsp_lightmap_mapped(u8 width, u8 height, u32 offset) {
|
|||
};
|
||||
}
|
||||
|
||||
u8 pxl8_bsp_light_at(const pxl8_bsp* bsp, f32 x, f32 y, f32 z, u8 ambient) {
|
||||
if (!bsp || !bsp->vertices || !bsp->vertex_lights) return 255;
|
||||
|
||||
f32 best_dist = FLT_MAX;
|
||||
u32 best_idx = 0;
|
||||
|
||||
for (u32 i = 0; i < bsp->num_vertices; i++) {
|
||||
f32 dx = bsp->vertices[i].position.x - x;
|
||||
f32 dy = bsp->vertices[i].position.y - y;
|
||||
f32 dz = bsp->vertices[i].position.z - z;
|
||||
f32 dist = dx * dx + dy * dy + dz * dz;
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_idx >= bsp->num_vertex_lights) return 255;
|
||||
|
||||
u32 packed = bsp->vertex_lights[best_idx];
|
||||
u8 direct = (packed >> 24) & 0xFF;
|
||||
u8 ao = (packed >> 16) & 0xFF;
|
||||
f32 combined = (f32)direct + ((f32)ambient / 255.0f) * (f32)ao;
|
||||
return (u8)(combined > 255.0f ? 255.0f : combined);
|
||||
}
|
||||
|
||||
pxl8_bsp_lightmap_sample pxl8_bsp_sample_lightmap(const pxl8_bsp* bsp, u32 face_idx, f32 u, f32 v) {
|
||||
pxl8_bsp_lightmap_sample white = {255, 255, 255};
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ pxl8_bsp_lightmap pxl8_bsp_lightmap_uniform(u8 r, u8 g, u8 b);
|
|||
pxl8_result pxl8_bsp_load(const char* path, pxl8_bsp* bsp);
|
||||
void pxl8_bsp_pvs_destroy(pxl8_bsp_pvs* pvs);
|
||||
bool pxl8_bsp_pvs_is_visible(const pxl8_bsp_pvs* pvs, i32 leaf);
|
||||
u8 pxl8_bsp_light_at(const pxl8_bsp* bsp, f32 x, f32 y, f32 z, u8 ambient);
|
||||
pxl8_bsp_lightmap_sample pxl8_bsp_sample_lightmap(const pxl8_bsp* bsp, u32 face_idx, f32 u, f32 v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -112,12 +112,67 @@ static void generate_blend_table(pxl8_colormap* cm, const u32* palette) {
|
|||
}
|
||||
}
|
||||
|
||||
static void generate_additive_table(pxl8_colormap* cm, const u32* palette, pxl8_light_color light_color) {
|
||||
pxl8_rgb light = pxl8_light_colors[light_color];
|
||||
u32 base_row = PXL8_ADDITIVE_START + (u32)light_color * PXL8_LIGHT_LEVELS;
|
||||
|
||||
for (u32 level = 0; level < PXL8_LIGHT_LEVELS; level++) {
|
||||
f32 brightness = (f32)level / (f32)(PXL8_LIGHT_LEVELS - 1);
|
||||
u32 row = base_row + level;
|
||||
|
||||
f32 lr = (f32)light.r / 255.0f;
|
||||
f32 lg = (f32)light.g / 255.0f;
|
||||
f32 lb = (f32)light.b / 255.0f;
|
||||
i32 add_r = (i32)(brightness * lr * 255.0f);
|
||||
i32 add_g = (i32)(brightness * lg * 255.0f);
|
||||
i32 add_b = (i32)(brightness * lb * 255.0f);
|
||||
|
||||
for (u32 pal_idx = 0; pal_idx < 256; pal_idx++) {
|
||||
u8 result_idx;
|
||||
|
||||
if (pal_idx == PXL8_TRANSPARENT) {
|
||||
result_idx = PXL8_TRANSPARENT;
|
||||
} else if (pal_idx >= PXL8_FULLBRIGHT_START) {
|
||||
result_idx = (u8)pal_idx;
|
||||
} else {
|
||||
u32 c = palette[pal_idx];
|
||||
i32 r = (i32)(c & 0xFF);
|
||||
i32 g = (i32)((c >> 8) & 0xFF);
|
||||
i32 b = (i32)((c >> 16) & 0xFF);
|
||||
|
||||
i32 tr = r + add_r;
|
||||
i32 tg = g + add_g;
|
||||
i32 tb = b + add_b;
|
||||
|
||||
result_idx = find_closest_color(palette,
|
||||
(u8)(tr > 255 ? 255 : tr),
|
||||
(u8)(tg > 255 ? 255 : tg),
|
||||
(u8)(tb > 255 ? 255 : tb));
|
||||
}
|
||||
|
||||
cm->table[row * 256 + pal_idx] = result_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_luminance_table(pxl8_colormap* cm, const u32* palette) {
|
||||
for (u32 i = 0; i < 256; i++) {
|
||||
u32 c = palette[i];
|
||||
u32 r = c & 0xFF;
|
||||
u32 g = (c >> 8) & 0xFF;
|
||||
u32 b = (c >> 16) & 0xFF;
|
||||
cm->luminance[i] = (u8)((77 * r + 150 * g + 29 * b) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
void pxl8_colormap_generate(pxl8_colormap* cm, const u32* palette) {
|
||||
if (!cm || !palette) return;
|
||||
|
||||
for (u32 light = 0; light < PXL8_LIGHT_COLORS; light++) {
|
||||
generate_light_table(cm, palette, (pxl8_light_color)light);
|
||||
generate_additive_table(cm, palette, (pxl8_light_color)light);
|
||||
}
|
||||
|
||||
generate_blend_table(cm, palette);
|
||||
generate_luminance_table(cm, palette);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ extern "C" {
|
|||
#define PXL8_LIGHT_LEVELS 8
|
||||
#define PXL8_LIGHT_ROWS (PXL8_LIGHT_COLORS * PXL8_LIGHT_LEVELS)
|
||||
#define PXL8_BLEND_ROWS 256
|
||||
#define PXL8_COLORMAP_ROWS (PXL8_LIGHT_ROWS + PXL8_BLEND_ROWS)
|
||||
#define PXL8_ADDITIVE_ROWS (PXL8_LIGHT_COLORS * PXL8_LIGHT_LEVELS)
|
||||
#define PXL8_ADDITIVE_START (PXL8_LIGHT_ROWS + PXL8_BLEND_ROWS)
|
||||
#define PXL8_COLORMAP_ROWS (PXL8_LIGHT_ROWS + PXL8_BLEND_ROWS + PXL8_ADDITIVE_ROWS)
|
||||
#define PXL8_COLORMAP_SIZE (256 * PXL8_COLORMAP_ROWS)
|
||||
|
||||
#define PXL8_FULLBRIGHT_START 240
|
||||
|
|
@ -47,6 +49,7 @@ static const pxl8_rgb pxl8_light_colors[PXL8_LIGHT_COLORS] = {
|
|||
|
||||
typedef struct {
|
||||
u8 table[PXL8_COLORMAP_SIZE];
|
||||
u8 luminance[256];
|
||||
} pxl8_colormap;
|
||||
|
||||
void pxl8_colormap_generate(pxl8_colormap* cm, const u32* palette);
|
||||
|
|
@ -68,6 +71,17 @@ static inline u8 pxl8_colormap_blend(const pxl8_colormap* cm, u8 src, u8 dst) {
|
|||
return cm->table[(blend_row << 8) + dst];
|
||||
}
|
||||
|
||||
static inline u8 pxl8_colormap_additive(const pxl8_colormap* cm, u8 pal_idx, pxl8_light_color light_color, u8 intensity) {
|
||||
u32 row = PXL8_ADDITIVE_START + ((u32)light_color << 3) + (intensity >> 5);
|
||||
return cm->table[(row << 8) + pal_idx];
|
||||
}
|
||||
|
||||
static inline u8 pxl8_colormap_additive_dithered(const pxl8_colormap* cm, u8 pal_idx, pxl8_light_color light_color, u8 intensity, u32 x, u32 y) {
|
||||
u8 dithered = pxl8_gfx_dither((f32)intensity + 0.5f, x, y);
|
||||
u32 row = PXL8_ADDITIVE_START + ((u32)light_color << 3) + (dithered >> 5);
|
||||
return cm->table[(row << 8) + pal_idx];
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "pxl8_color.h"
|
||||
#include "pxl8_colormap.h"
|
||||
#include "pxl8_font.h"
|
||||
#include "pxl8_glows.h"
|
||||
#include "pxl8_hal.h"
|
||||
#include "pxl8_log.h"
|
||||
#include "pxl8_macros.h"
|
||||
|
|
@ -694,6 +695,7 @@ void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8
|
|||
|
||||
pxl8_3d_frame frame = pxl8_3d_frame_from_camera(camera, uniforms);
|
||||
frame.bsp = gfx->bsp;
|
||||
frame.uniforms.camera_pos = frame.camera_pos;
|
||||
frame.uniforms.lights = lights ? pxl8_lights_data(lights) : NULL;
|
||||
frame.uniforms.lights_count = lights ? pxl8_lights_count(lights) : 0;
|
||||
|
||||
|
|
@ -765,7 +767,7 @@ void pxl8_3d_clear(pxl8_gfx* gfx, u8 color) {
|
|||
|
||||
void pxl8_3d_clear_depth(pxl8_gfx* gfx) {
|
||||
if (!gfx) return;
|
||||
pxl8_clear_depth(gfx->renderer, gfx_current_depth(gfx));
|
||||
pxl8_cmdbuf_clear_depth(gfx->cmdbuf, gfx_current_depth(gfx));
|
||||
}
|
||||
|
||||
void pxl8_3d_draw_line(pxl8_gfx* gfx, pxl8_vec3 v0, pxl8_vec3 v1, u8 color) {
|
||||
|
|
@ -1043,6 +1045,107 @@ bool pxl8_gfx_get_wireframe(const pxl8_gfx* gfx) {
|
|||
return gfx ? gfx->wireframe : false;
|
||||
}
|
||||
|
||||
void pxl8_gfx_apply_effect(pxl8_gfx* gfx, pxl8_gfx_effect effect, const void* params, u32 count) {
|
||||
if (!gfx || !params || count == 0) return;
|
||||
|
||||
if (effect == PXL8_GFX_EFFECT_GLOWS) {
|
||||
u8* fb = (u8*)pxl8_texture_get_data(gfx->renderer, gfx_current_color(gfx));
|
||||
if (!fb || !gfx->colormap) return;
|
||||
|
||||
u16* zb = (u16*)pxl8_texture_get_data(gfx->renderer, gfx_current_depth(gfx));
|
||||
i32 w = gfx->framebuffer_width;
|
||||
i32 h = gfx->framebuffer_height;
|
||||
const pxl8_glow* glows = (const pxl8_glow*)params;
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
const pxl8_glow* g = &glows[i];
|
||||
i32 cx = g->x;
|
||||
i32 cy = g->y;
|
||||
i32 r = (i32)g->radius;
|
||||
if (r <= 0) continue;
|
||||
|
||||
bool depth_test = g->depth > 0 && zb;
|
||||
f32 base_intensity = (f32)g->intensity / 255.0f;
|
||||
f32 inv_r = 1.0f / (f32)r;
|
||||
|
||||
i32 x0 = cx - r;
|
||||
i32 y0 = cy - r;
|
||||
i32 x1 = cx + r;
|
||||
i32 y1 = cy + r;
|
||||
|
||||
if (g->shape == PXL8_GLOW_SHAFT) {
|
||||
i32 sh = (i32)g->height;
|
||||
if (sh <= 0) sh = 1;
|
||||
y0 = cy - sh;
|
||||
y1 = cy + sh;
|
||||
}
|
||||
|
||||
if (x0 < 0) x0 = 0;
|
||||
if (y0 < 0) y0 = 0;
|
||||
if (x1 >= w) x1 = w - 1;
|
||||
if (y1 >= h) y1 = h - 1;
|
||||
|
||||
for (i32 py = y0; py <= y1; py++) {
|
||||
i32 dy = py - cy;
|
||||
for (i32 px = x0; px <= x1; px++) {
|
||||
i32 idx = py * w + px;
|
||||
|
||||
if (depth_test && zb[idx] < g->depth) continue;
|
||||
|
||||
u8 src = fb[idx];
|
||||
if (src == PXL8_TRANSPARENT) continue;
|
||||
|
||||
i32 dx = px - cx;
|
||||
f32 falloff;
|
||||
|
||||
switch (g->shape) {
|
||||
case PXL8_GLOW_CIRCLE: {
|
||||
f32 dist_sq = (f32)(dx * dx + dy * dy);
|
||||
f32 norm = dist_sq * inv_r * inv_r;
|
||||
if (norm >= 1.0f) continue;
|
||||
falloff = 1.0f - norm;
|
||||
falloff *= falloff;
|
||||
break;
|
||||
}
|
||||
case PXL8_GLOW_DIAMOND: {
|
||||
f32 manhattan = (f32)(abs(dx) + abs(dy));
|
||||
f32 norm = manhattan * inv_r;
|
||||
if (norm >= 1.0f) continue;
|
||||
falloff = 1.0f - norm;
|
||||
falloff *= falloff;
|
||||
break;
|
||||
}
|
||||
case PXL8_GLOW_SHAFT: {
|
||||
f32 abs_dx = (f32)abs(dx);
|
||||
if (abs_dx >= (f32)r) continue;
|
||||
f32 x_falloff = 1.0f - abs_dx * inv_r;
|
||||
i32 sh = (i32)g->height;
|
||||
if (sh <= 0) sh = 1;
|
||||
f32 abs_dy = (f32)abs(dy);
|
||||
f32 y_falloff = 1.0f - abs_dy / (f32)sh;
|
||||
falloff = x_falloff * y_falloff;
|
||||
falloff *= falloff;
|
||||
break;
|
||||
}
|
||||
default: continue;
|
||||
}
|
||||
|
||||
f32 brightness = falloff * base_intensity;
|
||||
f32 raw = brightness * 255.0f;
|
||||
if (raw > 255.0f) raw = 255.0f;
|
||||
u8 light_u8 = (u8)raw;
|
||||
if (light_u8 < 4) continue;
|
||||
|
||||
fb[idx] = pxl8_colormap_additive_dithered(
|
||||
gfx->colormap, src, g->color,
|
||||
light_u8, (u32)px, (u32)py
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 pxl8_gfx_get_ambient(const pxl8_gfx* gfx) {
|
||||
return gfx ? gfx->frame.uniforms.ambient : 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ void pxl8_glows_destroy(pxl8_glows* glows) {
|
|||
pxl8_free(glows);
|
||||
}
|
||||
|
||||
void pxl8_glows_add(pxl8_glows* glows, i16 x, i16 y, u8 radius, u16 intensity, u8 color, u8 shape) {
|
||||
void pxl8_glows_add(pxl8_glows* glows, i16 x, i16 y, u8 radius, u16 intensity, u8 color, u8 shape, u16 depth) {
|
||||
if (!glows || glows->count >= glows->capacity) return;
|
||||
|
||||
pxl8_glow* g = &glows->data[glows->count++];
|
||||
|
|
@ -43,7 +43,7 @@ void pxl8_glows_add(pxl8_glows* glows, i16 x, i16 y, u8 radius, u16 intensity, u
|
|||
g->intensity = intensity;
|
||||
g->color = color;
|
||||
g->shape = shape;
|
||||
g->depth = 0xFFFF;
|
||||
g->depth = depth;
|
||||
g->height = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
pxl8_glows* pxl8_glows_create(u32 capacity);
|
||||
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_add(pxl8_glows* glows, i16 x, i16 y, u8 radius, u16 intensity, u8 color, u8 shape, u16 depth);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ static void pxl8_palette_sort_colors(pxl8_palette* pal) {
|
|||
|
||||
pal->color_ramp[0] = 0;
|
||||
|
||||
u8 count = pal->color_count;
|
||||
u16 count = pal->color_count;
|
||||
palette_sort_entry entries[PXL8_PALETTE_SIZE - 1];
|
||||
for (u32 i = 1; i < count; i++) {
|
||||
u8 r, g, b, a;
|
||||
|
|
|
|||
|
|
@ -87,18 +87,15 @@ static u8 blend_indexed(
|
|||
const pxl8_gfx_pipeline_desc* pipeline,
|
||||
u8 src,
|
||||
u8 dst,
|
||||
const u32* palette,
|
||||
const u8* colormap
|
||||
const u32* palette
|
||||
) {
|
||||
(void)colormap;
|
||||
if (!pipeline || !pipeline->blend.enabled) return src;
|
||||
if (src == 0) return dst;
|
||||
if (!palette) return src;
|
||||
|
||||
f32 src_a = src == 0 ? 0.0f : 1.0f;
|
||||
f32 dst_a = dst == 0 ? 0.0f : 1.0f;
|
||||
f32 sf = blend_factor_value(pipeline->blend.src, src_a, dst_a);
|
||||
f32 df = blend_factor_value(pipeline->blend.dst, src_a, dst_a);
|
||||
f32 sf = blend_factor_value(pipeline->blend.src, 1.0f, dst_a);
|
||||
f32 df = blend_factor_value(pipeline->blend.dst, 1.0f, dst_a);
|
||||
|
||||
if (sf == 1.0f && df == 0.0f) return src;
|
||||
if (sf == 0.0f && df == 1.0f) return dst;
|
||||
|
|
@ -111,18 +108,11 @@ static u8 blend_indexed(
|
|||
u8 dg = (palette[dst] >> 8) & 0xFF;
|
||||
u8 db = (palette[dst] >> 16) & 0xFF;
|
||||
|
||||
i32 out_r = (i32)(sr * sf + dr * df);
|
||||
i32 out_g = (i32)(sg * sf + dg * df);
|
||||
i32 out_b = (i32)(sb * sf + db * df);
|
||||
u8 out_r = (u8)pxl8_clamp_byte((i32)(sr * sf + dr * df));
|
||||
u8 out_g = (u8)pxl8_clamp_byte((i32)(sg * sf + dg * df));
|
||||
u8 out_b = (u8)pxl8_clamp_byte((i32)(sb * sf + db * df));
|
||||
|
||||
if (out_r < 0) out_r = 0;
|
||||
if (out_g < 0) out_g = 0;
|
||||
if (out_b < 0) out_b = 0;
|
||||
if (out_r > 255) out_r = 255;
|
||||
if (out_g > 255) out_g = 255;
|
||||
if (out_b > 255) out_b = 255;
|
||||
|
||||
return palette_find_closest(palette, (u8)out_r, (u8)out_g, (u8)out_b);
|
||||
return palette_find_closest(palette, out_r, out_g, out_b);
|
||||
}
|
||||
|
||||
static inline pxl8_vec4 vec4_lerp(pxl8_vec4 a, pxl8_vec4 b, f32 t) {
|
||||
|
|
@ -192,6 +182,15 @@ static i32 clip_triangle_near(
|
|||
return 6;
|
||||
}
|
||||
|
||||
static inline pxl8_vec3 clip_to_screen(pxl8_vec4 clip, f32 vp_x, f32 vp_y, f32 hw, f32 hh) {
|
||||
f32 inv_w = 1.0f / clip.w;
|
||||
return (pxl8_vec3){
|
||||
vp_x + hw + clip.x * inv_w * hw,
|
||||
vp_y + hh - clip.y * inv_w * hh,
|
||||
clip.z * inv_w,
|
||||
};
|
||||
}
|
||||
|
||||
static bool setup_tri(
|
||||
tri_setup* setup,
|
||||
const raster_vertex* vo0, const raster_vertex* vo1, const raster_vertex* vo2,
|
||||
|
|
@ -203,18 +202,12 @@ static bool setup_tri(
|
|||
|
||||
f32 hw = (f32)viewport_w * 0.5f;
|
||||
f32 hh = (f32)viewport_h * 0.5f;
|
||||
f32 vp_xf = (f32)viewport_x;
|
||||
f32 vp_yf = (f32)viewport_y;
|
||||
|
||||
setup->p0.x = (f32)viewport_x + hw + vo0->clip_pos.x / vo0->clip_pos.w * hw;
|
||||
setup->p0.y = (f32)viewport_y + hh - vo0->clip_pos.y / vo0->clip_pos.w * hh;
|
||||
setup->p0.z = vo0->clip_pos.z / vo0->clip_pos.w;
|
||||
|
||||
setup->p1.x = (f32)viewport_x + hw + vo1->clip_pos.x / vo1->clip_pos.w * hw;
|
||||
setup->p1.y = (f32)viewport_y + hh - vo1->clip_pos.y / vo1->clip_pos.w * hh;
|
||||
setup->p1.z = vo1->clip_pos.z / vo1->clip_pos.w;
|
||||
|
||||
setup->p2.x = (f32)viewport_x + hw + vo2->clip_pos.x / vo2->clip_pos.w * hw;
|
||||
setup->p2.y = (f32)viewport_y + hh - vo2->clip_pos.y / vo2->clip_pos.w * hh;
|
||||
setup->p2.z = vo2->clip_pos.z / vo2->clip_pos.w;
|
||||
setup->p0 = clip_to_screen(vo0->clip_pos, vp_xf, vp_yf, hw, hh);
|
||||
setup->p1 = clip_to_screen(vo1->clip_pos, vp_xf, vp_yf, hw, hh);
|
||||
setup->p2 = clip_to_screen(vo2->clip_pos, vp_xf, vp_yf, hw, hh);
|
||||
|
||||
f32 cross = (setup->p1.x - setup->p0.x) * (setup->p2.y - setup->p0.y) -
|
||||
(setup->p1.y - setup->p0.y) * (setup->p2.x - setup->p0.x);
|
||||
|
|
@ -303,7 +296,6 @@ static void rasterize_triangle(
|
|||
u8 alpha_ref = pipeline ? pipeline->blend.alpha_ref : 0;
|
||||
bool blend_enabled = pipeline && pipeline->blend.enabled;
|
||||
const u32* palette = bindings ? bindings->palette : NULL;
|
||||
const u8* colormap = bindings ? bindings->colormap : NULL;
|
||||
|
||||
for (i32 y = setup->y_start; y <= setup->y_end; y++) {
|
||||
f32 yf = (f32)y + 0.5f;
|
||||
|
|
@ -548,7 +540,7 @@ static void rasterize_triangle(
|
|||
if (color != 0) {
|
||||
u8 out_color = color;
|
||||
if (blend_enabled) {
|
||||
out_color = blend_indexed(pipeline, color, prow[px], palette, colormap);
|
||||
out_color = blend_indexed(pipeline, color, prow[px], palette);
|
||||
}
|
||||
|
||||
prow[px] = out_color;
|
||||
|
|
@ -594,7 +586,7 @@ static void rasterize_triangle(
|
|||
if (color != 0) {
|
||||
u8 out_color = color;
|
||||
if (blend_enabled) {
|
||||
out_color = blend_indexed(pipeline, color, prow[px], palette, colormap);
|
||||
out_color = blend_indexed(pipeline, color, prow[px], palette);
|
||||
}
|
||||
|
||||
prow[px] = out_color;
|
||||
|
|
@ -1142,6 +1134,12 @@ void pxl8_begin_pass(pxl8_gfx_cmdbuf* cb, pxl8_gfx_pass pass) {
|
|||
cmd->begin_pass.pass = pass;
|
||||
}
|
||||
|
||||
void pxl8_cmdbuf_clear_depth(pxl8_gfx_cmdbuf* cb, pxl8_gfx_texture texture) {
|
||||
pxl8_gfx_cmd* cmd = cmd_alloc(cb);
|
||||
cmd->type = PXL8_GFX_CMD_CLEAR_DEPTH;
|
||||
cmd->clear_depth.texture = texture;
|
||||
}
|
||||
|
||||
void pxl8_end_pass(pxl8_gfx_cmdbuf* cb) {
|
||||
pxl8_gfx_cmd* cmd = cmd_alloc(cb);
|
||||
cmd->type = PXL8_GFX_CMD_END_PASS;
|
||||
|
|
@ -1370,17 +1368,16 @@ static void execute_draw(
|
|||
if (is_wireframe) {
|
||||
f32 hw = (f32)vp_w * 0.5f;
|
||||
f32 hh = (f32)vp_h * 0.5f;
|
||||
f32 vp_xf = (f32)vp_x;
|
||||
f32 vp_yf = (f32)vp_y;
|
||||
|
||||
raster_vertex* wv0 = &clipped[t];
|
||||
raster_vertex* wv1 = &clipped[t+1];
|
||||
raster_vertex* wv2 = &clipped[t+2];
|
||||
pxl8_vec3 s0 = clip_to_screen(clipped[t].clip_pos, vp_xf, vp_yf, hw, hh);
|
||||
pxl8_vec3 s1 = clip_to_screen(clipped[t+1].clip_pos, vp_xf, vp_yf, hw, hh);
|
||||
pxl8_vec3 s2 = clip_to_screen(clipped[t+2].clip_pos, vp_xf, vp_yf, hw, hh);
|
||||
|
||||
i32 sx0 = (i32)((f32)vp_x + hw + wv0->clip_pos.x / wv0->clip_pos.w * hw);
|
||||
i32 sy0 = (i32)((f32)vp_y + hh - wv0->clip_pos.y / wv0->clip_pos.w * hh);
|
||||
i32 sx1 = (i32)((f32)vp_x + hw + wv1->clip_pos.x / wv1->clip_pos.w * hw);
|
||||
i32 sy1 = (i32)((f32)vp_y + hh - wv1->clip_pos.y / wv1->clip_pos.w * hh);
|
||||
i32 sx2 = (i32)((f32)vp_x + hw + wv2->clip_pos.x / wv2->clip_pos.w * hw);
|
||||
i32 sy2 = (i32)((f32)vp_y + hh - wv2->clip_pos.y / wv2->clip_pos.w * hh);
|
||||
i32 sx0 = (i32)s0.x, sy0 = (i32)s0.y;
|
||||
i32 sx1 = (i32)s1.x, sy1 = (i32)s1.y;
|
||||
i32 sx2 = (i32)s2.x, sy2 = (i32)s2.y;
|
||||
|
||||
f32 cross = (f32)(sx1 - sx0) * (f32)(sy2 - sy0) - (f32)(sy1 - sy0) * (f32)(sx2 - sx0);
|
||||
if (!double_sided) {
|
||||
|
|
@ -1427,6 +1424,9 @@ void pxl8_gfx_submit(pxl8_renderer* r, pxl8_gfx_cmdbuf* cb) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case PXL8_GFX_CMD_CLEAR_DEPTH:
|
||||
pxl8_clear_depth(r, cmd->clear_depth.texture);
|
||||
break;
|
||||
case PXL8_GFX_CMD_END_PASS:
|
||||
r->current_pass = (pxl8_gfx_pass){ PXL8_GFX_INVALID_ID };
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ void pxl8_cmdbuf_destroy(pxl8_gfx_cmdbuf* cb);
|
|||
void pxl8_cmdbuf_reset(pxl8_gfx_cmdbuf* cb);
|
||||
|
||||
void pxl8_begin_pass(pxl8_gfx_cmdbuf* cb, pxl8_gfx_pass pass);
|
||||
void pxl8_cmdbuf_clear_depth(pxl8_gfx_cmdbuf* cb, pxl8_gfx_texture texture);
|
||||
void pxl8_end_pass(pxl8_gfx_cmdbuf* cb);
|
||||
void pxl8_set_bindings(pxl8_gfx_cmdbuf* cb, pxl8_gfx_bindings bindings);
|
||||
void pxl8_set_draw_params(pxl8_gfx_cmdbuf* cb, const pxl8_gfx_cmd_draw_params* p);
|
||||
|
|
|
|||
|
|
@ -177,14 +177,15 @@ typedef struct pxl8_gfx_cmd_draw_params {
|
|||
|
||||
typedef enum pxl8_gfx_cmd_type {
|
||||
PXL8_GFX_CMD_BEGIN_PASS,
|
||||
PXL8_GFX_CMD_END_PASS,
|
||||
PXL8_GFX_CMD_SET_PIPELINE,
|
||||
PXL8_GFX_CMD_SET_BINDINGS,
|
||||
PXL8_GFX_CMD_SET_VIEWPORT,
|
||||
PXL8_GFX_CMD_SET_SCISSOR,
|
||||
PXL8_GFX_CMD_SET_DRAW_PARAMS,
|
||||
PXL8_GFX_CMD_CLEAR_DEPTH,
|
||||
PXL8_GFX_CMD_DRAW,
|
||||
PXL8_GFX_CMD_END_PASS,
|
||||
PXL8_GFX_CMD_RESOLVE,
|
||||
PXL8_GFX_CMD_SET_BINDINGS,
|
||||
PXL8_GFX_CMD_SET_DRAW_PARAMS,
|
||||
PXL8_GFX_CMD_SET_PIPELINE,
|
||||
PXL8_GFX_CMD_SET_SCISSOR,
|
||||
PXL8_GFX_CMD_SET_VIEWPORT,
|
||||
} pxl8_gfx_cmd_type;
|
||||
|
||||
typedef struct pxl8_gfx_cmd_begin_pass {
|
||||
|
|
@ -217,6 +218,10 @@ typedef struct pxl8_gfx_cmd_draw {
|
|||
u32 index_count;
|
||||
} pxl8_gfx_cmd_draw;
|
||||
|
||||
typedef struct pxl8_gfx_cmd_clear_depth {
|
||||
pxl8_gfx_texture texture;
|
||||
} pxl8_gfx_cmd_clear_depth;
|
||||
|
||||
typedef struct pxl8_gfx_cmd_resolve {
|
||||
pxl8_gfx_texture src;
|
||||
u32* output;
|
||||
|
|
@ -226,13 +231,14 @@ typedef struct pxl8_gfx_cmd {
|
|||
pxl8_gfx_cmd_type type;
|
||||
union {
|
||||
pxl8_gfx_cmd_begin_pass begin_pass;
|
||||
pxl8_gfx_cmd_set_pipeline set_pipeline;
|
||||
pxl8_gfx_cmd_set_bindings set_bindings;
|
||||
pxl8_gfx_cmd_set_viewport set_viewport;
|
||||
pxl8_gfx_cmd_set_scissor set_scissor;
|
||||
pxl8_gfx_cmd_clear_depth clear_depth;
|
||||
pxl8_gfx_cmd_draw draw;
|
||||
pxl8_gfx_cmd_draw_params draw_params;
|
||||
pxl8_gfx_cmd_resolve resolve;
|
||||
pxl8_gfx_cmd_set_bindings set_bindings;
|
||||
pxl8_gfx_cmd_set_pipeline set_pipeline;
|
||||
pxl8_gfx_cmd_set_scissor set_scissor;
|
||||
pxl8_gfx_cmd_set_viewport set_viewport;
|
||||
};
|
||||
} pxl8_gfx_cmd;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ typedef struct pxl8_vertex_out {
|
|||
typedef struct pxl8_shader_uniforms {
|
||||
u8 ambient;
|
||||
bool baked_lighting;
|
||||
pxl8_vec3 camera_pos;
|
||||
pxl8_vec3 celestial_dir;
|
||||
f32 celestial_intensity;
|
||||
bool dither;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ void pxl8_shader_lit(
|
|||
}
|
||||
|
||||
pxl8_f32_simd light = ctx->v_light;
|
||||
pxl8_f32_simd dynamic_total = pxl8_f32_simd_zero();
|
||||
f32 max_strength[4] = {0, 0, 0, 0};
|
||||
u8 dominant_color[4] = {0, 0, 0, 0};
|
||||
|
||||
|
|
@ -101,10 +102,31 @@ void pxl8_shader_lit(
|
|||
}
|
||||
|
||||
light = pxl8_f32_simd_add(light, strength);
|
||||
dynamic_total = pxl8_f32_simd_add(dynamic_total, strength);
|
||||
}
|
||||
}
|
||||
|
||||
light = pxl8_f32_simd_clamp(light, pxl8_f32_simd_zero(), pxl8_f32_simd_set(1.0f));
|
||||
dynamic_total = pxl8_f32_simd_clamp(dynamic_total, pxl8_f32_simd_zero(), pxl8_f32_simd_set(1.0f));
|
||||
|
||||
if (uniforms && uniforms->fog_density > 0.0f) {
|
||||
pxl8_vec3_simd cam = pxl8_vec3_simd_set(uniforms->camera_pos);
|
||||
pxl8_vec3_simd to_frag = pxl8_vec3_simd_sub(ctx->v_world, cam);
|
||||
pxl8_f32_simd dist_sq = pxl8_vec3_simd_dot(to_frag, to_frag);
|
||||
pxl8_f32_simd fog_sq = pxl8_f32_simd_set(uniforms->fog_density * uniforms->fog_density);
|
||||
pxl8_f32_simd fog = pxl8_f32_simd_clamp(
|
||||
pxl8_f32_simd_mul(dist_sq, fog_sq),
|
||||
pxl8_f32_simd_zero(), pxl8_f32_simd_set(1.0f)
|
||||
);
|
||||
light = pxl8_f32_simd_mul(light, pxl8_f32_simd_sub(pxl8_f32_simd_set(1.0f), fog));
|
||||
pxl8_f32_simd scatter = pxl8_f32_simd_mul(
|
||||
pxl8_f32_simd_mul(dynamic_total, fog),
|
||||
pxl8_f32_simd_set(0.4f)
|
||||
);
|
||||
light = pxl8_f32_simd_add(light, scatter);
|
||||
light = pxl8_f32_simd_clamp(light, pxl8_f32_simd_zero(), pxl8_f32_simd_set(1.0f));
|
||||
}
|
||||
|
||||
pxl8_f32_simd light_f = pxl8_f32_simd_mul(light, pxl8_f32_simd_set(255.0f));
|
||||
|
||||
f32 light_arr[4];
|
||||
|
|
@ -133,6 +155,7 @@ void pxl8_shader_lit(
|
|||
}
|
||||
|
||||
f32 light = ctx->v_light;
|
||||
f32 dynamic_total = 0.0f;
|
||||
f32 max_strength = 0;
|
||||
u8 dominant_color = 0;
|
||||
|
||||
|
|
@ -178,11 +201,25 @@ void pxl8_shader_lit(
|
|||
dominant_color = l->color;
|
||||
}
|
||||
light += strength;
|
||||
dynamic_total += strength;
|
||||
}
|
||||
}
|
||||
|
||||
if (light > 1.0f) light = 1.0f;
|
||||
if (light < 0.0f) light = 0.0f;
|
||||
if (dynamic_total > 1.0f) dynamic_total = 1.0f;
|
||||
|
||||
if (uniforms && uniforms->fog_density > 0.0f) {
|
||||
f32 dx = ctx->v_world.x - uniforms->camera_pos.x;
|
||||
f32 dy = ctx->v_world.y - uniforms->camera_pos.y;
|
||||
f32 dz = ctx->v_world.z - uniforms->camera_pos.z;
|
||||
f32 dist_sq = dx * dx + dy * dy + dz * dz;
|
||||
f32 fog = dist_sq * uniforms->fog_density * uniforms->fog_density;
|
||||
if (fog > 1.0f) fog = 1.0f;
|
||||
light *= (1.0f - fog);
|
||||
light += dynamic_total * fog * 0.4f;
|
||||
if (light > 1.0f) light = 1.0f;
|
||||
}
|
||||
|
||||
f32 light_f = light * 255.0f;
|
||||
u8 light_u8 = (u8)light_f;
|
||||
|
|
|
|||
|
|
@ -106,6 +106,20 @@ pxl8.get_wireframe = gfx.get_wireframe
|
|||
|
||||
pxl8.Lights = effects.Lights
|
||||
pxl8.create_lights = effects.Lights.new
|
||||
pxl8.Glows = effects.Glows
|
||||
pxl8.create_glows = effects.Glows.new
|
||||
pxl8.GLOW_CIRCLE = 0
|
||||
pxl8.GLOW_DIAMOND = 1
|
||||
pxl8.GLOW_SHAFT = 2
|
||||
|
||||
pxl8.LIGHT_WHITE = 0
|
||||
pxl8.LIGHT_RED = 1
|
||||
pxl8.LIGHT_ORANGE = 2
|
||||
pxl8.LIGHT_YELLOW = 3
|
||||
pxl8.LIGHT_GREEN = 4
|
||||
pxl8.LIGHT_CYAN = 5
|
||||
pxl8.LIGHT_BLUE = 6
|
||||
pxl8.LIGHT_PURPLE = 7
|
||||
|
||||
pxl8.Compressor = sfx.Compressor
|
||||
pxl8.create_compressor = sfx.Compressor.new
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
local core = require("pxl8.core")
|
||||
|
||||
local effects = {}
|
||||
|
||||
|
|
@ -35,4 +36,40 @@ end
|
|||
|
||||
effects.Lights = Lights
|
||||
|
||||
local Glows = {}
|
||||
Glows.__index = Glows
|
||||
|
||||
function Glows.new(capacity)
|
||||
local ptr = C.pxl8_glows_create(capacity or 256)
|
||||
if ptr == nil then
|
||||
return nil
|
||||
end
|
||||
return setmetatable({ _ptr = ptr }, Glows)
|
||||
end
|
||||
|
||||
function Glows:add(x, y, radius, intensity, color, shape, depth)
|
||||
C.pxl8_glows_add(self._ptr, x, y, radius or 32, intensity or 128, color or 0, shape or 0, depth or 0xFFFF)
|
||||
end
|
||||
|
||||
function Glows:clear()
|
||||
C.pxl8_glows_clear(self._ptr)
|
||||
end
|
||||
|
||||
function Glows:count()
|
||||
return C.pxl8_glows_count(self._ptr)
|
||||
end
|
||||
|
||||
function Glows:render()
|
||||
C.pxl8_glows_render(self._ptr, core.gfx)
|
||||
end
|
||||
|
||||
function Glows:destroy()
|
||||
if self._ptr then
|
||||
C.pxl8_glows_destroy(self._ptr)
|
||||
self._ptr = nil
|
||||
end
|
||||
end
|
||||
|
||||
effects.Glows = Glows
|
||||
|
||||
return effects
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ function Bsp:face_normal(face_id)
|
|||
return C.pxl8_bsp_face_normal(self._ptr, face_id)
|
||||
end
|
||||
|
||||
function Bsp:light_at(x, y, z, ambient)
|
||||
return C.pxl8_bsp_light_at(self._ptr, x, y, z, ambient or 0)
|
||||
end
|
||||
|
||||
function Bsp:face_set_material(face_id, material_id)
|
||||
C.pxl8_bsp_face_set_material(self._ptr, face_id, material_id)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "pxl8_types.h"
|
||||
|
|
|
|||
|
|
@ -220,8 +220,17 @@ static const char* pxl8_ffi_cdefs =
|
|||
"u32 pxl8_lights_count(const pxl8_lights* lights);\n"
|
||||
"const pxl8_light* pxl8_lights_data(const pxl8_lights* lights);\n"
|
||||
"\n"
|
||||
"typedef struct pxl8_glows pxl8_glows;\n"
|
||||
"pxl8_glows* pxl8_glows_create(u32 capacity);\n"
|
||||
"void pxl8_glows_destroy(pxl8_glows* glows);\n"
|
||||
"void pxl8_glows_add(pxl8_glows* glows, i16 x, i16 y, u8 radius, u16 intensity, u8 color, u8 shape, u16 depth);\n"
|
||||
"void pxl8_glows_clear(pxl8_glows* glows);\n"
|
||||
"u32 pxl8_glows_count(const pxl8_glows* glows);\n"
|
||||
"void pxl8_glows_render(pxl8_glows* glows, pxl8_gfx* gfx);\n"
|
||||
"\n"
|
||||
"typedef struct pxl8_3d_uniforms {\n"
|
||||
" u8 ambient;\n"
|
||||
" pxl8_vec3 camera_pos;\n"
|
||||
" pxl8_vec3 celestial_dir;\n"
|
||||
" f32 celestial_intensity;\n"
|
||||
" u8 fog_color;\n"
|
||||
|
|
@ -392,6 +401,7 @@ static const char* pxl8_ffi_cdefs =
|
|||
"\n"
|
||||
"u32 pxl8_bsp_face_count(const pxl8_bsp* bsp);\n"
|
||||
"pxl8_vec3 pxl8_bsp_face_normal(const pxl8_bsp* bsp, u32 face_id);\n"
|
||||
"u8 pxl8_bsp_light_at(const pxl8_bsp* bsp, f32 x, f32 y, f32 z, u8 ambient);\n"
|
||||
"\n"
|
||||
"typedef enum { PXL8_WORLD_CHUNK_VXL = 0, PXL8_WORLD_CHUNK_BSP = 1 } pxl8_world_chunk_type;\n"
|
||||
"\n"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue