#define V_ParticlesCap Mebi(2) #define V_TileShadowOffsetMeters 0.05 #define V_QuadShadowOffsetMeters 0.05 #define V_TileShadowColor VEC4(0, 0, 0, 0.5) #define V_QuadShadowColor VEC4(0, 0, 0, 0.25) //////////////////////////////////////////////////////////// //~ Shader register types Enum(V_GpuFlag) { V_GpuFlag_None = 0, V_GpuFlag_DrawShadows = (1 << 0), }; G_DeclRegister(V_GpuFlag, V_GpuReg_Flags, 0); G_DeclRegister(G_BufferRef, V_GpuReg_Frame, 1); G_DeclRegister(G_TextureRef, V_GpuReg_NoiseTex, 2); G_DeclRegister(i32, V_GpuReg_MipsCount, 3); G_DeclRegister(i32, V_GpuReg_MipIdx, 4); //////////////////////////////////////////////////////////// //~ Particle types #define V_ParticleSimBasis 0xb49f2d9e406873b9ull #define V_ParticleColorBasis 0x569aa8341ecc0ea3ull #define V_ParticleCellBasis 0xf60c0cff344b0c5dull #define V_ParticleStainBasis 0x3c64e8226d98d376ull #define V_ParticleLifetimeBasis 0x4969cf8f60816abfull #define V_ParticleFalloffBasis 0xa475ffbeeeef3b9dull Enum(V_ParticleFlag) { V_ParticleFlag_None = 0, V_ParticleFlag_StainWhenPruned = (1 << 1), V_ParticleFlag_NoReflect = (1 << 2), V_ParticleFlag_OnlyCollideWithWalls = (1 << 3), V_ParticleFlag_GasBlend = (1 << 4), V_ParticleFlag_FadeLifetime = (1 << 5), V_ParticleFlag_HaltOnCollision = (1 << 6), }; Enum(V_ParticleLayer) { V_ParticleLayer_Ground, V_ParticleLayer_Mid, V_ParticleLayer_Air, V_ParticleLayer_COUNT }; // NOTE: Higher particle enum values take priority over lower within the same layer ones when drawing / staining #define V_ParticlesXList(X) \ X( \ /* Name */ None, \ /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Ground, \ /* Stain rate, pen chance */ 30, 0, \ /* Lifetime */ Inf, Inf, \ /* Falloff */ 0, 0, \ /* Prune speed threshold */ 0.01, \ /* Base color */ VEC4(0, 0, 0, 0), \ /* Dry color factor */ VEC4(1, 1, 1, 1) \ ) \ \ /* Ground particles */ \ X( \ /* Name */ BloodTrail, \ /* Flags */ V_ParticleFlag_NoReflect | V_ParticleFlag_StainWhenPruned, \ /* Layer */ V_ParticleLayer_Ground, \ /* Stain rate, pen chance */ 100, 0.25, \ /* Lifetime */ Inf, Inf, \ /* Falloff */ 10, 20, \ /* Prune speed threshold */ 0.5, \ /* Base color */ VEC4(0.6, 0.1, 0.1, 0.05), \ /* Dry color factor */ VEC4(0.4, 0.4, 0.4, 1) \ ) \ X( \ /* Name */ Debris, \ /* Flags */ V_ParticleFlag_StainWhenPruned, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ Inf, Inf, \ /* Falloff */ 20, 30, \ /* Prune speed threshold */ 0.1, \ /* Base color */ VEC4(0.4, 0.3, 0.2, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \ ) \ X( \ /* Name */ Fire, \ /* Flags */ V_ParticleFlag_StainWhenPruned, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ Inf, Inf, \ /* Falloff */ 10, 20, \ /* Prune speed threshold */ 0.1, \ /* Base color */ VEC4(2, 0.5, 0, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \ ) \ X( \ /* Name */ HotDebris, \ /* Flags */ V_ParticleFlag_StainWhenPruned, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ Inf, Inf, \ /* Falloff */ 20, 30, \ /* Prune speed threshold */ 0.1, \ /* Base color */ VEC4(2, 0.5, 0, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \ ) \ X( \ /* Name */ Spark, \ /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ 0.2, 0.3, \ /* Falloff */ 10, 20, \ /* Prune speed threshold */ 0.1, \ /* Base color */ VEC4(2, 0.5, 0, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \ ) \ \ /* Air particles */ \ X( \ /* Name */ BulletSmoke, \ /* Flags */ V_ParticleFlag_OnlyCollideWithWalls | V_ParticleFlag_GasBlend | V_ParticleFlag_FadeLifetime, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ 0.075, 0.2, \ /* Falloff */ 0, 0, \ /* Prune speed threshold */ 0.00, \ /* Base color */ VEC4(0.8, 0.6, 0.2, 0.005), \ /* Dry color factor */ VEC4(1, 1, 1, 1) \ ) \ X( \ /* Name */ MuzzleWide, \ /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Air, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ 0.0, .05, \ /* Falloff */ 0, 0, \ /* Prune speed threshold */ 0, \ /* Base color */ VEC4(10, 3.5, 0, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \ ) \ X( \ /* Name */ MuzzleNarrow, \ /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Air, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ 0.0, 0.05, \ /* Falloff */ 0, 0, \ /* Prune speed threshold */ 0, \ /* Base color */ VEC4(10, 3.5, 0, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \ ) \ X( \ /* Name */ BulletTrail, \ /* Flags */ V_ParticleFlag_OnlyCollideWithWalls | V_ParticleFlag_FadeLifetime, \ /* Layer */ V_ParticleLayer_Air, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ 0.075, 0.075, \ /* Falloff */ 0, 0, \ /* Prune speed threshold */ 0, \ /* Base color */ VEC4(3, 1.5, 0, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \ ) \ X( \ /* Name */ Bullet, \ /* Flags */ V_ParticleFlag_NoReflect | V_ParticleFlag_HaltOnCollision, \ /* Layer */ V_ParticleLayer_Air, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ Inf, Inf, \ /* Falloff */ 0, 0, \ /* Prune speed threshold */ 0.01, \ /* Base color */ VEC4(5, 1.75, 0.75, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \ ) \ X( \ /* Name */ WallDust, \ /* Flags */ V_ParticleFlag_OnlyCollideWithWalls | V_ParticleFlag_GasBlend | V_ParticleFlag_FadeLifetime, \ /* Layer */ V_ParticleLayer_Air, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ 0.1, 0.25, \ /* Falloff */ 10, 20, \ /* Prune speed threshold */ 0.01, \ /* Base color */ VEC4(0.5, 0.5, 0.5, 0.35), \ /* Dry color factor */ VEC4(1, 1, 1, 1) \ ) \ \ /* Test particles */ \ X( \ /* Name */ Test, \ /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ Inf, Inf, \ /* Falloff */ 0, 0, \ /* Prune speed threshold */ 0.01, \ /* Base color */ VEC4(1, 1, 0, 1), \ /* Dry color factor */ VEC4(1, 1, 1, 1) \ ) \ /* ----------------------------------------------------------------------------------------------------------------------------------- */ Enum(V_ParticleKind) { #define X(name, ...) V_ParticleKind_##name, V_ParticlesXList(X) #undef X V_ParticleKind_COUNT, }; Struct(V_Emitter) { V_ParticleKind kind; u32 first_particle_seq; u32 count; Rng2 pos; Rng speed; Rng angle; }; // TODO: Pack this efficiently Struct(V_Particle) { i32 kind; // If >= 0, then this maps to V_ParticleKind. Otherwise it represent a particle to be initialized using emitter at index [abs(kind) - 1] u32 origin_occluder; u32 prev_occluder; // TODO: Remove this f32 alive_seconds; f32 stain_accum; u32 cells_count; Vec2 pos; Vec2 velocity; }; Struct(V_ParticleDesc) { V_ParticleKind kind; V_ParticleFlag flags; V_ParticleLayer layer; f32 stain_rate; f32 pen_rate; f32 lifetime_min; f32 lifetime_max; f32 falloff_min; f32 falloff_max; f32 prune_speed_threshold; Vec4 base_color; Vec4 dry_factor; }; #if IsCpu Struct(V_EmitterNode) { V_EmitterNode *next; V_Emitter emitter; }; #endif //////////////////////////////////////////////////////////// //~ Quad types Enum(V_GpuQuadFlag) { V_QuadFlag_None = 0, }; Struct(V_GpuQuad) { V_GpuQuadFlag flags; u32 occluder_id; Affine quad_uv_to_world_af; G_TextureRef tex; Rng2 tex_slice_uv; Vec4 mask_color_lin; }; //////////////////////////////////////////////////////////// //~ Debug vert types Struct(V_DVert) { Vec2 pos; Vec4 color_lin; }; //////////////////////////////////////////////////////////// //~ Profiler types #define V_ProfilerFramesCap Kibi(16) #define V_ProfilerZonesXList(X) \ X(None, Color_Cyan) \ /* ---------------------------- */ Enum(V_ProfilerZone) { #define X(name, ...) CAT(V_ProfilerZone_,name), V_ProfilerZonesXList(X) #undef X V_ProfilerZone_COUNT }; Struct(V_ProfilerZoneInfo) { f32 elapsed_seconds; }; Struct(V_ProfilerFrame) { V_ProfilerZoneInfo zones[V_ProfilerZone_COUNT]; }; //////////////////////////////////////////////////////////// //~ State types Struct(V_TileDesc) { G_TextureRef tex; Vec2 tex_dims; }; Enum(V_SelectionMode) { V_SelectionMode_Tile, }; Enum(V_EditMode) { V_EditMode_Prefab, V_EditMode_Tile, }; Struct(V_Timeline) { b32 show; b32 paused; b32 locked; }; Struct(V_Affines) { // World <-> screen (raw) Affine world_to_screen_raw; Affine screen_to_world_raw; // World <-> screen Affine world_to_screen; Affine screen_to_world; // World <-> shade Affine world_to_shade; Affine shade_to_world; // Shade <-> screen Affine shade_to_screen; Affine screen_to_shade; // World <-> cell Affine world_to_cell; Affine cell_to_world; // World <-> tile Affine world_to_tile; Affine tile_to_world; }; Struct(V_SharedFrame) { //- Time i64 tick; i64 time_ns; i64 dt_ns; f32 dt; //- Modes // TODO: Move to shader-constant flags b32 tiles_dirty; b32 should_clear_particles; b32 should_tone_map; b32 is_looking; b32 is_moving; b32 show_consoles; b32 show_profilers; b32 is_editing; b32 ui_debug; b32 is_selecting; b32 is_panning; b32 has_mouse_focus; b32 has_keyboard_focus; //- Timeline V_Timeline prev_timeline; V_Timeline timeline; //- Editor state V_EditMode edit_mode; V_SelectionMode selection_mode; P_TileKind equipped_tile; P_PrefabKind equipped_prefab; Vec2 world_selection_start; Vec2 edit_camera_pos; f32 edit_camera_zoom; f32 camera_shake; //- Camera i32 zooms; f32 camera_lerp_rate; Vec2 camera_pos; f32 camera_zoom; //- Dims Vec2 screen_dims; Vec2 shade_dims; //- Affines V_Affines af; //- Cursor Vec2 ui_cursor; Vec2 screen_cursor; Vec2 shade_cursor; Vec2 world_cursor; Rng2 screen_selection; Rng2 shade_selection; Rng2 world_selection; //- Crosshair Vec2 world_guy_origin; Vec2 world_crosshair_base; Vec2 world_crosshair; Vec2 screen_crosshair; Vec2 shade_crosshair; //- Control Vec2 move; Vec2 look; //- Gpu data G_SamplerRef basic_samplers[G_BasicSamplerKind_COUNT]; u64 profiler_frame_seq; G_BufferRef profiler_frames; Vec2 profiler_graph_dims; G_TextureRef profiler_graph; V_TileDesc tile_descs[P_TileKind_COUNT]; G_TextureRef tiles; f32 backdrop_parallax; G_TextureRef backdrop_src; G_TextureRef backdrop_chain; G_TextureRef screen; G_TextureRef shade; G_TextureRef albedo; G_TextureRef bloom_chain; u32 emitters_count; G_BufferRef emitters; G_BufferRef particles; G_TextureRef stains; G_TextureRef dry_stains; G_TextureRef drynesses; G_TextureRef occluders; G_TextureRef particle_cells[V_ParticleLayer_COUNT]; G_TextureRef particle_densities[V_ParticleLayer_COUNT]; G_IndexBufferDesc dvert_idxs; G_BufferRef dverts; u32 quads_count; G_BufferRef quads; }; //////////////////////////////////////////////////////////// //~ Helpers V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind);