diff --git a/demo/mod/sky.fnl b/demo/mod/sky.fnl index cb04abe..426512b 100644 --- a/demo/mod/sky.fnl +++ b/demo/mod/sky.fnl @@ -1,5 +1,4 @@ (local pxl8 (require :pxl8)) -(local effects (require :pxl8.effects)) (local SKY_GRADIENT_START 144) (local SKY_GRADIENT_COUNT 16) @@ -25,6 +24,7 @@ (var sky-mesh nil) (var star-count 0) (var star-directions nil) +(var star-glows nil) (var star-projected nil) (var star-time 0) (var tiny-stars []) @@ -167,6 +167,7 @@ (set star-count (+ (length tiny-stars) (length random-stars))) (set star-directions (pxl8.create_vec3_array star-count)) + (set star-glows (pxl8.create_glows 10000)) (set star-projected (pxl8.create_vec3_array star-count)) (var idx 0) @@ -185,9 +186,8 @@ (fn render-stars [cam-x cam-y cam-z intensity dt] (set star-time (+ star-time (or dt 0))) - (when (and (> intensity 0) (> star-count 0)) - (let [glows [] - fade-in (* intensity intensity) + (when (and (> intensity 0) (> star-count 0) star-glows) + (let [fade-in (* intensity intensity) time-factor (/ star-time 60) star-rotation (/ (* star-time math.pi 2) STAR_CYCLE_PERIOD) t (pxl8.mat4_translate cam-x cam-y cam-z) @@ -196,6 +196,7 @@ transform (pxl8.mat4_multiply t (pxl8.mat4_multiply r s)) tiny-count (length tiny-stars)] + (star-glows:clear) (pxl8.project_points star-directions star-projected star-count transform) (for [i 0 (- tiny-count 1)] @@ -204,11 +205,8 @@ (let [star (. tiny-stars (+ i 1)) int (math.floor (* star.brightness fade-in))] (when (> int 8) - (table.insert glows {:x (math.floor screen.x) :y (math.floor screen.y) - :radius 1 - :intensity int - :color star.color - :shape effects.GLOW_CIRCLE})))))) + (star-glows:add (math.floor screen.x) (math.floor screen.y) + 1 int star.color pxl8.GLOW_CIRCLE)))))) (for [i 0 (- (length random-stars) 1)] (let [screen (. star-projected (+ tiny-count i))] @@ -221,33 +219,20 @@ sy (math.floor screen.y)] (if (> star.brightness 220) (do - (table.insert glows {:x sx :y sy :radius 3 - :intensity (math.floor (* int 1.5)) - :color star.color :shape effects.GLOW_DIAMOND}) - (table.insert glows {:x sx :y sy :radius 5 - :intensity (math.floor (/ int 2)) - :color star.color :shape effects.GLOW_CIRCLE})) + (star-glows:add sx sy 3 (math.floor (* int 1.5)) star.color pxl8.GLOW_DIAMOND) + (star-glows:add sx sy 5 (math.floor (/ int 2)) star.color pxl8.GLOW_CIRCLE)) (> star.brightness 180) (do - (table.insert glows {:x sx :y sy :radius 2 :intensity int - :color star.color :shape effects.GLOW_DIAMOND}) - (table.insert glows {:x sx :y sy :radius 4 - :intensity (math.floor (/ int 3)) - :color star.color :shape effects.GLOW_CIRCLE})) + (star-glows:add sx sy 2 int star.color pxl8.GLOW_DIAMOND) + (star-glows:add sx sy 4 (math.floor (/ int 3)) star.color pxl8.GLOW_CIRCLE)) (> star.brightness 120) (do - (table.insert glows {:x sx :y sy :radius 2 - :intensity (math.floor (* int 0.67)) - :color star.color :shape effects.GLOW_DIAMOND}) - (table.insert glows {:x sx :y sy :radius 3 - :intensity (math.floor (/ int 4)) - :color star.color :shape effects.GLOW_CIRCLE})) - (table.insert glows {:x sx :y sy :radius 2 - :intensity (math.floor (* int 0.5)) - :color star.color :shape effects.GLOW_CIRCLE})))))) + (star-glows:add sx sy 2 (math.floor (* int 0.67)) star.color pxl8.GLOW_DIAMOND) + (star-glows:add sx sy 3 (math.floor (/ int 4)) star.color pxl8.GLOW_CIRCLE)) + (star-glows:add sx sy 2 (math.floor (* int 0.5)) star.color pxl8.GLOW_CIRCLE)))))) - (when (> (length glows) 0) - (effects.glows glows))))) + (when (> (star-glows:count) 0) + (star-glows:render))))) (fn render [cam-x cam-y cam-z wireframe] (when (not sky-mesh) (create-sky-dome)) diff --git a/pxl8.sh b/pxl8.sh index 9ef8c35..8a5cd43 100755 --- a/pxl8.sh +++ b/pxl8.sh @@ -395,6 +395,7 @@ case "$COMMAND" in src/gfx/pxl8_dither.c src/gfx/pxl8_font.c src/gfx/pxl8_gfx.c + src/gfx/pxl8_glows.c src/gfx/pxl8_lightmap.c src/gfx/pxl8_mesh.c src/gfx/pxl8_palette.c diff --git a/src/gfx/pxl8_glows.c b/src/gfx/pxl8_glows.c new file mode 100644 index 0000000..4279d8e --- /dev/null +++ b/src/gfx/pxl8_glows.c @@ -0,0 +1,59 @@ +#include "pxl8_glows.h" + +#include + +struct pxl8_glows { + pxl8_glow_source* data; + u32 capacity; + u32 count; +}; + +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)); + if (!glows->data) { + free(glows); + return NULL; + } + + glows->capacity = capacity; + glows->count = 0; + + return glows; +} + +void pxl8_glows_destroy(pxl8_glows* glows) { + if (!glows) return; + free(glows->data); + free(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++]; + g->x = x; + g->y = y; + g->radius = radius; + g->intensity = intensity; + g->color = color; + g->shape = shape; + g->depth = 0xFFFF; + g->height = 0; +} + +void pxl8_glows_clear(pxl8_glows* glows) { + if (!glows) return; + glows->count = 0; +} + +u32 pxl8_glows_count(const pxl8_glows* glows) { + return glows ? glows->count : 0; +} + +void pxl8_glows_render(pxl8_glows* glows, pxl8_gfx* gfx) { + if (!glows || !gfx || glows->count == 0) return; + pxl8_gfx_apply_effect(gfx, PXL8_GFX_EFFECT_GLOWS, glows->data, glows->count); +} diff --git a/src/gfx/pxl8_glows.h b/src/gfx/pxl8_glows.h new file mode 100644 index 0000000..f292d1b --- /dev/null +++ b/src/gfx/pxl8_glows.h @@ -0,0 +1,22 @@ +#pragma once + +#include "pxl8_gfx.h" +#include "pxl8_types.h" + +typedef struct pxl8_glows pxl8_glows; + +#ifdef __cplusplus +extern "C" { +#endif + +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_clear(pxl8_glows* glows); +u32 pxl8_glows_count(const pxl8_glows* glows); +void pxl8_glows_render(pxl8_glows* glows, pxl8_gfx* gfx); + +#ifdef __cplusplus +} +#endif diff --git a/src/lua/pxl8.lua b/src/lua/pxl8.lua index 40d29c9..b486b05 100644 --- a/src/lua/pxl8.lua +++ b/src/lua/pxl8.lua @@ -1,6 +1,7 @@ local anim = require("pxl8.anim") local bytes = require("pxl8.bytes") local core = require("pxl8.core") +local effects = require("pxl8.effects") local gfx2d = require("pxl8.gfx2d") local gfx3d = require("pxl8.gfx3d") local gui = require("pxl8.gui") @@ -98,6 +99,12 @@ pxl8.draw_mesh = gfx3d.draw_mesh pxl8.end_frame_3d = gfx3d.end_frame pxl8.project_points = gfx3d.project_points +pxl8.GLOW_CIRCLE = effects.GLOW_CIRCLE +pxl8.GLOW_DIAMOND = effects.GLOW_DIAMOND +pxl8.GLOW_SHAFT = effects.GLOW_SHAFT +pxl8.Glows = effects.Glows +pxl8.create_glows = effects.Glows.new + pxl8.Compressor = sfx.Compressor pxl8.create_compressor = sfx.Compressor.new pxl8.Delay = sfx.Delay diff --git a/src/lua/pxl8/effects.lua b/src/lua/pxl8/effects.lua index 4db069a..260d04c 100644 --- a/src/lua/pxl8/effects.lua +++ b/src/lua/pxl8/effects.lua @@ -8,25 +8,40 @@ effects.GLOW_CIRCLE = 0 effects.GLOW_DIAMOND = 1 effects.GLOW_SHAFT = 2 -function effects.glows(glows) - if not glows or #glows == 0 then return end +local Glows = {} +Glows.__index = Glows - local count = #glows - local glow_array = ffi.new("pxl8_glow_source[?]", count) - - for i, g in ipairs(glows) do - local idx = i - 1 - glow_array[idx].x = g.x or 0 - glow_array[idx].y = g.y or 0 - glow_array[idx].radius = g.radius or 8 - glow_array[idx].intensity = g.intensity or 255 - glow_array[idx].color = g.color or 15 - glow_array[idx].depth = g.depth or 0xFFFF - glow_array[idx].height = g.height or 0 - glow_array[idx].shape = g.shape or 0 +function Glows.new(capacity) + local ptr = C.pxl8_glows_create(capacity or 1000) + if ptr == nil then + return nil end - - C.pxl8_gfx_apply_effect(core.gfx, C.PXL8_GFX_EFFECT_GLOWS, glow_array, count) + return setmetatable({ _ptr = ptr }, Glows) end +function Glows:add(x, y, radius, intensity, color, shape) + C.pxl8_glows_add(self._ptr, x, y, radius or 8, intensity or 255, color or 15, shape or 0) +end + +function Glows:clear() + C.pxl8_glows_clear(self._ptr) +end + +function Glows:count() + return C.pxl8_glows_count(self._ptr) +end + +function Glows:destroy() + if self._ptr then + C.pxl8_glows_destroy(self._ptr) + self._ptr = nil + end +end + +function Glows:render() + C.pxl8_glows_render(self._ptr, core.gfx) +end + +effects.Glows = Glows + return effects diff --git a/src/script/pxl8_script_ffi.h b/src/script/pxl8_script_ffi.h index 858c421..b66e161 100644 --- a/src/script/pxl8_script_ffi.h +++ b/src/script/pxl8_script_ffi.h @@ -249,6 +249,14 @@ static const char* pxl8_ffi_cdefs = "\n" "void pxl8_gfx_apply_effect(pxl8_gfx* gfx, pxl8_gfx_effect effect, const void* params, u32 count);\n" "void pxl8_gfx_blend_tables_update(pxl8_gfx* gfx);\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);\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" "void pxl8_gfx_colormap_update(pxl8_gfx* gfx);\n" "\n" "void pxl8_3d_begin_frame(pxl8_gfx* gfx, const pxl8_3d_camera* camera, const pxl8_3d_uniforms* uniforms);\n"