diff --git a/src/base/base_shader.gh b/src/base/base_shader.gh index b68ec5f0..02368f6f 100644 --- a/src/base/base_shader.gh +++ b/src/base/base_shader.gh @@ -99,6 +99,30 @@ u32 U32FromVec4(Vec4 v) return result; } +f32 LinearFromSrgbF32(f32 srgb) +{ + f32 result; + if (srgb <= 0.04045f) + { + result = srgb / 12.92f; + } + else + { + result = pow((srgb + 0.055f) / 1.055f, 2.4f); + } + return result; +} + +Vec4 LinearFromSrgb(Vec4 srgb) +{ + Vec4 result; + result.x = LinearFromSrgbF32(srgb.x); + result.y = LinearFromSrgbF32(srgb.y); + result.z = LinearFromSrgbF32(srgb.z); + result.w = srgb.w; + return result; +} + //////////////////////////////////////////////////////////// //~ Vertex ID helpers diff --git a/src/pp/pp_vis/pp_vis.lay b/src/pp/pp_vis/pp_vis.lay index f75f6d66..4bfa543e 100644 --- a/src/pp/pp_vis/pp_vis.lay +++ b/src/pp/pp_vis/pp_vis.lay @@ -20,6 +20,8 @@ @PixelShader V_DQuadPS @VertexShader V_DVertVS @PixelShader V_DVertPS +@VertexShader V_OverlayVS +@PixelShader V_OverlayPS ////////////////////////////// //- Api diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 8d980494..ba822619 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -67,11 +67,17 @@ void V_TickForever(WaveLaneCtx *lane) G_Layout_DirectQueue_ShaderRead_ShaderReadWrite_CopyRead_CopyWrite ); gpu_tiles_ref = G_PushTexture2DRef(gpu_perm, gpu_tiles); + /* TODO: Clear tiles from GPU (instead of copy from cpu) */ + G_CopyCpuToTexture( + cl, + gpu_tiles, VEC3I32(0, 0, 0), + tiles, VEC3I32(tiles_dims.x, tiles_dims.y, 1), + RNG3I32(VEC3I32(0, 0, 0), VEC3I32(tiles_dims.x, tiles_dims.y, 1)) + ); } G_CommitCommandList(cl); } - for (u32 i = 0; i < countof(V.frames); ++i) { V_Frame *frame = &V.frames[i]; @@ -439,11 +445,56 @@ void V_TickForever(WaveLaneCtx *lane) frame->draw_to_world_xf = InvertXform(frame->world_to_draw_xf); } - /* Cursors */ + ////////////////////////////// + //- Update cursors / selection + frame->ui_cursor = ui_frame->cursor_pos; frame->draw_cursor = MulXformV2(frame->ui_to_draw_xf, frame->ui_cursor); frame->world_cursor = MulXformV2(frame->ui_to_world_xf, frame->ui_cursor); + frame->ui_selection_start = frame->ui_cursor; + if (frame->is_editing) + { + frame->selection_mode = V_SelectionMode_Tile; + frame->is_selecting = frame->held_buttons[Button_M1]; + if (frame->is_selecting && last_frame->is_selecting) + { + frame->ui_selection_start = last_frame->ui_selection_start; + } + } + + frame->ui_selection.p0.x = MinF32(last_frame->ui_cursor.x, last_frame->ui_selection_start.x); + frame->ui_selection.p0.y = MinF32(last_frame->ui_cursor.y, last_frame->ui_selection_start.y); + frame->ui_selection.p1.x = MaxF32(last_frame->ui_cursor.x, last_frame->ui_selection_start.x); + frame->ui_selection.p1.y = MaxF32(last_frame->ui_cursor.y, last_frame->ui_selection_start.y); + + frame->draw_selection.p0 = MulXformV2(last_frame->ui_to_draw_xf, frame->ui_selection.p0); + frame->draw_selection.p1 = MulXformV2(last_frame->ui_to_draw_xf, frame->ui_selection.p1); + + frame->world_selection.p0 = MulXformV2(last_frame->ui_to_world_xf, frame->ui_selection.p0); + frame->world_selection.p1 = MulXformV2(last_frame->ui_to_world_xf, frame->ui_selection.p1); + + ////////////////////////////// + //- Place tiles + + /* TODO: Push vis cmd */ + + if (frame->is_editing && last_frame->is_selecting && !frame->is_selecting) + { + if (last_frame->selection_mode == V_SelectionMode_Tile) + { + Rng2I32 tile_range = Zi; + tile_range.p0 = S_TilePosFromWorldPos(frame->world_selection.p0); + tile_range.p1 = S_TilePosFromWorldPos(frame->world_selection.p1); + tile_range.p1 = AddVec2I32(tile_range.p1, VEC2I32(1, 1)); + + S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Tile); + cmd->tile_placement.placement_kind = S_TilePlacementKind_Range; + cmd->tile_placement.tile_kind = S_TileKind_Floor; + cmd->tile_placement.range = tile_range; + } + } + ////////////////////////////// //- Build command palette @@ -647,7 +698,7 @@ void V_TickForever(WaveLaneCtx *lane) { S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Tile); cmd->tile_placement.placement_kind = S_TilePlacementKind_Range; - cmd->tile_placement.tile_kind = S_TileKind_Floor; + cmd->tile_placement.tile_kind = S_TileKind_Wall; cmd->tile_placement.range.p0 = VEC2I32(100, 100); cmd->tile_placement.range.p1 = VEC2I32(110, 110); // cmd->tile_placement.range.p0 = VEC2I32(2, 2); @@ -702,53 +753,6 @@ void V_TickForever(WaveLaneCtx *lane) } UnlockTicketMutex(&S.input_back_tm); - // LockTicketMutex(&S.input_back_tm); - // { - // S_InputState *v2s = &S.input_states[S.input_back_idx]; - - // /* Submit control cmd */ - // { - // S_Cmd *cmd = 0; - // { - // S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); - // SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); - // ++v2s->cmds_count; - // cmd = &cmd_node->cmd; - // } - // cmd->kind = S_CmdKind_Control; - // cmd->target = V.player_key; - // cmd->move = frame->move; - // cmd->look = frame->look; - // } - - // /* Submit tile cmds */ - - - // /* Submit spawn cmds */ - // if (spawn_ents.count > 0) - // { - // S_Cmd *cmd = 0; - // { - // S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); - // SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); - // ++v2s->cmds_count; - // cmd = &cmd_node->cmd; - // } - // cmd->kind = S_CmdKind_Spawn; - // S_EntList *dst = &cmd->ents; - // for (S_EntListNode *src_n = spawn_ents.first; src_n; src_n = src_n->next) - // { - // S_EntListNode *dst_n = PushStruct(v2s->arena, S_EntListNode); - // { - // SllQueuePush(dst->first, dst->last, dst_n); - // ++dst->count; - // } - // dst_n->ent = src_n->ent; - // } - // } - // } - // UnlockTicketMutex(&S.input_back_tm); - ////////////////////////////// //- Render @@ -825,20 +829,20 @@ void V_TickForever(WaveLaneCtx *lane) params.world_to_draw_xf = frame->world_to_draw_xf; params.draw_to_world_xf = frame->draw_to_world_xf; - params.target_cursor_pos = frame->draw_cursor; + params.selection_mode = frame->selection_mode; + params.ui_cursor = frame->ui_cursor; + params.draw_cursor = frame->draw_cursor; + params.world_cursor = frame->world_cursor; + params.ui_selection = frame->ui_selection; + params.draw_selection = frame->draw_selection; + params.world_selection = frame->world_selection; + params.camera_pos = frame->camera_pos; params.camera_zoom = frame->camera_zoom; params.world_size = world_size; params.tiles = gpu_tiles_ref; params.shape_verts = dverts_ro; - - params.background_color_a = LinearFromSrgb(VEC4(0.30, 0.30, 0.30, 1)); - params.background_color_b = LinearFromSrgb(VEC4(0.15, 0.15, 0.15, 1)); - params.grid_color = LinearFromSrgb(VEC4(0, 0, 0, 1)); - params.x_axis_color = LinearFromSrgb(VEC4(0.75, 0, 0, 1)); - params.y_axis_color = LinearFromSrgb(VEC4(0, 0.75, 0, 1)); - params.bounds_color = LinearFromSrgb(VEC4(0.75, 0.75, 0, 1)); } G_ResourceHandle params_buff = G_PushBufferFromString(frame->gpu_arena, frame->cl, StringFromStruct(¶ms)); G_StructuredBufferRef params_ro = G_PushStructuredBufferRef(frame->gpu_arena, params_buff, V_DParams); @@ -859,7 +863,6 @@ void V_TickForever(WaveLaneCtx *lane) G_DumbMemoryLayoutSync(frame->cl, draw_target, G_Layout_DirectQueue_ShaderReadWrite); - /* Backdrop pass */ { G_Compute(frame->cl, V_BackdropCS, V_BackdropCSThreadSizeFromTexSize(frame->draw_dims)); } @@ -869,14 +872,29 @@ void V_TickForever(WaveLaneCtx *lane) G_DumbMemoryLayoutSync(frame->cl, draw_target, G_Layout_DirectQueue_RenderTargetWrite); - /* Shapes pass */ { - G_Rasterize(frame->cl, - V_DVertVS, V_DVertPS, - 1, dvert_idxs_ib, - 1, &draw_target, - viewport, scissor, - G_RasterMode_TriangleList); + G_Rasterize( + frame->cl, + V_DVertVS, V_DVertPS, + 1, dvert_idxs_ib, + 1, &draw_target, + viewport, scissor, + G_RasterMode_TriangleList + ); + } + + ////////////////////////////// + //- Overlay pass + + { + G_Rasterize( + frame->cl, + V_OverlayVS, V_OverlayPS, + 1, G_QuadIndices(), + 1, &draw_target, + viewport, scissor, + G_RasterMode_TriangleList + ); } ////////////////////////////// diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index c2c83ef5..296d9129 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -113,7 +113,10 @@ Struct(V_Frame) V_EditMode edit_mode; /* Editor */ + b32 is_selecting; b32 is_panning; + V_SelectionMode selection_mode; + Vec2 ui_selection_start; Vec2 edit_camera_pos; f32 edit_camera_zoom; @@ -137,6 +140,9 @@ Struct(V_Frame) Vec2 ui_cursor; Vec2 draw_cursor; Vec2 world_cursor; + Rng2 ui_selection; + Rng2 draw_selection; + Rng2 world_selection; /* Control */ Vec2 move; diff --git a/src/pp/pp_vis/pp_vis_shaders.cgh b/src/pp/pp_vis/pp_vis_shaders.cgh index a01d6ef4..0f81c253 100644 --- a/src/pp/pp_vis/pp_vis_shaders.cgh +++ b/src/pp/pp_vis/pp_vis_shaders.cgh @@ -3,6 +3,12 @@ G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 0); +Enum(V_SelectionMode) +{ + V_SelectionMode_None, + V_SelectionMode_Tile, +}; + Struct(V_DParams) { Vec2I32 target_size; @@ -12,7 +18,14 @@ Struct(V_DParams) Xform world_to_draw_xf; Xform draw_to_world_xf; - Vec2 target_cursor_pos; + V_SelectionMode selection_mode; + Vec2 ui_cursor; + Vec2 draw_cursor; + Vec2 world_cursor; + Rng2 ui_selection; + Rng2 draw_selection; + Rng2 world_selection; + Vec2 camera_pos; f32 camera_zoom; @@ -20,13 +33,6 @@ Struct(V_DParams) G_Texture2DRef tiles; G_StructuredBufferRef quads; G_StructuredBufferRef shape_verts; - - Vec4 background_color_a; - Vec4 background_color_b; - Vec4 grid_color; - Vec4 x_axis_color; - Vec4 y_axis_color; - Vec4 bounds_color; }; //////////////////////////////////////////////////////////// diff --git a/src/pp/pp_vis/pp_vis_shaders.g b/src/pp/pp_vis/pp_vis_shaders.g index 6416da81..56bb82e7 100644 --- a/src/pp/pp_vis/pp_vis_shaders.g +++ b/src/pp/pp_vis/pp_vis_shaders.g @@ -7,6 +7,13 @@ ComputeShader2D(V_BackdropCS, 8, 8) RWTexture2D target = G_Dereference(params.target_rw); Texture2D tiles = G_Dereference(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)); + Vec2U32 target_pos = SV_DispatchThreadID; Vec2I32 target_size = params.target_size; if (target_pos.x < target_size.x && target_pos.y < target_size.y) @@ -29,15 +36,16 @@ ComputeShader2D(V_BackdropCS, 8, 8) { i32 color_idx = 0; Vec4 colors[2] = { - params.background_color_a, - params.background_color_b + background_color_a, + background_color_b }; - Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(1.0, 1.0)); - if (world_pos_modded.x < 0.5) + 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 < 0.5) + if (world_pos_modded.y < checker_size) { color_idx = !color_idx; } @@ -62,7 +70,7 @@ ComputeShader2D(V_BackdropCS, 8, 8) grid_dist = min(grid_dist, abs(target_pos.y - grid_screen_p1.y)); if (grid_dist <= half_thickness) { - result = params.grid_color; + result = grid_color; } } /* Tile */ @@ -91,11 +99,11 @@ ComputeShader2D(V_BackdropCS, 8, 8) f32 y_dist = abs(target_pos.y - zero_screen.y); if (y_dist <= half_thickness) { - result = params.x_axis_color; + result = x_axis_color; } else if (x_dist <= half_thickness) { - result = params.y_axis_color; + result = y_axis_color; } } /* World bounds */ @@ -107,7 +115,7 @@ ComputeShader2D(V_BackdropCS, 8, 8) bounds_dist = min(bounds_dist, abs(target_pos.y - bounds_screen_p1.y)); if (bounds_dist <= half_thickness) { - result = params.bounds_color; + result = bounds_color; } } } @@ -189,3 +197,76 @@ PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input) 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_ShaderConst_Params)[0]; + 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); + + 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.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_WorldSize / 2) && + world_pos.y > -(S_WorldSize / 2) && + world_pos.x < (S_WorldSize / 2) && + world_pos.y < (S_WorldSize / 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; +} diff --git a/src/pp/pp_vis/pp_vis_shaders.gh b/src/pp/pp_vis/pp_vis_shaders.gh index 286bf6b7..d311e6e1 100644 --- a/src/pp/pp_vis/pp_vis_shaders.gh +++ b/src/pp/pp_vis/pp_vis_shaders.gh @@ -27,6 +27,20 @@ Struct(V_DVertPSOutput) Semantic(Vec4, sv_target0); }; +//////////////////////////////////////////////////////////// +//~ Overlay shader types + +Struct(V_OverlayPSInput) +{ + + Semantic(Vec4, sv_position); +}; + +Struct(V_OverlayPSOutput) +{ + Semantic(Vec4, sv_target0); +}; + //////////////////////////////////////////////////////////// //~ Shaders @@ -40,3 +54,7 @@ PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input); //- Shape VertexShader(V_DVertVS, V_DVertPSInput); PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input); + +//- Overlay +VertexShader(V_OverlayVS, V_OverlayPSInput); +PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input);