gpu particle testing
This commit is contained in:
parent
0e269f0e83
commit
b8e08c72ad
Binary file not shown.
Binary file not shown.
@ -486,9 +486,11 @@
|
|||||||
typedef u32 b32;
|
typedef u32 b32;
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
typedef int i32;
|
typedef int i32;
|
||||||
|
typedef int64_t i64;
|
||||||
typedef uint u32;
|
typedef uint u32;
|
||||||
|
typedef uint64_t u64;
|
||||||
typedef float f32;
|
typedef float f32;
|
||||||
typedef uint b32;
|
typedef bool b32; // bool has 32-bit size & alignment in HLSL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Min / max constants
|
//- Min / max constants
|
||||||
@ -609,6 +611,7 @@
|
|||||||
#define CompLit(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
#define CompLit(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
||||||
#define StringFromPointers(p0, p1) ((String) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
#define StringFromPointers(p0, p1) ((String) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
||||||
#define StringFromStruct(ptr) ((String) { sizeof(*(ptr)), (u8 *)(ptr) })
|
#define StringFromStruct(ptr) ((String) { sizeof(*(ptr)), (u8 *)(ptr) })
|
||||||
|
#define StringFromStructs(ptr, count) ((String) { sizeof(*(ptr)) * (count), (u8 *)(ptr) })
|
||||||
#define StringFromArena(arena) (STRING((arena)->pos, ArenaFirst(arena, u8)))
|
#define StringFromArena(arena) (STRING((arena)->pos, ArenaFirst(arena, u8)))
|
||||||
|
|
||||||
#define StringFromFixedArray(a) \
|
#define StringFromFixedArray(a) \
|
||||||
@ -742,23 +745,23 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Basic mixing/hashing
|
//~ Basic mixing/hashing
|
||||||
|
|
||||||
#if IsLanguageC
|
// Based on Jon Maiga's "mx3"
|
||||||
// Based on Jon Maiga's "mx3"
|
// https://jonkagstrom.com/mx3/mx3_rev2.html
|
||||||
// https://jonkagstrom.com/mx3/mx3_rev2.html
|
u64 MixU64(u64 seed)
|
||||||
u64 MixU64(u64 seed)
|
{
|
||||||
{
|
|
||||||
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
||||||
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
|
||||||
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
||||||
seed = (seed ^ (seed >> 29));
|
seed = (seed ^ (seed >> 29));
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 MixU64s(u64 seed_a, u64 seed_b)
|
u64 MixU64s(u64 seed_a, u64 seed_b)
|
||||||
{
|
{
|
||||||
return MixU64((seed_a * 3) + seed_b);
|
return MixU64((seed_a * 3) + seed_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IsLanguageC
|
||||||
// FNV-1a parameters for different hash sizes:
|
// FNV-1a parameters for different hash sizes:
|
||||||
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_hash_parameters
|
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_hash_parameters
|
||||||
Inline u64 HashFnv64(u64 seed, String s)
|
Inline u64 HashFnv64(u64 seed, String s)
|
||||||
|
|||||||
@ -103,11 +103,11 @@ G_ForceDeclConstant(f32, G_ShaderConst_TweakF32, 10
|
|||||||
template<typename T> u32 countof(RWStructuredBuffer<T> buff) { u32 result; buff.GetDimensions(result); return result; }
|
template<typename T> u32 countof(RWStructuredBuffer<T> buff) { u32 result; buff.GetDimensions(result); return result; }
|
||||||
u32 countof(ByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
u32 countof(ByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
||||||
u32 countof(RWByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
u32 countof(RWByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
||||||
u32 countof(Texture1D tex) { u32 result; tex.GetDimensions(result); return result; }
|
template<typename T> u32 countof(Texture1D<T> tex) { u32 result; tex.GetDimensions(result); return result; }
|
||||||
template<typename T> u32 countof(RWTexture1D<T> tex) { u32 result; tex.GetDimensions(result); return result; }
|
template<typename T> u32 countof(RWTexture1D<T> tex) { u32 result; tex.GetDimensions(result); return result; }
|
||||||
Vec2U32 countof(Texture2D tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
template<typename T> Vec2U32 countof(Texture2D<T> tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
||||||
template<typename T> Vec2U32 countof(RWTexture2D<T> tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
template<typename T> Vec2U32 countof(RWTexture2D<T> tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
||||||
Vec3U32 countof(Texture3D tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
template<typename T> Vec3U32 countof(Texture3D<T> tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
||||||
template<typename T> Vec3U32 countof(RWTexture3D<T> tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
template<typename T> Vec3U32 countof(RWTexture3D<T> tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,9 @@
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Api
|
//- Api
|
||||||
|
|
||||||
@IncludeC pp_sim_tiles.cgh
|
@IncludeC pp_sim_shared.cgh
|
||||||
@IncludeG pp_sim_tiles.cgh
|
@IncludeG pp_sim_shared.cgh
|
||||||
|
|
||||||
@IncludeC pp_sim_core.h
|
@IncludeC pp_sim_core.h
|
||||||
@IncludeC pp_sim_transcode.h
|
@IncludeC pp_sim_transcode.h
|
||||||
|
|
||||||
@ -20,5 +21,5 @@
|
|||||||
|
|
||||||
@IncludeC pp_sim_core.c
|
@IncludeC pp_sim_core.c
|
||||||
@IncludeC pp_sim_transcode.c
|
@IncludeC pp_sim_transcode.c
|
||||||
@IncludeC pp_sim_tiles.cg
|
@IncludeC pp_sim_shared.cg
|
||||||
@IncludeG pp_sim_tiles.cg
|
@IncludeG pp_sim_shared.cg
|
||||||
|
|||||||
@ -1469,8 +1469,6 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Debug draw entities
|
//- Debug draw entities
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Tile types
|
//~ Tile types
|
||||||
|
|
||||||
#define S_WorldPitch 96
|
#define S_WorldPitch 96.0
|
||||||
#define S_TilesPitch (S_WorldPitch * 2)
|
#define S_TilesPitch (S_WorldPitch * 2)
|
||||||
#define S_TilesCount (S_TilesPitch * S_TilesPitch)
|
#define S_TilesCount (S_TilesPitch * S_TilesPitch)
|
||||||
|
|
||||||
@ -22,15 +22,18 @@
|
|||||||
@PixelShader V_DVertPS
|
@PixelShader V_DVertPS
|
||||||
@VertexShader V_OverlayVS
|
@VertexShader V_OverlayVS
|
||||||
@PixelShader V_OverlayPS
|
@PixelShader V_OverlayPS
|
||||||
|
@ComputeShader V_EmitParticlesCS
|
||||||
|
@ComputeShader V_SimParticlesCS
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Api
|
//- Api
|
||||||
|
|
||||||
@IncludeC pp_vis_shaders.cgh
|
@IncludeC pp_vis_shared.cgh
|
||||||
|
@IncludeG pp_vis_shared.cgh
|
||||||
|
|
||||||
@IncludeC pp_vis_core.h
|
@IncludeC pp_vis_core.h
|
||||||
|
|
||||||
@IncludeG pp_vis_shaders.cgh
|
@IncludeG pp_vis_gpu.gh
|
||||||
@IncludeG pp_vis_shaders.gh
|
|
||||||
|
|
||||||
@Bootstrap V_Bootstrap
|
@Bootstrap V_Bootstrap
|
||||||
|
|
||||||
@ -39,4 +42,4 @@
|
|||||||
|
|
||||||
@IncludeC pp_vis_core.c
|
@IncludeC pp_vis_core.c
|
||||||
|
|
||||||
@IncludeG pp_vis_shaders.g
|
@IncludeG pp_vis_gpu.g
|
||||||
|
|||||||
@ -307,12 +307,37 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
world->ent_bins_count = Kibi(16);
|
world->ent_bins_count = Kibi(16);
|
||||||
world->ent_bins = PushStructs(world_arena, S_EntBin, world->ent_bins_count);
|
world->ent_bins = PushStructs(world_arena, S_EntBin, world->ent_bins_count);
|
||||||
world->tiles = PushStructs(world_arena, u8, S_TilesCount);
|
world->tiles = PushStructs(world_arena, u8, S_TilesCount);
|
||||||
Vec2I32 tiles_dims = VEC2I32(S_TilesPitch, S_TilesPitch);
|
|
||||||
|
|
||||||
|
Vec2I32 tiles_dims = VEC2I32(S_TilesPitch, S_TilesPitch);
|
||||||
|
Vec2I32 decals_dims = VEC2I32(V_PixelsPerMeter * S_WorldPitch, V_PixelsPerMeter * S_WorldPitch);
|
||||||
|
|
||||||
|
u32 max_particles = Kibi(128);
|
||||||
|
|
||||||
|
// Init gpu state
|
||||||
|
G_ResourceHandle gpu_state = Zi;
|
||||||
G_ResourceHandle gpu_tiles = Zi;
|
G_ResourceHandle gpu_tiles = Zi;
|
||||||
|
G_ResourceHandle gpu_particles = Zi;
|
||||||
|
G_ResourceHandle gpu_decals = Zi;
|
||||||
|
G_RWStructuredBufferRef gpu_state_ref = Zi;
|
||||||
G_Texture2DRef gpu_tiles_ref = Zi;
|
G_Texture2DRef gpu_tiles_ref = Zi;
|
||||||
|
G_RWStructuredBufferRef gpu_particles_ref = Zi;
|
||||||
|
G_RWTexture2DRef gpu_decals_ref = Zi;
|
||||||
{
|
{
|
||||||
|
// FIXME: Clear initial resource memory
|
||||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
||||||
|
{
|
||||||
|
// Init state buffer
|
||||||
|
{
|
||||||
|
gpu_state = G_PushBuffer(
|
||||||
|
gpu_perm, cl,
|
||||||
|
V_GpuState,
|
||||||
|
1,
|
||||||
|
.flags = G_ResourceFlag_AllowShaderReadWrite
|
||||||
|
);
|
||||||
|
gpu_state_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_state, V_GpuState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init tile map texture
|
||||||
{
|
{
|
||||||
gpu_tiles = G_PushTexture2D(
|
gpu_tiles = G_PushTexture2D(
|
||||||
gpu_perm, cl,
|
gpu_perm, cl,
|
||||||
@ -321,13 +346,28 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
G_Layout_DirectQueue_ShaderRead_ShaderReadWrite_CopyRead_CopyWrite
|
G_Layout_DirectQueue_ShaderRead_ShaderReadWrite_CopyRead_CopyWrite
|
||||||
);
|
);
|
||||||
gpu_tiles_ref = G_PushTexture2DRef(gpu_perm, gpu_tiles);
|
gpu_tiles_ref = G_PushTexture2DRef(gpu_perm, gpu_tiles);
|
||||||
// TODO: Clear tiles from GPU (instead of copy from cpu)
|
}
|
||||||
G_CopyCpuToTexture(
|
// Init particle buffer
|
||||||
cl,
|
{
|
||||||
gpu_tiles, VEC3I32(0, 0, 0),
|
gpu_particles = G_PushBuffer(
|
||||||
world->tiles, VEC3I32(tiles_dims.x, tiles_dims.y, 1),
|
gpu_perm, cl,
|
||||||
RNG3I32(VEC3I32(0, 0, 0), VEC3I32(tiles_dims.x, tiles_dims.y, 1))
|
V_Particle,
|
||||||
|
max_particles,
|
||||||
|
.flags = G_ResourceFlag_AllowShaderReadWrite
|
||||||
);
|
);
|
||||||
|
gpu_particles_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles, V_Particle);
|
||||||
|
}
|
||||||
|
// Init decal texture
|
||||||
|
{
|
||||||
|
gpu_decals = G_PushTexture2D(
|
||||||
|
gpu_perm, cl,
|
||||||
|
G_Format_R8_Uint,
|
||||||
|
decals_dims,
|
||||||
|
G_Layout_DirectQueue_ShaderReadWrite,
|
||||||
|
.flags = G_ResourceFlag_AllowShaderReadWrite
|
||||||
|
);
|
||||||
|
gpu_decals_ref = G_PushRWTexture2DRef(gpu_perm, gpu_decals);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
G_CommitCommandList(cl);
|
G_CommitCommandList(cl);
|
||||||
}
|
}
|
||||||
@ -342,7 +382,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- State
|
//- Init shortcuts
|
||||||
|
|
||||||
// Init shortcuts
|
// Init shortcuts
|
||||||
u64 shortcut_bins_count = 1024;
|
u64 shortcut_bins_count = 1024;
|
||||||
@ -420,6 +460,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->time_ns = TimeNs();
|
frame->time_ns = TimeNs();
|
||||||
frame->dt_ns = ClampI64(frame->time_ns - last_frame->time_ns, 1, NsFromSeconds(1.0 / 50));
|
frame->dt_ns = ClampI64(frame->time_ns - last_frame->time_ns, 1, NsFromSeconds(1.0 / 50));
|
||||||
frame->dt = SecondsFromNs(frame->dt_ns);
|
frame->dt = SecondsFromNs(frame->dt_ns);
|
||||||
|
frame->rand = last_frame->rand;
|
||||||
|
|
||||||
if (S_IsKeyNil(V.player_key))
|
if (S_IsKeyNil(V.player_key))
|
||||||
{
|
{
|
||||||
@ -727,11 +768,11 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Initialize world <-> draw <-> ui transforms
|
//- Compute frame xforms
|
||||||
|
|
||||||
// World <-> ui
|
// World <-> ui
|
||||||
frame->world_to_ui_xf = XformIdentity;
|
frame->xf.world_to_ui = XformIdentity;
|
||||||
frame->ui_to_world_xf = XformIdentity;
|
frame->xf.ui_to_world = XformIdentity;
|
||||||
{
|
{
|
||||||
// Determine target camera pos
|
// Determine target camera pos
|
||||||
Vec2 target_camera_pos = Zi;
|
Vec2 target_camera_pos = Zi;
|
||||||
@ -812,35 +853,45 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->camera_zoom = LerpF32(last_frame->camera_zoom, target_camera_zoom, frame->camera_lerp_rate);
|
frame->camera_zoom = LerpF32(last_frame->camera_zoom, target_camera_zoom, frame->camera_lerp_rate);
|
||||||
{
|
{
|
||||||
f32 camera_scale = (f32)frame->draw_dims.x / (meters_per_draw_width * frame->camera_zoom);
|
f32 camera_scale = (f32)frame->draw_dims.x / (meters_per_draw_width * frame->camera_zoom);
|
||||||
frame->world_to_ui_xf = XformFromScale(VEC2(camera_scale, camera_scale));
|
frame->xf.world_to_ui = XformFromScale(VEC2(camera_scale, camera_scale));
|
||||||
frame->world_to_ui_xf = TranslateXform(frame->world_to_ui_xf, NegVec2(frame->camera_pos));
|
frame->xf.world_to_ui = TranslateXform(frame->xf.world_to_ui, NegVec2(frame->camera_pos));
|
||||||
frame->world_to_ui_xf = WorldTranslateXform(frame->world_to_ui_xf, MulVec2(Vec2FromVec(frame->draw_dims), 0.5));
|
frame->xf.world_to_ui = WorldTranslateXform(frame->xf.world_to_ui, MulVec2(Vec2FromVec(frame->draw_dims), 0.5));
|
||||||
frame->ui_to_world_xf = InvertXform(frame->world_to_ui_xf);
|
frame->xf.ui_to_world = InvertXform(frame->xf.world_to_ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw <-> ui
|
// Draw <-> ui
|
||||||
frame->draw_to_ui_xf = XformIdentity;
|
frame->xf.draw_to_ui = XformIdentity;
|
||||||
frame->ui_to_draw_xf = XformIdentity;
|
frame->xf.ui_to_draw = XformIdentity;
|
||||||
{
|
{
|
||||||
frame->ui_to_draw_xf = InvertXform(frame->draw_to_ui_xf);
|
frame->xf.ui_to_draw = InvertXform(frame->xf.draw_to_ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
// World <-> draw
|
// World <-> draw
|
||||||
frame->world_to_draw_xf = XformIdentity;
|
frame->xf.world_to_draw = XformIdentity;
|
||||||
frame->draw_to_world_xf = XformIdentity;
|
frame->xf.draw_to_world = XformIdentity;
|
||||||
{
|
{
|
||||||
frame->world_to_draw_xf = MulXform(frame->world_to_ui_xf, frame->ui_to_draw_xf);
|
frame->xf.world_to_draw = MulXform(frame->xf.world_to_ui, frame->xf.ui_to_draw);
|
||||||
frame->draw_to_world_xf = InvertXform(frame->world_to_draw_xf);
|
frame->xf.draw_to_world = InvertXform(frame->xf.world_to_draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// World <-> decal
|
||||||
|
// TODO: This can be constant (so shaders don't need to read it every frame)
|
||||||
|
frame->xf.world_to_decal = XformIdentity;
|
||||||
|
frame->xf.decal_to_world = XformIdentity;
|
||||||
|
{
|
||||||
|
frame->xf.world_to_decal = ScaleXform(frame->xf.world_to_decal, VEC2(V_PixelsPerMeter, V_PixelsPerMeter));
|
||||||
|
frame->xf.world_to_decal = TranslateXform(frame->xf.world_to_decal, VEC2((S_WorldPitch / 2.0), (S_WorldPitch / 2.0)));
|
||||||
|
frame->xf.decal_to_world = InvertXform(frame->xf.world_to_decal);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Update cursors / selection
|
//- Update cursors / selection
|
||||||
|
|
||||||
frame->ui_cursor = ui_frame->cursor_pos;
|
frame->ui_cursor = ui_frame->cursor_pos;
|
||||||
frame->draw_cursor = MulXformV2(frame->ui_to_draw_xf, frame->ui_cursor);
|
frame->draw_cursor = MulXformV2(frame->xf.ui_to_draw, frame->ui_cursor);
|
||||||
frame->world_cursor = MulXformV2(frame->ui_to_world_xf, frame->ui_cursor);
|
frame->world_cursor = MulXformV2(frame->xf.ui_to_world, frame->ui_cursor);
|
||||||
|
|
||||||
frame->world_selection_start = frame->world_cursor;
|
frame->world_selection_start = frame->world_cursor;
|
||||||
if (frame->is_editing)
|
if (frame->is_editing)
|
||||||
@ -870,11 +921,11 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->world_selection.p1.x = MaxF32(frame->world_cursor.x, frame->world_selection_start.x);
|
frame->world_selection.p1.x = MaxF32(frame->world_cursor.x, frame->world_selection_start.x);
|
||||||
frame->world_selection.p1.y = MaxF32(frame->world_cursor.y, frame->world_selection_start.y);
|
frame->world_selection.p1.y = MaxF32(frame->world_cursor.y, frame->world_selection_start.y);
|
||||||
|
|
||||||
frame->ui_selection.p0 = MulXformV2(frame->world_to_ui_xf, frame->world_selection.p0);
|
frame->ui_selection.p0 = MulXformV2(frame->xf.world_to_ui, frame->world_selection.p0);
|
||||||
frame->ui_selection.p1 = MulXformV2(frame->world_to_ui_xf, frame->world_selection.p1);
|
frame->ui_selection.p1 = MulXformV2(frame->xf.world_to_ui, frame->world_selection.p1);
|
||||||
|
|
||||||
frame->draw_selection.p0 = MulXformV2(frame->world_to_draw_xf, frame->world_selection.p0);
|
frame->draw_selection.p0 = MulXformV2(frame->xf.world_to_draw, frame->world_selection.p0);
|
||||||
frame->draw_selection.p1 = MulXformV2(frame->world_to_draw_xf, frame->world_selection.p1);
|
frame->draw_selection.p1 = MulXformV2(frame->xf.world_to_draw, frame->world_selection.p1);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Place tiles
|
//- Place tiles
|
||||||
@ -2111,12 +2162,14 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
||||||
Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor);
|
Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor);
|
||||||
|
Vec2 decal_pos = MulXformV2(frame->xf.world_to_decal, frame->world_cursor);
|
||||||
i32 tile_idx = S_TileIdxFromTilePos(tile_pos);
|
i32 tile_idx = S_TileIdxFromTilePos(tile_pos);
|
||||||
{
|
{
|
||||||
UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos));
|
UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos));
|
||||||
UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor));
|
UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor));
|
||||||
UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos));
|
UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos));
|
||||||
UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx));
|
UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx));
|
||||||
|
UI_BuildLabelF("Cursor decal pos: %F", FmtFloat2(decal_pos));
|
||||||
UI_BuildLabelF("Hovered ent: %F", S_FmtKey(hovered_ent->key));
|
UI_BuildLabelF("Hovered ent: %F", S_FmtKey(hovered_ent->key));
|
||||||
}
|
}
|
||||||
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
|
||||||
@ -2498,11 +2551,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Draw entities
|
//- Draw entities
|
||||||
|
|
||||||
// Build shape buffers
|
|
||||||
for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent))
|
for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent))
|
||||||
{
|
{
|
||||||
Xform ent_to_world_xf = ent->xf;
|
Xform ent_to_world_xf = ent->xf;
|
||||||
Xform ent_to_draw_xf = MulXform(frame->world_to_draw_xf, ent_to_world_xf);
|
Xform ent_to_draw_xf = MulXform(frame->xf.world_to_draw, ent_to_world_xf);
|
||||||
S_Shape draw_shape = S_MulXformShape(ent_to_draw_xf, ent->local_shape);
|
S_Shape draw_shape = S_MulXformShape(ent_to_draw_xf, ent->local_shape);
|
||||||
|
|
||||||
f32 opacity = 0.5;
|
f32 opacity = 0.5;
|
||||||
@ -2561,7 +2613,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
case S_DebugDrawKind_Point:
|
case S_DebugDrawKind_Point:
|
||||||
{
|
{
|
||||||
Vec2 ui_p = MulXformV2(frame->world_to_ui_xf, desc->point.p);
|
Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, desc->point.p);
|
||||||
S_Shape ui_shape = S_ShapeFromDesc(
|
S_Shape ui_shape = S_ShapeFromDesc(
|
||||||
.count = 1,
|
.count = 1,
|
||||||
.points = { ui_p },
|
.points = { ui_p },
|
||||||
@ -2572,27 +2624,68 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
case S_DebugDrawKind_Line:
|
case S_DebugDrawKind_Line:
|
||||||
{
|
{
|
||||||
Vec2 ui_p0 = MulXformV2(frame->world_to_ui_xf, desc->line.p0);
|
Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, desc->line.p0);
|
||||||
Vec2 ui_p1 = MulXformV2(frame->world_to_ui_xf, desc->line.p1);
|
Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, desc->line.p1);
|
||||||
V_DrawLine(ui_p0, ui_p1, color);
|
V_DrawLine(ui_p0, ui_p1, color);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case S_DebugDrawKind_Rect:
|
case S_DebugDrawKind_Rect:
|
||||||
{
|
{
|
||||||
Rng2 ui_rect = Zi;
|
Rng2 ui_rect = Zi;
|
||||||
ui_rect.p0 = MulXformV2(frame->world_to_ui_xf, desc->rect.p0);
|
ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, desc->rect.p0);
|
||||||
ui_rect.p1 = MulXformV2(frame->world_to_ui_xf, desc->rect.p1);
|
ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, desc->rect.p1);
|
||||||
V_DrawRect(ui_rect, color, V_DrawFlag_Line);
|
V_DrawRect(ui_rect, color, V_DrawFlag_Line);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case S_DebugDrawKind_Shape:
|
case S_DebugDrawKind_Shape:
|
||||||
{
|
{
|
||||||
S_Shape ui_shape = S_MulXformShape(frame->world_to_ui_xf, desc->shape);
|
S_Shape ui_shape = S_MulXformShape(frame->xf.world_to_ui, desc->shape);
|
||||||
V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
|
V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Build emitters
|
||||||
|
|
||||||
|
i64 emitters_count = 0;
|
||||||
|
V_EmitterNode *first_emitter_node = 0;
|
||||||
|
V_EmitterNode *last_emitter_node = 0;
|
||||||
|
|
||||||
|
// Spawn test emitters
|
||||||
|
{
|
||||||
|
V_Emitter *emitter = 0;
|
||||||
|
{
|
||||||
|
V_EmitterNode *en = PushStruct(frame->arena, V_EmitterNode);
|
||||||
|
SllQueuePush(first_emitter_node, last_emitter_node, en);
|
||||||
|
emitters_count += 1;
|
||||||
|
emitter = &en->emitter;
|
||||||
|
}
|
||||||
|
emitter->particle_kind = V_ParticleKind_Test;
|
||||||
|
|
||||||
|
Vec2 dir = VEC2(0, 1);
|
||||||
|
emitter->pos = frame->world_cursor;
|
||||||
|
emitter->angle = AngleFromVec2(dir);
|
||||||
|
|
||||||
|
emitter->count = 1000;
|
||||||
|
emitter->speed = 4;
|
||||||
|
|
||||||
|
emitter->seed = RandU64FromState(&frame->rand);
|
||||||
|
emitter->speed_spread = 1;
|
||||||
|
emitter->angle_spread = Tau;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten emitters list
|
||||||
|
V_Emitter *flattened_emitters = PushStructsNoZero(frame->arena, V_Emitter, emitters_count);
|
||||||
|
{
|
||||||
|
i64 emitter_idx = 0;
|
||||||
|
for (V_EmitterNode *en = first_emitter_node; en; en = en->next)
|
||||||
|
{
|
||||||
|
flattened_emitters[emitter_idx] = en->emitter;
|
||||||
|
++emitter_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Push data to GPU
|
//- Push data to GPU
|
||||||
|
|
||||||
@ -2615,15 +2708,20 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
G_StructuredBufferRef dverts_ro = G_PushStructuredBufferRef(frame->gpu_arena, dverts_buff, V_DVert);
|
G_StructuredBufferRef dverts_ro = G_PushStructuredBufferRef(frame->gpu_arena, dverts_buff, V_DVert);
|
||||||
G_IndexBufferDesc dvert_idxs_ib = G_IdxBuff32(dvert_idxs_buff);
|
G_IndexBufferDesc dvert_idxs_ib = G_IdxBuff32(dvert_idxs_buff);
|
||||||
|
|
||||||
|
// Emitters
|
||||||
|
G_ResourceHandle gpu_emitters = G_PushBufferFromString(frame->gpu_arena, frame->cl, StringFromStructs(flattened_emitters, emitters_count));
|
||||||
|
G_StructuredBufferRef gpu_emitters_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_emitters, V_Emitter);
|
||||||
|
|
||||||
// Params
|
// Params
|
||||||
V_DParams params = Zi;
|
V_GpuParams params = Zi;
|
||||||
{
|
{
|
||||||
|
params.dt = frame->dt;
|
||||||
params.target_size = frame->draw_dims;
|
params.target_size = frame->draw_dims;
|
||||||
params.target_ro = draw_target_ro;
|
params.target_ro = draw_target_ro;
|
||||||
params.target_rw = draw_target_rw;
|
params.target_rw = draw_target_rw;
|
||||||
|
params.xf = frame->xf;
|
||||||
params.world_to_draw_xf = frame->world_to_draw_xf;
|
params.seed = RandU64FromState(&frame->rand);
|
||||||
params.draw_to_world_xf = frame->draw_to_world_xf;
|
params.noise = G_BasicNoiseTexture();
|
||||||
|
|
||||||
params.selection_mode = frame->selection_mode;
|
params.selection_mode = frame->selection_mode;
|
||||||
params.equipped_tile = frame->equipped_tile;
|
params.equipped_tile = frame->equipped_tile;
|
||||||
@ -2642,12 +2740,21 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
params.tiles = gpu_tiles_ref;
|
params.tiles = gpu_tiles_ref;
|
||||||
params.shape_verts = dverts_ro;
|
params.shape_verts = dverts_ro;
|
||||||
|
|
||||||
|
params.emitters_count = emitters_count;
|
||||||
|
params.emitters = gpu_emitters_ref;
|
||||||
|
|
||||||
|
params.max_particles = max_particles;
|
||||||
|
params.particles = gpu_particles_ref;
|
||||||
|
|
||||||
|
params.decals = gpu_decals_ref;
|
||||||
}
|
}
|
||||||
G_ResourceHandle params_buff = G_PushBufferFromString(frame->gpu_arena, frame->cl, StringFromStruct(¶ms));
|
G_ResourceHandle gpu_params = G_PushBufferFromString(frame->gpu_arena, frame->cl, StringFromStruct(¶ms));
|
||||||
G_StructuredBufferRef params_ro = G_PushStructuredBufferRef(frame->gpu_arena, params_buff, V_DParams);
|
G_StructuredBufferRef gpu_params_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_params, V_GpuParams);
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
G_SetConstant(frame->cl, V_ShaderConst_Params, params_ro);
|
G_SetConstant(frame->cl, V_ShaderConst_State, gpu_state_ref);
|
||||||
|
G_SetConstant(frame->cl, V_ShaderConst_Params, gpu_params_ref);
|
||||||
|
|
||||||
// Sync
|
// Sync
|
||||||
G_DumbGlobalMemorySync(frame->cl);
|
G_DumbGlobalMemorySync(frame->cl);
|
||||||
@ -2696,6 +2803,19 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Particle simulation pass
|
||||||
|
|
||||||
|
{
|
||||||
|
// Emit particles
|
||||||
|
G_Compute(frame->cl, V_EmitParticlesCS, VEC3I32((emitters_count + 63) / 64, 1, 1));
|
||||||
|
|
||||||
|
G_DumbMemorySync(frame->cl, gpu_particles);
|
||||||
|
|
||||||
|
// Simulate particles
|
||||||
|
G_Compute(frame->cl, V_SimParticlesCS, VEC3I32((max_particles + 63) / 64, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Finalize draw target
|
//- Finalize draw target
|
||||||
|
|
||||||
|
|||||||
@ -213,6 +213,7 @@ Struct(V_Frame)
|
|||||||
i64 time_ns;
|
i64 time_ns;
|
||||||
i64 dt_ns;
|
i64 dt_ns;
|
||||||
f64 dt;
|
f64 dt;
|
||||||
|
RandState rand;
|
||||||
|
|
||||||
Button held_buttons[Button_COUNT];
|
Button held_buttons[Button_COUNT];
|
||||||
V_Palette palette;
|
V_Palette palette;
|
||||||
@ -245,17 +246,8 @@ Struct(V_Frame)
|
|||||||
Vec2 camera_pos;
|
Vec2 camera_pos;
|
||||||
f32 camera_zoom;
|
f32 camera_zoom;
|
||||||
|
|
||||||
// World <-> ui
|
// Xforms;
|
||||||
Xform world_to_ui_xf;
|
V_Xforms xf;
|
||||||
Xform ui_to_world_xf;
|
|
||||||
|
|
||||||
// Draw <-> ui
|
|
||||||
Xform draw_to_ui_xf;
|
|
||||||
Xform ui_to_draw_xf;
|
|
||||||
|
|
||||||
// World <-> draw
|
|
||||||
Xform world_to_draw_xf;
|
|
||||||
Xform draw_to_world_xf;
|
|
||||||
|
|
||||||
// Cursors
|
// Cursors
|
||||||
Vec2 ui_cursor;
|
Vec2 ui_cursor;
|
||||||
|
|||||||
428
src/pp/pp_vis/pp_vis_gpu.g
Normal file
428
src/pp/pp_vis/pp_vis_gpu.g
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Backdrop shader
|
||||||
|
|
||||||
|
ComputeShader2D(V_BackdropCS, 8, 8)
|
||||||
|
{
|
||||||
|
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
||||||
|
Texture2D<S_TileKind> tiles = G_Dereference<S_TileKind>(params.tiles);
|
||||||
|
|
||||||
|
const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1));
|
||||||
|
const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1));
|
||||||
|
const Vec4 grid_color = LinearFromSrgb(Vec4(0, 0, 0, 1));
|
||||||
|
const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1));
|
||||||
|
const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1));
|
||||||
|
const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1));
|
||||||
|
|
||||||
|
Vec2 ui_pos = SV_DispatchThreadID + Vec2(0.5, 0.5);
|
||||||
|
if (ui_pos.x < params.target_size.x && ui_pos.y < params.target_size.y)
|
||||||
|
{
|
||||||
|
Vec4 result = Vec4(0.025, 0.025, 0.025, 1);
|
||||||
|
Vec2 world_pos = mul(params.xf.ui_to_world, Vec3(ui_pos, 1));
|
||||||
|
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
||||||
|
|
||||||
|
f32 half_thickness = 1;
|
||||||
|
f32 half_bounds_size = S_WorldPitch * 0.5;
|
||||||
|
Vec2 bounds_screen_p0 = mul(params.xf.world_to_draw, Vec3(-half_bounds_size, -half_bounds_size, 1));
|
||||||
|
Vec2 bounds_screen_p1 = mul(params.xf.world_to_draw, Vec3(half_bounds_size, half_bounds_size, 1));
|
||||||
|
bool is_in_bounds = ui_pos.x > (bounds_screen_p0.x - half_thickness) &&
|
||||||
|
ui_pos.y > (bounds_screen_p0.y - half_thickness) &&
|
||||||
|
ui_pos.x < (bounds_screen_p1.x + half_thickness) &&
|
||||||
|
ui_pos.y < (bounds_screen_p1.y + half_thickness);
|
||||||
|
if (is_in_bounds)
|
||||||
|
{
|
||||||
|
// Grid checker
|
||||||
|
{
|
||||||
|
i32 color_idx = 0;
|
||||||
|
Vec4 colors[2] = {
|
||||||
|
background_color_a,
|
||||||
|
background_color_b
|
||||||
|
};
|
||||||
|
const f32 checker_size = 0.5;
|
||||||
|
Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2));
|
||||||
|
if (world_pos_modded.x < checker_size)
|
||||||
|
{
|
||||||
|
color_idx = !color_idx;
|
||||||
|
}
|
||||||
|
if (world_pos_modded.y < checker_size)
|
||||||
|
{
|
||||||
|
color_idx = !color_idx;
|
||||||
|
}
|
||||||
|
if (world_pos.x < 0)
|
||||||
|
{
|
||||||
|
color_idx = !color_idx;
|
||||||
|
}
|
||||||
|
if (world_pos.y < 0)
|
||||||
|
{
|
||||||
|
color_idx = !color_idx;
|
||||||
|
}
|
||||||
|
result = colors[color_idx];
|
||||||
|
}
|
||||||
|
// Grid outline
|
||||||
|
{
|
||||||
|
Vec2 grid_screen_p0 = mul(params.xf.world_to_draw, Vec3(floor(world_pos), 1));
|
||||||
|
Vec2 grid_screen_p1 = mul(params.xf.world_to_draw, Vec3(ceil(world_pos), 1));
|
||||||
|
f32 grid_dist = 100000;
|
||||||
|
grid_dist = min(grid_dist, abs(ui_pos.x - grid_screen_p0.x));
|
||||||
|
grid_dist = min(grid_dist, abs(ui_pos.x - grid_screen_p1.x));
|
||||||
|
grid_dist = min(grid_dist, abs(ui_pos.y - grid_screen_p0.y));
|
||||||
|
grid_dist = min(grid_dist, abs(ui_pos.y - grid_screen_p1.y));
|
||||||
|
if (grid_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = grid_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Tile
|
||||||
|
{
|
||||||
|
S_TileKind tile = tiles.Load(Vec3I32(tile_pos, 0));
|
||||||
|
switch (tile)
|
||||||
|
{
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case S_TileKind_Floor:
|
||||||
|
{
|
||||||
|
result = Color_Blue;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case S_TileKind_Wall:
|
||||||
|
{
|
||||||
|
result = Color_Red;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Axis
|
||||||
|
{
|
||||||
|
Vec2 zero_screen = mul(params.xf.world_to_draw, Vec3(0, 0, 1));
|
||||||
|
f32 x_dist = abs(ui_pos.x - zero_screen.x);
|
||||||
|
f32 y_dist = abs(ui_pos.y - zero_screen.y);
|
||||||
|
if (y_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = x_axis_color;
|
||||||
|
}
|
||||||
|
else if (x_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = y_axis_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// World bounds
|
||||||
|
{
|
||||||
|
f32 bounds_dist = 100000;
|
||||||
|
bounds_dist = min(bounds_dist, abs(ui_pos.x - bounds_screen_p0.x));
|
||||||
|
bounds_dist = min(bounds_dist, abs(ui_pos.x - bounds_screen_p1.x));
|
||||||
|
bounds_dist = min(bounds_dist, abs(ui_pos.y - bounds_screen_p0.y));
|
||||||
|
bounds_dist = min(bounds_dist, abs(ui_pos.y - bounds_screen_p1.y));
|
||||||
|
if (bounds_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = bounds_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target[SV_DispatchThreadID] = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Quad shader
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Vertex shader
|
||||||
|
|
||||||
|
VertexShader(V_DQuadVS, V_DQuadPSInput)
|
||||||
|
{
|
||||||
|
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
||||||
|
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
||||||
|
|
||||||
|
V_DQuad quad = quads[SV_InstanceID];
|
||||||
|
|
||||||
|
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID);
|
||||||
|
// Vec2 tex_uv = lerp(quad.tex_uv0, quad.tex_uv1, rect_uv);
|
||||||
|
// Vec2 target_pos = lerp(quad.p0, quad.p1, rect_uv);
|
||||||
|
Vec2 target_pos = 0;
|
||||||
|
|
||||||
|
V_DQuadPSInput result;
|
||||||
|
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
||||||
|
result.quad_idx = SV_InstanceID;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Pixel shader
|
||||||
|
|
||||||
|
PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input)
|
||||||
|
{
|
||||||
|
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
||||||
|
V_DQuad quad = quads[input.quad_idx];
|
||||||
|
|
||||||
|
Vec4 final_color = 0;
|
||||||
|
|
||||||
|
V_DQuadPSOutput output;
|
||||||
|
output.sv_target0 = final_color;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Particle simulation shaders
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Particle emitter shader
|
||||||
|
|
||||||
|
// TODO: Initialize particles in per-particle-sim-thread rather than sequentially in emitter thread
|
||||||
|
|
||||||
|
ComputeShader(V_EmitParticlesCS, 64)
|
||||||
|
{
|
||||||
|
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
RWStructuredBuffer<V_GpuState> state_buff = G_Dereference<V_GpuState>(V_ShaderConst_State);
|
||||||
|
StructuredBuffer<V_Emitter> emitters = G_Dereference<V_Emitter>(params.emitters);
|
||||||
|
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
|
||||||
|
|
||||||
|
u32 emitter_idx = SV_DispatchThreadID;
|
||||||
|
if (emitter_idx < params.emitters_count)
|
||||||
|
{
|
||||||
|
V_Emitter emitter = emitters[emitter_idx];
|
||||||
|
|
||||||
|
u32 first_particle_seq;
|
||||||
|
InterlockedAdd(state_buff[0].particle_seq, emitter.count, first_particle_seq);
|
||||||
|
u32 last_particle_seq = first_particle_seq + emitter.count;
|
||||||
|
|
||||||
|
u32 particles_created_count = 0;
|
||||||
|
for (u32 particle_seq = first_particle_seq; particle_seq < last_particle_seq; ++particle_seq)
|
||||||
|
{
|
||||||
|
u32 particle_idx = particle_seq % params.max_particles;
|
||||||
|
particles[particle_idx].kind = emitter.particle_kind;
|
||||||
|
particles[particle_idx].emitter_init_num = emitter_idx + 1;
|
||||||
|
particles[particle_idx].idx_in_emitter = particles_created_count;
|
||||||
|
particles_created_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
// RWStructuredBuffer<V_GpuState> state_buff = G_Dereference<V_GpuState>(V_ShaderConst_State);
|
||||||
|
// StructuredBuffer<V_Emitter> emitters = G_Dereference<V_Emitter>(params.emitters);
|
||||||
|
// RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
|
||||||
|
// Texture3D<u32> noise3d = G_Dereference<u32>(params.noise);
|
||||||
|
|
||||||
|
// u32 emitter_idx = SV_DispatchThreadID;
|
||||||
|
// if (emitter_idx < params.emitters_count)
|
||||||
|
// {
|
||||||
|
// V_Emitter emitter = emitters[emitter_idx];
|
||||||
|
|
||||||
|
// u32 first_particle_seq;
|
||||||
|
// InterlockedAdd(state_buff[0].particle_seq, emitter.count, first_particle_seq);
|
||||||
|
// u32 last_particle_seq = first_particle_seq + emitter.count;
|
||||||
|
|
||||||
|
// Vec2U32 speed_noise_coord;
|
||||||
|
// Vec2U32 angle_noise_coord;
|
||||||
|
// {
|
||||||
|
// speed_noise_coord.x = ((emitter.speed_seed >> 0) & 0xFFFF) % countof(noise3d).x;
|
||||||
|
// speed_noise_coord.y = ((emitter.speed_seed >> 16) & 0xFFFF) % countof(noise3d).y;
|
||||||
|
// angle_noise_coord.x = ((emitter.angle_seed >> 0) & 0xFFFF) % countof(noise3d).x;
|
||||||
|
// angle_noise_coord.y = ((emitter.angle_seed >> 16) & 0xFFFF) % countof(noise3d).y;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// u64 base_seed =
|
||||||
|
// for (u32 particle_seq = first_particle_seq; particle_seq < last_particle_seq; ++particle_seq)
|
||||||
|
// {
|
||||||
|
// V_Particle particle;
|
||||||
|
// {
|
||||||
|
// u32 speed_noise = noise3d.Load(Vec4U32(speed_noise_coord.xy, particle_seq % countof(noise3d).z, 0));
|
||||||
|
// u32 angle_noise = noise3d.Load(Vec4U32(angle_noise_coord.xy, particle_seq % countof(noise3d).z, 0));
|
||||||
|
// f32 speed_rand = speed_noise / (f32)0xFFFF;
|
||||||
|
// f32 angle_rand = angle_noise / (f32)0xFFFF;
|
||||||
|
// f32 speed = emitter.speed + ((speed_rand * 2 - 1) * emitter.speed_spread);
|
||||||
|
// f32 angle = emitter.angle + ((angle_rand * 2 - 1) * emitter.angle_spread);
|
||||||
|
|
||||||
|
// particle.kind = emitter.particle_kind;
|
||||||
|
// particle.pos = emitter.pos;
|
||||||
|
// particle.velocity = Vec2(cos(angle), sin(angle)) * speed;
|
||||||
|
// }
|
||||||
|
// particles[particle_seq % params.max_particles] = particle;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Particle sim shader
|
||||||
|
|
||||||
|
ComputeShader(V_SimParticlesCS, 64)
|
||||||
|
{
|
||||||
|
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
|
||||||
|
RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
|
||||||
|
|
||||||
|
u32 particle_idx = SV_DispatchThreadID;
|
||||||
|
if (particle_idx < params.max_particles)
|
||||||
|
{
|
||||||
|
V_Particle particle = particles[particle_idx];
|
||||||
|
if (particle.kind != V_ParticleKind_None)
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
if (particle.emitter_init_num != 0)
|
||||||
|
{
|
||||||
|
V_Emitter emitter = G_Dereference<V_Emitter>(params.emitters)[particle.emitter_init_num - 1];
|
||||||
|
|
||||||
|
// TODO: Faster mix
|
||||||
|
u64 seed = MixU64(emitter.seed + particle.idx_in_emitter);
|
||||||
|
|
||||||
|
// TODO: Blue noise
|
||||||
|
u32 speed_noise = ((u32)seed >> 0) & 0xFFFF;
|
||||||
|
u32 angle_noise = ((u32)seed >> 16) & 0xFFFF;
|
||||||
|
f32 speed_rand = speed_noise / (f32)0xFFFF;
|
||||||
|
f32 angle_rand = angle_noise / (f32)0xFFFF;
|
||||||
|
|
||||||
|
f32 speed = emitter.speed + ((speed_rand * 2 - 1) * emitter.speed_spread);
|
||||||
|
f32 angle = emitter.angle + ((angle_rand * 2 - 1) * emitter.angle_spread);
|
||||||
|
|
||||||
|
particle.pos = emitter.pos;
|
||||||
|
particle.velocity = Vec2(cos(angle), sin(angle)) * speed;
|
||||||
|
|
||||||
|
particle.emitter_init_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate
|
||||||
|
{
|
||||||
|
f32 dt = params.dt;
|
||||||
|
particle.pos += particle.velocity * dt;
|
||||||
|
|
||||||
|
Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(particle.pos, 1));
|
||||||
|
if (decal_pos.x >= 0 && decal_pos.y >= 0 && decal_pos.x < countof(decals).x && decal_pos.y < countof(decals).y)
|
||||||
|
{
|
||||||
|
// FIXME: Atomic write
|
||||||
|
decals[floor(decal_pos)] = particle.kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
particles[particle_idx] = particle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Shape shader
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Vertex shader
|
||||||
|
|
||||||
|
VertexShader(V_DVertVS, V_DVertPSInput)
|
||||||
|
{
|
||||||
|
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(params.shape_verts);
|
||||||
|
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
||||||
|
|
||||||
|
V_DVert vert = verts[SV_VertexID];
|
||||||
|
|
||||||
|
Vec2 target_pos = vert.pos;
|
||||||
|
|
||||||
|
V_DVertPSInput result;
|
||||||
|
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
||||||
|
result.color_lin = vert.color_lin;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Pixel shader
|
||||||
|
|
||||||
|
PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input)
|
||||||
|
{
|
||||||
|
V_DVertPSOutput output;
|
||||||
|
output.sv_target0 = input.color_lin;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Overlay shader
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Vertex shader
|
||||||
|
|
||||||
|
VertexShader(V_OverlayVS, V_OverlayPSInput)
|
||||||
|
{
|
||||||
|
Vec2 uv = RectUvFromVertexId(SV_VertexID);
|
||||||
|
V_OverlayPSInput result;
|
||||||
|
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Pixel shader
|
||||||
|
|
||||||
|
PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
|
||||||
|
{
|
||||||
|
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
|
||||||
|
Vec2 ui_pos = input.sv_position.xy;
|
||||||
|
Vec4 result = 0;
|
||||||
|
|
||||||
|
Vec2 world_pos = mul(params.xf.ui_to_world, Vec3(ui_pos, 1));
|
||||||
|
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
||||||
|
S_TileKind equipped_tile = params.equipped_tile;
|
||||||
|
|
||||||
|
f32 half_thickness = 1;
|
||||||
|
Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1));
|
||||||
|
// Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25));
|
||||||
|
|
||||||
|
Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6));
|
||||||
|
|
||||||
|
Rng2 screen_selection = params.draw_selection;
|
||||||
|
Rng2 world_selection = params.world_selection;
|
||||||
|
|
||||||
|
Rng2I32 tile_selection;
|
||||||
|
tile_selection.p0 = S_TilePosFromWorldPos(world_selection.p0);
|
||||||
|
tile_selection.p1 = S_TilePosFromWorldPos(world_selection.p1);
|
||||||
|
|
||||||
|
if (params.has_mouse_focus)
|
||||||
|
{
|
||||||
|
if (params.selection_mode == V_SelectionMode_Tile)
|
||||||
|
{
|
||||||
|
f32 dist = 100000000;
|
||||||
|
dist = min(dist, ui_pos.x - screen_selection.p0.x);
|
||||||
|
dist = min(dist, ui_pos.y - screen_selection.p0.y);
|
||||||
|
dist = min(dist, screen_selection.p1.x - ui_pos.x);
|
||||||
|
dist = min(dist, screen_selection.p1.y - ui_pos.y);
|
||||||
|
dist = -dist;
|
||||||
|
|
||||||
|
// if (dist >= -half_thickness && dist <= half_thickness)
|
||||||
|
// {
|
||||||
|
// result = border_color;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
world_pos.x > -(S_WorldPitch / 2) &&
|
||||||
|
world_pos.y > -(S_WorldPitch / 2) &&
|
||||||
|
world_pos.x < (S_WorldPitch / 2) &&
|
||||||
|
world_pos.y < (S_WorldPitch / 2) &&
|
||||||
|
tile_pos.x >= tile_selection.p0.x &&
|
||||||
|
tile_pos.x <= tile_selection.p1.x &&
|
||||||
|
tile_pos.y >= tile_selection.p0.y &&
|
||||||
|
tile_pos.y <= tile_selection.p1.y
|
||||||
|
)
|
||||||
|
{
|
||||||
|
result = inner_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove this
|
||||||
|
// Decals test
|
||||||
|
{
|
||||||
|
RWTexture2D<V_ParticleKind> decals = G_Dereference<V_ParticleKind>(params.decals);
|
||||||
|
Vec2 decal_pos = mul(params.xf.world_to_decal, Vec3(world_pos, 1));
|
||||||
|
// Vec2 decal_uv = decal_pos / countof(decals);
|
||||||
|
V_ParticleKind decal = decals.Load(floor(decal_pos));
|
||||||
|
|
||||||
|
if (decal == V_ParticleKind_Test)
|
||||||
|
{
|
||||||
|
result = Color_Yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
V_OverlayPSOutput output;
|
||||||
|
output.sv_target0 = result;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
@ -17,7 +17,6 @@ Struct(V_DQuadPSOutput)
|
|||||||
|
|
||||||
Struct(V_DVertPSInput)
|
Struct(V_DVertPSInput)
|
||||||
{
|
{
|
||||||
|
|
||||||
Semantic(Vec4, sv_position);
|
Semantic(Vec4, sv_position);
|
||||||
Semantic(Vec4, color_lin);
|
Semantic(Vec4, color_lin);
|
||||||
};
|
};
|
||||||
@ -44,17 +43,21 @@ Struct(V_OverlayPSOutput)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Shaders
|
//~ Shaders
|
||||||
|
|
||||||
//- Backdrop
|
//- Backdrop shader
|
||||||
ComputeShader2D(V_BackdropCS, 8, 8);
|
ComputeShader2D(V_BackdropCS, 8, 8);
|
||||||
|
|
||||||
//- Quad
|
//- Quad shader
|
||||||
VertexShader(V_DQuadVS, V_DQuadPSInput);
|
VertexShader(V_DQuadVS, V_DQuadPSInput);
|
||||||
PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input);
|
PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input);
|
||||||
|
|
||||||
//- Shape
|
//- Particle simulation shaders
|
||||||
|
ComputeShader(V_EmitParticlesCS, 64);
|
||||||
|
ComputeShader(V_SimParticlesCS, 64);
|
||||||
|
|
||||||
|
//- Shape shader
|
||||||
VertexShader(V_DVertVS, V_DVertPSInput);
|
VertexShader(V_DVertVS, V_DVertPSInput);
|
||||||
PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input);
|
PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input);
|
||||||
|
|
||||||
//- Overlay
|
//- Overlay shader
|
||||||
VertexShader(V_OverlayVS, V_OverlayPSInput);
|
VertexShader(V_OverlayVS, V_OverlayPSInput);
|
||||||
PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input);
|
PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input);
|
||||||
@ -1,67 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Constant types
|
|
||||||
|
|
||||||
G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 0);
|
|
||||||
|
|
||||||
Enum(V_SelectionMode)
|
|
||||||
{
|
|
||||||
V_SelectionMode_None,
|
|
||||||
V_SelectionMode_Tile,
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(V_DParams)
|
|
||||||
{
|
|
||||||
Vec2 target_size;
|
|
||||||
G_Texture2DRef target_ro;
|
|
||||||
G_RWTexture2DRef target_rw;
|
|
||||||
|
|
||||||
Xform world_to_draw_xf;
|
|
||||||
Xform draw_to_world_xf;
|
|
||||||
|
|
||||||
V_SelectionMode selection_mode;
|
|
||||||
S_TileKind equipped_tile;
|
|
||||||
|
|
||||||
b32 has_mouse_focus;
|
|
||||||
b32 has_keyboard_focus;
|
|
||||||
Vec2 ui_cursor;
|
|
||||||
Vec2 draw_cursor;
|
|
||||||
Vec2 world_cursor;
|
|
||||||
Rng2 ui_selection;
|
|
||||||
Rng2 draw_selection;
|
|
||||||
Rng2 world_selection;
|
|
||||||
|
|
||||||
Vec2 camera_pos;
|
|
||||||
f32 camera_zoom;
|
|
||||||
|
|
||||||
G_Texture2DRef tiles;
|
|
||||||
G_StructuredBufferRef quads;
|
|
||||||
G_StructuredBufferRef shape_verts;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Backdrop shader types
|
|
||||||
|
|
||||||
#define V_BackdropCSThreadSizeFromTexSize(tex_size) VEC3I32((tex_size.x + 7) / 8, (tex_size.y + 7) / 8, 1)
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Quad shader types
|
|
||||||
|
|
||||||
Enum(V_DQuadFlag)
|
|
||||||
{
|
|
||||||
V_DQuadFlag_None = 0,
|
|
||||||
V_DQuadFlag_DrawGrid = (1 << 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(V_DQuad)
|
|
||||||
{
|
|
||||||
V_DQuadFlag flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Shape shader types
|
|
||||||
|
|
||||||
Struct(V_DVert)
|
|
||||||
{
|
|
||||||
Vec2 pos;
|
|
||||||
Vec4 color_lin;
|
|
||||||
};
|
|
||||||
@ -1,276 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Backdrop shader
|
|
||||||
|
|
||||||
ComputeShader2D(V_BackdropCS, 8, 8)
|
|
||||||
{
|
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
|
||||||
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
|
||||||
Texture2D<uint> tiles = G_Dereference<uint>(params.tiles);
|
|
||||||
|
|
||||||
const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1));
|
|
||||||
const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1));
|
|
||||||
const Vec4 grid_color = LinearFromSrgb(Vec4(0, 0, 0, 1));
|
|
||||||
const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1));
|
|
||||||
const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1));
|
|
||||||
const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1));
|
|
||||||
|
|
||||||
Vec2 screen_pos = SV_DispatchThreadID + Vec2(0.5, 0.5);
|
|
||||||
if (screen_pos.x < params.target_size.x && screen_pos.y < params.target_size.y)
|
|
||||||
{
|
|
||||||
Vec4 result = Vec4(0.025, 0.025, 0.025, 1);
|
|
||||||
Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(screen_pos, 1));
|
|
||||||
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
|
||||||
|
|
||||||
f32 half_thickness = 1;
|
|
||||||
f32 half_bounds_size = S_WorldPitch * 0.5;
|
|
||||||
Vec2 bounds_screen_p0 = mul(params.world_to_draw_xf, Vec3(-half_bounds_size, -half_bounds_size, 1));
|
|
||||||
Vec2 bounds_screen_p1 = mul(params.world_to_draw_xf, Vec3(half_bounds_size, half_bounds_size, 1));
|
|
||||||
bool is_in_bounds = screen_pos.x > (bounds_screen_p0.x - half_thickness) &&
|
|
||||||
screen_pos.y > (bounds_screen_p0.y - half_thickness) &&
|
|
||||||
screen_pos.x < (bounds_screen_p1.x + half_thickness) &&
|
|
||||||
screen_pos.y < (bounds_screen_p1.y + half_thickness);
|
|
||||||
if (is_in_bounds)
|
|
||||||
{
|
|
||||||
// Grid checker
|
|
||||||
{
|
|
||||||
i32 color_idx = 0;
|
|
||||||
Vec4 colors[2] = {
|
|
||||||
background_color_a,
|
|
||||||
background_color_b
|
|
||||||
};
|
|
||||||
const f32 checker_size = 0.5;
|
|
||||||
Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2));
|
|
||||||
if (world_pos_modded.x < checker_size)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
if (world_pos_modded.y < checker_size)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
if (world_pos.x < 0)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
if (world_pos.y < 0)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
result = colors[color_idx];
|
|
||||||
}
|
|
||||||
// Grid outline
|
|
||||||
{
|
|
||||||
Vec2 grid_screen_p0 = mul(params.world_to_draw_xf, Vec3(floor(world_pos), 1));
|
|
||||||
Vec2 grid_screen_p1 = mul(params.world_to_draw_xf, Vec3(ceil(world_pos), 1));
|
|
||||||
f32 grid_dist = 100000;
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.x - grid_screen_p0.x));
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.x - grid_screen_p1.x));
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.y - grid_screen_p0.y));
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.y - grid_screen_p1.y));
|
|
||||||
if (grid_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = grid_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Tile
|
|
||||||
{
|
|
||||||
S_TileKind tile = (S_TileKind)tiles.Load(Vec3I32(tile_pos, 0));
|
|
||||||
switch (tile)
|
|
||||||
{
|
|
||||||
default: break;
|
|
||||||
|
|
||||||
case S_TileKind_Floor:
|
|
||||||
{
|
|
||||||
result = Color_Blue;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case S_TileKind_Wall:
|
|
||||||
{
|
|
||||||
result = Color_Red;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Axis
|
|
||||||
{
|
|
||||||
Vec2 zero_screen = mul(params.world_to_draw_xf, Vec3(0, 0, 1));
|
|
||||||
f32 x_dist = abs(screen_pos.x - zero_screen.x);
|
|
||||||
f32 y_dist = abs(screen_pos.y - zero_screen.y);
|
|
||||||
if (y_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = x_axis_color;
|
|
||||||
}
|
|
||||||
else if (x_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = y_axis_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// World bounds
|
|
||||||
{
|
|
||||||
f32 bounds_dist = 100000;
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.x - bounds_screen_p0.x));
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.x - bounds_screen_p1.x));
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.y - bounds_screen_p0.y));
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.y - bounds_screen_p1.y));
|
|
||||||
if (bounds_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = bounds_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
target[SV_DispatchThreadID] = result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Quad shader
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Vertex shader
|
|
||||||
|
|
||||||
VertexShader(V_DQuadVS, V_DQuadPSInput)
|
|
||||||
{
|
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
|
||||||
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
|
||||||
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
|
||||||
|
|
||||||
V_DQuad quad = quads[SV_InstanceID];
|
|
||||||
|
|
||||||
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID);
|
|
||||||
// Vec2 tex_uv = lerp(quad.tex_uv0, quad.tex_uv1, rect_uv);
|
|
||||||
// Vec2 target_pos = lerp(quad.p0, quad.p1, rect_uv);
|
|
||||||
Vec2 target_pos = 0;
|
|
||||||
|
|
||||||
V_DQuadPSInput result;
|
|
||||||
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
|
||||||
result.quad_idx = SV_InstanceID;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Pixel shader
|
|
||||||
|
|
||||||
PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input)
|
|
||||||
{
|
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
|
||||||
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
|
||||||
V_DQuad quad = quads[input.quad_idx];
|
|
||||||
|
|
||||||
Vec4 final_color = 0;
|
|
||||||
|
|
||||||
V_DQuadPSOutput output;
|
|
||||||
output.sv_target0 = final_color;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Shape shader
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Vertex shader
|
|
||||||
|
|
||||||
VertexShader(V_DVertVS, V_DVertPSInput)
|
|
||||||
{
|
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
|
||||||
StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(params.shape_verts);
|
|
||||||
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
|
||||||
|
|
||||||
V_DVert vert = verts[SV_VertexID];
|
|
||||||
|
|
||||||
Vec2 target_pos = vert.pos;
|
|
||||||
|
|
||||||
V_DVertPSInput result;
|
|
||||||
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
|
||||||
result.color_lin = vert.color_lin;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Pixel shader
|
|
||||||
|
|
||||||
PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input)
|
|
||||||
{
|
|
||||||
V_DVertPSOutput output;
|
|
||||||
output.sv_target0 = input.color_lin;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Overlay shader
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Vertex shader
|
|
||||||
|
|
||||||
VertexShader(V_OverlayVS, V_OverlayPSInput)
|
|
||||||
{
|
|
||||||
Vec2 uv = RectUvFromVertexId(SV_VertexID);
|
|
||||||
V_OverlayPSInput result;
|
|
||||||
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Pixel shader
|
|
||||||
|
|
||||||
PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
|
|
||||||
{
|
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
|
||||||
Texture2D<uint> tiles = G_Dereference<uint>(params.tiles);
|
|
||||||
Vec2 screen_pos = input.sv_position.xy;
|
|
||||||
Vec4 result = 0;
|
|
||||||
|
|
||||||
Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(screen_pos, 1));
|
|
||||||
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
|
||||||
S_TileKind equipped_tile = params.equipped_tile;
|
|
||||||
|
|
||||||
f32 half_thickness = 1;
|
|
||||||
Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1));
|
|
||||||
// Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25));
|
|
||||||
|
|
||||||
Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6));
|
|
||||||
|
|
||||||
Rng2 screen_selection = params.draw_selection;
|
|
||||||
Rng2 world_selection = params.world_selection;
|
|
||||||
|
|
||||||
Rng2I32 tile_selection;
|
|
||||||
tile_selection.p0 = S_TilePosFromWorldPos(world_selection.p0);
|
|
||||||
tile_selection.p1 = S_TilePosFromWorldPos(world_selection.p1);
|
|
||||||
|
|
||||||
if (params.has_mouse_focus)
|
|
||||||
{
|
|
||||||
if (params.selection_mode == V_SelectionMode_Tile)
|
|
||||||
{
|
|
||||||
f32 dist = 100000000;
|
|
||||||
dist = min(dist, screen_pos.x - screen_selection.p0.x);
|
|
||||||
dist = min(dist, screen_pos.y - screen_selection.p0.y);
|
|
||||||
dist = min(dist, screen_selection.p1.x - screen_pos.x);
|
|
||||||
dist = min(dist, screen_selection.p1.y - screen_pos.y);
|
|
||||||
dist = -dist;
|
|
||||||
|
|
||||||
// if (dist >= -half_thickness && dist <= half_thickness)
|
|
||||||
// {
|
|
||||||
// result = border_color;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
{
|
|
||||||
if (
|
|
||||||
world_pos.x > -(S_WorldPitch / 2) &&
|
|
||||||
world_pos.y > -(S_WorldPitch / 2) &&
|
|
||||||
world_pos.x < (S_WorldPitch / 2) &&
|
|
||||||
world_pos.y < (S_WorldPitch / 2) &&
|
|
||||||
tile_pos.x >= tile_selection.p0.x &&
|
|
||||||
tile_pos.x <= tile_selection.p1.x &&
|
|
||||||
tile_pos.y >= tile_selection.p0.y &&
|
|
||||||
tile_pos.y <= tile_selection.p1.y
|
|
||||||
)
|
|
||||||
{
|
|
||||||
result = inner_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
V_OverlayPSOutput output;
|
|
||||||
output.sv_target0 = result;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
146
src/pp/pp_vis/pp_vis_shared.cgh
Normal file
146
src/pp/pp_vis/pp_vis_shared.cgh
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#define V_PixelsPerMeter 48.0
|
||||||
|
#define V_PixelsPerSqMeter (V_PixelsPerMeter * V_PixelsPerMeter)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Constant types
|
||||||
|
|
||||||
|
G_DeclConstant(G_RWStructuredBufferRef, V_ShaderConst_State, 0);
|
||||||
|
G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 1);
|
||||||
|
|
||||||
|
Enum(V_SelectionMode)
|
||||||
|
{
|
||||||
|
V_SelectionMode_None,
|
||||||
|
V_SelectionMode_Tile,
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_Xforms)
|
||||||
|
{
|
||||||
|
// World <-> ui
|
||||||
|
Xform world_to_ui;
|
||||||
|
Xform ui_to_world;
|
||||||
|
|
||||||
|
// Draw <-> ui
|
||||||
|
Xform draw_to_ui;
|
||||||
|
Xform ui_to_draw;
|
||||||
|
|
||||||
|
// World <-> draw
|
||||||
|
Xform world_to_draw;
|
||||||
|
Xform draw_to_world;
|
||||||
|
|
||||||
|
// World <-> decal
|
||||||
|
Xform world_to_decal;
|
||||||
|
Xform decal_to_world;
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_GpuState)
|
||||||
|
{
|
||||||
|
u32 particle_seq; // Atomic monotonically increasing allocation counter sequence for particle ring buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_GpuParams)
|
||||||
|
{
|
||||||
|
f32 dt;
|
||||||
|
Vec2 target_size;
|
||||||
|
G_Texture2DRef target_ro;
|
||||||
|
G_RWTexture2DRef target_rw;
|
||||||
|
V_Xforms xf;
|
||||||
|
|
||||||
|
u64 seed;
|
||||||
|
G_Texture3DRef noise;
|
||||||
|
|
||||||
|
V_SelectionMode selection_mode;
|
||||||
|
S_TileKind equipped_tile;
|
||||||
|
|
||||||
|
b32 has_mouse_focus;
|
||||||
|
b32 has_keyboard_focus;
|
||||||
|
Vec2 ui_cursor;
|
||||||
|
Vec2 draw_cursor;
|
||||||
|
Vec2 world_cursor;
|
||||||
|
Rng2 ui_selection;
|
||||||
|
Rng2 draw_selection;
|
||||||
|
Rng2 world_selection;
|
||||||
|
|
||||||
|
Vec2 camera_pos;
|
||||||
|
f32 camera_zoom;
|
||||||
|
|
||||||
|
G_Texture2DRef tiles;
|
||||||
|
G_StructuredBufferRef quads;
|
||||||
|
G_StructuredBufferRef shape_verts;
|
||||||
|
|
||||||
|
u32 emitters_count;
|
||||||
|
G_StructuredBufferRef emitters;
|
||||||
|
|
||||||
|
u32 max_particles;
|
||||||
|
G_RWStructuredBufferRef particles;
|
||||||
|
G_RWTexture2DRef decals;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Particle types
|
||||||
|
|
||||||
|
Enum(V_ParticleKind)
|
||||||
|
{
|
||||||
|
V_ParticleKind_None,
|
||||||
|
V_ParticleKind_Test
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_Emitter)
|
||||||
|
{
|
||||||
|
V_ParticleKind particle_kind;
|
||||||
|
|
||||||
|
Vec2 pos;
|
||||||
|
f32 angle;
|
||||||
|
u32 count;
|
||||||
|
f32 speed;
|
||||||
|
|
||||||
|
u64 seed;
|
||||||
|
f32 angle_spread;
|
||||||
|
f32 speed_spread;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Pack this efficiently
|
||||||
|
Struct(V_Particle)
|
||||||
|
{
|
||||||
|
V_ParticleKind kind;
|
||||||
|
u32 emitter_init_num; // if != 0, then initialize using emitter at index (emitter_init_num - 1)
|
||||||
|
u32 idx_in_emitter;
|
||||||
|
|
||||||
|
Vec2 pos;
|
||||||
|
Vec2 velocity;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if IsLanguageC
|
||||||
|
Struct(V_EmitterNode)
|
||||||
|
{
|
||||||
|
V_EmitterNode *next;
|
||||||
|
V_Emitter emitter;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Backdrop shader types
|
||||||
|
|
||||||
|
#define V_BackdropCSThreadSizeFromTexSize(tex_size) VEC3I32((tex_size.x + 7) / 8, (tex_size.y + 7) / 8, 1)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Quad types
|
||||||
|
|
||||||
|
Enum(V_DQuadFlag)
|
||||||
|
{
|
||||||
|
V_DQuadFlag_None = 0,
|
||||||
|
V_DQuadFlag_DrawGrid = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(V_DQuad)
|
||||||
|
{
|
||||||
|
V_DQuadFlag flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Vert types
|
||||||
|
|
||||||
|
Struct(V_DVert)
|
||||||
|
{
|
||||||
|
Vec2 pos;
|
||||||
|
Vec4 color_lin;
|
||||||
|
};
|
||||||
@ -20,13 +20,14 @@
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Api
|
//- Api
|
||||||
|
|
||||||
|
@IncludeC ui_shared.cgh
|
||||||
|
@IncludeG ui_shared.cgh
|
||||||
|
|
||||||
@IncludeC ui_icon.h
|
@IncludeC ui_icon.h
|
||||||
@IncludeC ui_core.h
|
@IncludeC ui_core.h
|
||||||
@IncludeC ui_extras.h
|
@IncludeC ui_extras.h
|
||||||
@IncludeC ui_shaders.cgh
|
|
||||||
|
|
||||||
@IncludeG ui_shaders.cgh
|
@IncludeG ui_gpu.gh
|
||||||
@IncludeG ui_shaders.gh
|
|
||||||
|
|
||||||
@Bootstrap UI_Bootstrap
|
@Bootstrap UI_Bootstrap
|
||||||
|
|
||||||
@ -35,4 +36,5 @@
|
|||||||
|
|
||||||
@IncludeC ui_core.c
|
@IncludeC ui_core.c
|
||||||
@IncludeC ui_extras.c
|
@IncludeC ui_extras.c
|
||||||
@IncludeG ui_shaders.g
|
|
||||||
|
@IncludeG ui_gpu.g
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user