diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index f43a19eb..e3b7ea9b 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -1915,7 +1915,7 @@ void V_TickForever(WaveLaneCtx *lane) Affine wep_uv_to_world_af = ScaleAffine(wep_pix_to_world_af, DimsFromRng2(wep.tex_rect)); V_Quad *quad = PushStruct(frame->quads_arena, V_Quad); - quad->quad_uv_to_shade_af = MulAffine(frame->af.world_to_shade, wep_uv_to_world_af); + quad->quad_uv_to_screen_af = MulAffine(frame->af.world_to_screen, wep_uv_to_world_af); quad->tex = wep.tex; quad->tex_slice_uv = DivRng2Vec2(wep.tex_rect, wep.tex_dims); } @@ -1926,7 +1926,7 @@ void V_TickForever(WaveLaneCtx *lane) Affine body_uv_to_world_af = ScaleAffine(body_pix_to_world_af, DimsFromRng2(body.tex_rect)); V_Quad *quad = PushStruct(frame->quads_arena, V_Quad); - quad->quad_uv_to_shade_af = MulAffine(frame->af.world_to_shade, body_uv_to_world_af); + quad->quad_uv_to_screen_af = MulAffine(frame->af.world_to_screen, body_uv_to_world_af); quad->tex = body.tex; quad->tex_slice_uv = DivRng2Vec2(body.tex_rect, body.tex_dims); } @@ -4277,6 +4277,16 @@ void V_TickForever(WaveLaneCtx *lane) Rng3 screen_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->screen_dims.x, frame->screen_dims.y, 1)); Rng2 screen_scissor = RNG2(VEC2(screen_viewport.p0.x, screen_viewport.p0.y), VEC2(screen_viewport.p1.x, screen_viewport.p1.y)); + // Albedo texture + G_ResourceHandle albedo_target = G_PushTexture2D( + frame->gpu_arena, frame->cl, + G_Format_R16G16B16A16_Float, + frame->screen_dims, + G_Layout_DirectQueue_RenderTargetWrite, + .flags = G_ResourceFlag_AllowRenderTarget + ); + G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target); + // Shade texture G_ResourceHandle shade_target = G_PushTexture2D( frame->gpu_arena, frame->cl, @@ -4290,16 +4300,6 @@ void V_TickForever(WaveLaneCtx *lane) Rng3 shade_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->shade_dims.x, frame->shade_dims.y, 1)); Rng2 shade_scissor = RNG2(VEC2(shade_viewport.p0.x, shade_viewport.p0.y), VEC2(shade_viewport.p1.x, shade_viewport.p1.y)); - // Albedo texture - G_ResourceHandle albedo_target = G_PushTexture2D( - frame->gpu_arena, frame->cl, - G_Format_R16G16B16A16_Float, - frame->shade_dims, - G_Layout_DirectQueue_RenderTargetWrite, - .flags = G_ResourceFlag_AllowRenderTarget - ); - G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target); - // Quad buffers G_ResourceHandle quads_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->quads_arena)); G_StructuredBufferRef quads_ref = G_PushStructuredBufferRef(frame->gpu_arena, quads_buff, V_Quad); @@ -4356,9 +4356,9 @@ void V_TickForever(WaveLaneCtx *lane) params.shade_dims = frame->shade_dims; params.shade_ro = shade_target_ro; params.shade_rw = shade_target_rw; - params.albedo_ro = albedo_target_ro; params.screen_dims = frame->screen_dims; + params.albedo_ro = albedo_target_ro; params.tiles = gpu_tiles_ref; params.quads = quads_ref; @@ -4463,12 +4463,9 @@ void V_TickForever(WaveLaneCtx *lane) V_QuadVS, V_QuadPS, G_CountBuffer(quads_buff, V_Quad), G_QuadIndices(), 1, &G_Rt(albedo_target, G_BlendMode_CompositeStraightAlpha), - shade_viewport, shade_scissor, + screen_viewport, screen_scissor, G_RasterMode_TriangleList ); - - // Transition albedo to readonly - G_DumbMemoryLayoutSync(frame->cl, albedo_target, G_Layout_DirectQueue_ShaderRead); } ////////////////////////////// @@ -4488,6 +4485,14 @@ void V_TickForever(WaveLaneCtx *lane) G_DumbGlobalMemorySync(frame->cl); } + ////////////////////////////// + //- Transition G-buffers + + { + // Make albedo readonly + G_DumbMemoryLayoutSync(frame->cl, albedo_target, G_Layout_DirectQueue_ShaderRead); + } + ////////////////////////////// //- Shading pass diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index 56fed375..0c878178 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -89,15 +89,14 @@ VertexShader(V_QuadVS, V_QuadPSInput) V_Quad quad = quads[SV_InstanceID]; Vec2 rect_uv = RectUvFromIdx(SV_VertexID); - Vec2 shade_pos = mul(quad.quad_uv_to_shade_af, Vec3(rect_uv, 1)); + Vec2 screen_pos = mul(quad.quad_uv_to_screen_af, Vec3(rect_uv, 1)); - Vec2 tex_pos_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv); - // Vec2 shade_pos = lerp(quad.p0, quad.p1, rect_uv); + Vec2 samp_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv); V_QuadPSInput result; - result.sv_position = Vec4(NdcFromPos(shade_pos, params.shade_dims).xy, 0, 1); + result.sv_position = Vec4(NdcFromPos(screen_pos, params.screen_dims).xy, 0, 1); result.quad_idx = SV_InstanceID; - result.tex_pos_uv = tex_pos_uv; + result.samp_uv = samp_uv; return result; } @@ -113,7 +112,7 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input) V_Quad quad = quads[input.quad_idx]; Texture2D tex = G_Dereference(quad.tex); - Vec4 albedo = tex.Sample(clamp_sampler, input.tex_pos_uv); + Vec4 albedo = tex.Sample(clamp_sampler, input.samp_uv); // Vec4 albedo = Color_Cyan; @@ -443,38 +442,38 @@ ComputeShader(V_SimParticlesCS, 64) } // Commit + // FIXME: Atomic writes { - // FIXME: Atomic write - if (is_in_world_bounds) - { - b32 should_stain = 0; - if ((particle.flags & V_ParticleFlag_StainTrail) || ((particle.flags & V_ParticleFlag_StainOnPrune) && particle.exists == 0)) - { - should_stain = 1; - } - Vec4 color = particle.color; - color.a *= old_exists; - cells[cell_pos] = color; - if (should_stain) - { - f32 old_dryness = drynesses[cell_pos]; - Vec4 old_stain = stains[cell_pos]; - // old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5); - // old_stain = V_DryColor(old_stain, old_dryness); - Vec4 new_stain = 0; - new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a)); - new_stain.a = color.a + (old_stain.a * (1.0 - color.a)); - // new_stain = V_DryColor(new_stain, old_dryness * 0.1); - // new_stain = V_DryColor(new_stain, old_dryness * 0.5); + b32 should_stain = is_in_world_bounds && ( + AnyBit(particle.flags, V_ParticleFlag_StainTrail) || + (AnyBit(particle.flags, V_ParticleFlag_StainOnPrune) && particle.exists == 0) + ); + b32 should_draw = is_in_world_bounds; - stains[cell_pos] = new_stain; - drynesses[cell_pos] = 0; - } - } - else + Vec4 color = particle.color; + color.a *= old_exists; + + // Stain + if (should_stain) { - // Prune out of bounds particle - particle.exists = 0; + f32 old_dryness = drynesses[cell_pos]; + Vec4 old_stain = stains[cell_pos]; + // old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5); + // old_stain = V_DryColor(old_stain, old_dryness); + Vec4 new_stain = 0; + new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a)); + new_stain.a = color.a + (old_stain.a * (1.0 - color.a)); + // new_stain = V_DryColor(new_stain, old_dryness * 0.1); + // new_stain = V_DryColor(new_stain, old_dryness * 0.5); + + stains[cell_pos] = new_stain; + drynesses[cell_pos] = 0; + } + + // Draw + if (should_draw) + { + cells[cell_pos] = color; } } particles[particle_idx] = particle; @@ -489,7 +488,7 @@ ComputeShader2D(V_ShadeCS, 8, 8) { V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; RWTexture2D shade_tex = G_Dereference(params.shade_rw); - Texture2D albedo_tex = G_Dereference(params.albedo_ro); + // Texture2D albedo_tex = G_Dereference(params.albedo_ro); Texture2D tiles = G_Dereference(params.tiles); RWTexture2D stains = G_Dereference(params.stains); RWTexture2D drynesses = G_Dereference(params.drynesses); @@ -509,9 +508,89 @@ ComputeShader2D(V_ShadeCS, 8, 8) //- Compute albedo Vec4 albedo = 0; + + ////////////////////////////// + //- Compute result + + Vec4 result = albedo; + + ////////////////////////////// + //- Write result + + if (all(shade_pos < countof(shade_tex))) { + shade_tex[shade_pos] = result; + } +} + +//////////////////////////////////////////////////////////// +//~ Composite + +////////////////////////////// +//- Vertex shader + +VertexShader(V_CompositeVS, V_CompositePSInput) +{ + Vec2 uv = RectUvFromIdx(SV_VertexID); + V_CompositePSInput result; + result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1); + return result; +} + +////////////////////////////// +//- Pixel shader + +PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) +{ + V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; + Texture2D shade_tex = G_Dereference(params.shade_ro); + Texture2D albedo_tex = G_Dereference(params.albedo_ro); + RWTexture2D stains = G_Dereference(params.stains); + RWTexture2D cells = G_Dereference(params.cells); + RWTexture2D drynesses = G_Dereference(params.drynesses); + Texture2D tiles = G_Dereference(params.tiles); + SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler); + + Vec2 screen_pos = input.sv_position.xy; + Vec2 world_pos = mul(params.af.screen_to_world, Vec3(screen_pos, 1)); + Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1)); + Vec2 cell_pos = floor(mul(params.af.world_to_cell, Vec3(world_pos, 1))); + Vec2 shade_pos = mul(params.af.screen_to_shade, Vec3(screen_pos.xy, 1)); + + f32 half_thickness = 1; + Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5; + Vec2 world_bounds_screen_p0 = mul(params.af.world_to_screen, Vec3(-half_world_dims.xy, 1)); + Vec2 world_bounds_screen_p1 = mul(params.af.world_to_screen, Vec3(half_world_dims.xy, 1)); + b32 is_in_world_bounds = ( + screen_pos.x > (world_bounds_screen_p0.x - half_thickness) && + screen_pos.y > (world_bounds_screen_p0.y - half_thickness) && + screen_pos.x < (world_bounds_screen_p1.x + half_thickness) && + screen_pos.y < (world_bounds_screen_p1.y + half_thickness) + ); + + P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); + P_TileKind equipped_tile = params.equipped_tile; + + ////////////////////////////// + //- Shade color + + // Vec4 shade_color = 0; + // if (all(shade_pos >= Vec2(0, 0)) && all(shade_pos < countof(shade_tex))) + // { + // Vec2 shade_uv = shade_pos / countof(shade_tex); + // shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0); + // } + + ////////////////////////////// + //- Albedo color + + Vec4 albedo_color = 0; + { + ////////////////////////////// //- Tile color + // TODO: Remove this + b32 tile_is_wall = 0; Vec4 tile_color = Vec4(0.025, 0.025, 0.025, 1); if (is_in_world_bounds) @@ -581,10 +660,9 @@ ComputeShader2D(V_ShadeCS, 8, 8) } } - //- Albedo tex color - Vec4 albedo_tex_color = albedo_tex.Load(Vec3(shade_pos, 0)); - + ////////////////////////////// //- Stain color + Vec4 stain_color = 0; { f32 dryness = drynesses.Load(cell_pos); @@ -592,84 +670,38 @@ ComputeShader2D(V_ShadeCS, 8, 8) stain_color.rgb *= 1.0 - (0.75 * tile_is_wall); // Darken wall stains } - //- Composite albedo - albedo = BlendPremul(!tile_is_wall * tile_color, albedo); // Blend floor tile - albedo = BlendPremul(!tile_is_wall * stain_color, albedo); // Blend floor stain - albedo = BlendPremul(albedo_tex_color, albedo); - albedo = BlendPremul(tile_is_wall * tile_color, albedo); // Blend wall tile - albedo = BlendPremul(tile_is_wall * stain_color, albedo); // Blend wall stain + ////////////////////////////// + //- Albedo tex + + Vec4 albedo_tex_color = albedo_tex.Load(Vec3(screen_pos, 0)); + + ////////////////////////////// + //- Compose albedo + + albedo_color = BlendPremul(!tile_is_wall * tile_color, albedo_color); // Blend floor tile + albedo_color = BlendPremul(!tile_is_wall * stain_color, albedo_color); // Blend floor stain + albedo_color = BlendPremul(albedo_tex_color, albedo_color); + albedo_color = BlendPremul(tile_is_wall * tile_color, albedo_color); // Blend wall tile + albedo_color = BlendPremul(tile_is_wall * stain_color, albedo_color); // Blend wall stain } ////////////////////////////// - //- Compute result + //- Particle color - Vec4 result = albedo; + // TODO: Remove this + + Vec4 particle_color = 0; + if (is_in_world_bounds) + { + particle_color = cells.Load(cell_pos); + } ////////////////////////////// - //- Write result - - if (all(shade_pos < countof(shade_tex))) - { - shade_tex[shade_pos] = result; - } -} - -//////////////////////////////////////////////////////////// -//~ Composite - -////////////////////////////// -//- Vertex shader - -VertexShader(V_CompositeVS, V_CompositePSInput) -{ - Vec2 uv = RectUvFromIdx(SV_VertexID); - V_CompositePSInput result; - result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1); - return result; -} - -////////////////////////////// -//- Pixel shader - -PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) -{ - V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; - Texture2D shade_tex = G_Dereference(params.shade_ro); - SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler); - - Vec2 screen_pos = input.sv_position.xy; - - Vec2 world_pos = mul(params.af.screen_to_world, Vec3(screen_pos, 1)); - Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1)); - P_TileKind equipped_tile = params.equipped_tile; - - f32 half_thickness = 1; - - Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5; - Vec2 world_bounds_screen_p0 = mul(params.af.world_to_screen, Vec3(-half_world_dims.xy, 1)); - Vec2 world_bounds_screen_p1 = mul(params.af.world_to_screen, Vec3(half_world_dims.xy, 1)); - b32 is_in_world_bounds = ( - screen_pos.x > (world_bounds_screen_p0.x - half_thickness) && - screen_pos.y > (world_bounds_screen_p0.y - half_thickness) && - screen_pos.x < (world_bounds_screen_p1.x + half_thickness) && - screen_pos.y < (world_bounds_screen_p1.y + half_thickness) - ); - - Vec2 shade_pos = mul(params.af.screen_to_shade, Vec3(screen_pos.xy, 1)); - - //- Shaded color - Vec4 shade_color = 0; - if (all(shade_pos >= Vec2(0, 0)) && all(shade_pos < countof(shade_tex))) - { - Vec2 shade_uv = shade_pos / countof(shade_tex); - shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0); - } - //- Tile selection overlay + Vec4 selection_color = 0; if (params.has_mouse_focus && params.selection_mode == V_SelectionMode_Tile) { - 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)); @@ -713,7 +745,9 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) selection_color.rgb *= selection_color.a; } + ////////////////////////////// //- Grid overlay + Vec4 overlay_color = 0; if (is_in_world_bounds) { @@ -771,9 +805,13 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) overlay_color.rgb *= overlay_color.a; } - //- Composite + ////////////////////////////// + //- Blend + Vec4 result = Vec4(0, 0, 0, 1); - result = BlendPremul(shade_color, result); + // result = BlendPremul(shade_color, result); + result = BlendPremul(albedo_color, result); + result = BlendPremul(particle_color, result); result = BlendPremul(selection_color, result); result = BlendPremul(overlay_color, result); diff --git a/src/pp/pp_vis/pp_vis_gpu.gh b/src/pp/pp_vis/pp_vis_gpu.gh index 136b6acf..9c0407ac 100644 --- a/src/pp/pp_vis/pp_vis_gpu.gh +++ b/src/pp/pp_vis/pp_vis_gpu.gh @@ -5,7 +5,7 @@ Struct(V_QuadPSInput) { Semantic(Vec4, sv_position); Semantic(nointerpolation u32, quad_idx); - Semantic(Vec2, tex_pos_uv); + Semantic(Vec2, samp_uv); }; Struct(V_QuadPSOutput) diff --git a/src/pp/pp_vis/pp_vis_shared.cgh b/src/pp/pp_vis/pp_vis_shared.cgh index 852edd7c..93823af8 100644 --- a/src/pp/pp_vis/pp_vis_shared.cgh +++ b/src/pp/pp_vis/pp_vis_shared.cgh @@ -183,7 +183,7 @@ Enum(V_QuadFlag) Struct(V_Quad) { V_QuadFlag flags; - Affine quad_uv_to_shade_af; + Affine quad_uv_to_screen_af; G_Texture2DRef tex; Rng2 tex_slice_uv; };