melhoria nuvens volumetric 2

melhoria nuvens volumetric 2
This commit is contained in:
Jessica_Natalia
2026-08-13 20:38:15 -03:00
parent fb21b362d6
commit 979ba07441
4 changed files with 55 additions and 24 deletions
+2 -2
View File
@@ -4,7 +4,7 @@
; until their VCS guest-side sources are connected.
[VolumetricClouds]
Enabled=true
DownscaleDiv=4
DownscaleDiv=2
Layers=2
ShadowSteps=4
Opacity=1.0
@@ -38,6 +38,6 @@ FogColorB=0.78
FogStart=4500.0
; ProperShaders temporal resolve controls.
TemporalBlend=0.50
TemporalBlend=0.85
TemporalDenoise=1.0
TemporalClamp=1.0
@@ -261,6 +261,30 @@ float3 PreviousCloudNdc(float3 dir){
return float3(q.xy/max(q.z,1e-8),q.z);
}
float CloudSlabEntry(float cameraZ,float rayZ,float bottom,float top){
if(abs(rayZ)<1e-6)return 50000.0;
if(cameraZ>=bottom&&cameraZ<=top)return 0.0;
float a=(bottom-cameraZ)/rayZ,b=(top-cameraZ)/rayZ;
float entry=min(a,b),leave=max(a,b);
return leave<0.0?50000.0:max(entry,0.0);
}
// Reproject translation as well as rotation. CloudPadding carries the previous
// camera position. A world point on the nearest enabled physical cloud slab is
// stable under the orbiting VCS third-person camera, unlike a direction-only
// reprojection that forces the history to reset whenever the camera moves.
float3 PreviousCloudDirection(float2 uv){
float3 dir=WorldRay(uv);
float distance=CloudSlabEntry(CloudCameraPosition.z,dir.z,500.0,900.0);
if((g_Settings&3u)>=2u)
distance=min(distance,CloudSlabEntry(CloudCameraPosition.z,dir.z,3500.0,3600.0));
if((g_Settings&3u)>=3u)
distance=min(distance,CloudSlabEntry(CloudCameraPosition.z,dir.z,1500.0,1900.0));
distance=min(max(distance,1.0),50000.0);
float3 worldPoint=CloudCameraPosition+dir*distance;
return normalize(worldPoint-CloudPadding);
}
// Literal SM5 adaptation of ProperShaders' PS_TemporalResolve. The march fills
// one Bayer slot per 2x2 block; every other pixel keeps its own reprojected
// history and leaks slightly toward the smooth current-frame reconstruction.
@@ -287,7 +311,7 @@ float4 CloudTemporalResolvePS(PresentVertexOutput i):SV_TARGET {
float4 t11=CloudTexture0.SampleLevel(CloudSampler,sb+marchTexel,0.0);
float4 spatial=lerp(lerp(t00,t10,sf.x),lerp(t01,t11,sf.x),sf.y);
float3 previous=PreviousCloudNdc(WorldRay(uv));
float3 previous=PreviousCloudNdc(PreviousCloudDirection(uv));
float2 prevUV=float2(previous.x*0.5+0.5,0.5-previous.y*0.5);
float2 inside=step(float2(0,0),prevUV)*step(prevUV,float2(1,1));
float valid=CloudHistoryValid*inside.x*inside.y*step(1e-8,previous.z);
+26 -19
View File
@@ -2176,7 +2176,11 @@ CloudShaderConstants cloud_present_constants(const Dx12GeState &s) noexcept {
out.ray_forward_opacity[axis] = static_cast<float>(center_world[axis]);
out.camera_settings[axis] = camera->camera_position[axis];
}
out.ray_right_time[3] = static_cast<float>(s.frame_epoch) * (1.0f / 60.0f);
// ProperShaders supplies g_Time in milliseconds. The stochastic march
// offset deliberately changes every frame so temporal accumulation can
// average it away; seconds made adjacent samples nearly identical and left
// the high-frequency grain fixed on screen.
out.ray_right_time[3] = static_cast<float>(s.frame_epoch) * (1000.0f / 60.0f);
out.ray_up_seed[3] = config.random_seed;
out.ray_forward_opacity[3] = config.opacity;
const std::uint32_t settings = std::clamp<std::uint32_t>(config.layers, 1u, 3u) |
@@ -2202,7 +2206,8 @@ void record_clouds_into_world_target(Dx12GeState &s, Dx12FramebufferTarget &targ
!s.cloud_march.image || !s.cloud_target_pipeline ||
!s.cloud_resolve_pipeline || !s.cloud_composite_pipeline)
return;
const std::uint32_t settings = std::bit_cast<std::uint32_t>(clouds.camera_settings[3]);
CloudShaderConstants draw_clouds = clouds;
const std::uint32_t settings = std::bit_cast<std::uint32_t>(draw_clouds.camera_settings[3]);
if ((settings & 0x10000u) == 0u) return;
const std::uint32_t previous_index = s.cloud_history_index & 1u;
@@ -2214,16 +2219,18 @@ void record_clouds_into_world_target(Dx12GeState &s, Dx12FramebufferTarget &targ
float camera_delta_squared = 0.0f;
if (s.cloud_history_valid) {
for (std::size_t axis = 0u; axis < 3u; ++axis) {
const float delta = clouds.camera_settings[axis] - s.cloud_previous_camera[axis];
const float delta = draw_clouds.camera_settings[axis] - s.cloud_previous_camera[axis];
camera_delta_squared += delta * delta;
}
}
// Like ProperShaders, rotation is reprojected while positional movement
// gets one complete current-frame march. A composite of several cloud
// depths cannot be translated correctly with a single motion vector.
const bool camera_translated = s.cloud_history_valid &&
camera_delta_squared > 0.0004f;
const bool full_current_frame = !s.cloud_history_valid || camera_translated;
// VCS' third-person camera translates while orbiting the player. Reproject
// ordinary translation against the physical cloud slabs in the shader and
// reset only for an actual cut/teleport (50 world units in one frame).
const bool camera_cut = s.cloud_history_valid && camera_delta_squared > 2500.0f;
const bool full_current_frame = !s.cloud_history_valid || camera_cut;
for (std::size_t axis = 0u; axis < 3u; ++axis)
draw_clouds.brightness_padding[1u + axis] = s.cloud_history_valid
? s.cloud_previous_camera[axis] : draw_clouds.camera_settings[axis];
constexpr std::array<std::array<float, 2>, 4> kBayerSlots{{
{{0.0f, 0.0f}}, {{1.0f, 1.0f}}, {{1.0f, 0.0f}}, {{0.0f, 1.0f}}}};
const auto &subpixel = kBayerSlots[s.cloud_temporal_frame & 3u];
@@ -2234,15 +2241,15 @@ void record_clouds_into_world_target(Dx12GeState &s, Dx12FramebufferTarget &targ
for (std::size_t axis = 0u; axis < 3u; ++axis)
destination[axis] = s.cloud_history_valid
? s.cloud_previous_ray_basis[offset + axis]
: (offset == 0u ? clouds.ray_right_time[axis]
: offset == 3u ? clouds.ray_up_seed[axis]
: clouds.ray_forward_opacity[axis]);
: (offset == 0u ? draw_clouds.ray_right_time[axis]
: offset == 3u ? draw_clouds.ray_up_seed[axis]
: draw_clouds.ray_forward_opacity[axis]);
};
copy_previous_basis(temporal.previous_right_history, 0u);
copy_previous_basis(temporal.previous_up_blend, 3u);
copy_previous_basis(temporal.previous_forward_spatial, 6u);
temporal.previous_right_history[3] =
s.cloud_history_valid && !camera_translated ? 1.0f : 0.0f;
s.cloud_history_valid && !camera_cut ? 1.0f : 0.0f;
temporal.previous_up_blend[3] = std::clamp(config.temporal_blend, 0.0f, 0.95f);
temporal.previous_forward_spatial[3] =
std::clamp(config.temporal_denoise * 0.012f, 0.0f, 0.25f);
@@ -2259,7 +2266,7 @@ void record_clouds_into_world_target(Dx12GeState &s, Dx12FramebufferTarget &targ
ID3D12DescriptorHeap *heaps[]{s.srv_heap.Get(), s.sampler_heap.Get()};
s.list->SetDescriptorHeaps(2u, heaps);
s.list->SetGraphicsRootSignature(s.cloud_root_signature.Get());
s.list->SetGraphicsRoot32BitConstants(0u, 40u, &clouds, 0u);
s.list->SetGraphicsRoot32BitConstants(0u, 40u, &draw_clouds, 0u);
s.list->SetGraphicsRoot32BitConstants(3u, 20u, &temporal, 0u);
s.list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
constexpr float clear_cloud[4]{0.0f, 0.0f, 0.0f, 1.0f};
@@ -2324,10 +2331,10 @@ void record_clouds_into_world_target(Dx12GeState &s, Dx12FramebufferTarget &targ
s.cloud_history_index = current_index;
++s.cloud_temporal_frame;
for (std::size_t axis = 0u; axis < 3u; ++axis) {
s.cloud_previous_camera[axis] = clouds.camera_settings[axis];
s.cloud_previous_ray_basis[axis] = clouds.ray_right_time[axis];
s.cloud_previous_ray_basis[3u + axis] = clouds.ray_up_seed[axis];
s.cloud_previous_ray_basis[6u + axis] = clouds.ray_forward_opacity[axis];
s.cloud_previous_camera[axis] = draw_clouds.camera_settings[axis];
s.cloud_previous_ray_basis[axis] = draw_clouds.ray_right_time[axis];
s.cloud_previous_ray_basis[3u + axis] = draw_clouds.ray_up_seed[axis];
s.cloud_previous_ray_basis[6u + axis] = draw_clouds.ray_forward_opacity[axis];
}
s.cloud_history_valid = true;
@@ -2344,7 +2351,7 @@ void record_clouds_into_world_target(Dx12GeState &s, Dx12FramebufferTarget &targ
s.list->RSSetScissorRects(1u, &scissor);
s.list->SetPipelineState(s.cloud_composite_pipeline.Get());
s.list->SetGraphicsRootSignature(s.cloud_root_signature.Get());
s.list->SetGraphicsRoot32BitConstants(0u, 40u, &clouds, 0u);
s.list->SetGraphicsRoot32BitConstants(0u, 40u, &draw_clouds, 0u);
temporal.control[0] = 0.0f;
s.list->SetGraphicsRoot32BitConstants(3u, 20u, &temporal, 0u);
s.list->SetGraphicsRootDescriptorTable(1u, srv_gpu(s, current.srv_index));
+2 -2
View File
@@ -180,7 +180,7 @@ struct WidescreenConfiguration {
// materially changes CloudWorks' appearance.
struct VolumetricCloudsConfiguration {
bool enabled{false};
std::uint32_t downscale_div{4u};
std::uint32_t downscale_div{2u};
std::uint32_t layers{2u};
std::uint32_t shadow_steps{4u};
float coverage_low{0.35f};
@@ -206,7 +206,7 @@ struct VolumetricCloudsConfiguration {
float fog_color_b{0.78f};
float fog_start{4500.0f};
float day_progression{0.88f};
float temporal_blend{0.50f};
float temporal_blend{0.85f};
float temporal_denoise{1.0f};
float temporal_clamp{1.0f};
};