From 79ee8d049264fe3cda81bc88631cf083caeb1acd Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 11 Mar 2026 22:11:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BD=93=E7=A7=AF=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=EF=BC=9A=E4=BD=BF=E7=94=A8=20HDDA=20=E6=A0=91?= =?UTF-8?q?=E9=81=8D=E5=8E=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改进内容: 1. 添加 get_hdda_hit 函数,使用 pnanovdb_hdda_tree_marcher 2. 添加 get_dim_coord 函数,检测空区域维度 3. 优化 ray marching: - 先用 HDDA 找到第一个有数据的点 - 遍历中检测 dim,跳过空区域 - 回溯机制避免跳过有效数据 效果:体积云渲染更完整,不再是只有框表面有数据 --- Res/Shader/volume.hlsl | 65 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/Res/Shader/volume.hlsl b/Res/Shader/volume.hlsl index 3f370cb0..82b618a2 100644 --- a/Res/Shader/volume.hlsl +++ b/Res/Shader/volume.hlsl @@ -59,6 +59,31 @@ float get_value_coord(inout pnanovdb_readaccessor_t acc, float3 pos) return pnanovdb_read_float(buf, address); } +uint get_dim_coord(inout pnanovdb_readaccessor_t acc, float3 pos) +{ + pnanovdb_vec3_t p = pos; + pnanovdb_coord_t ijk = pnanovdb_hdda_pos_to_ijk(p); + return pnanovdb_readaccessor_get_dim(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, ijk); +} + +bool get_hdda_hit(inout pnanovdb_readaccessor_t acc, inout float tmin, float3 origin, float3 direction, float tmax, out float valueAtHit) +{ + pnanovdb_vec3_t p_origin = origin; + pnanovdb_vec3_t p_direction = direction; + float thit; + bool hit = pnanovdb_hdda_tree_marcher( + PNANOVDB_GRID_TYPE_FLOAT, + buf, + acc, + p_origin, tmin, + p_direction, tmax, + thit, + valueAtHit + ); + tmin = thit; + return hit; +} + PSInput MainVS(VSInput input) { PSInput output; @@ -100,19 +125,45 @@ float4 MainPS(PSInput input) : SV_TARGET float3 color = float3(0, 0, 0); float transmittance = 1.0; + float not_used; + bool hit = get_hdda_hit(volume.acc, tmin, _CameraPos, rayDir, tmax, not_used); + if (!hit) { return float4(0, 0, 0, 0); } + + float skip = 0; + for (uint i = 0; i < _MaxSteps; i++) { - float t = tmin + i * _StepSize; - if (t > tmax || transmittance < 0.01) break; + if (tmin >= tmax || transmittance < 0.01) break; - float3 worldPos = _CameraPos + rayDir * t; + float3 worldPos = _CameraPos + rayDir * tmin; + + uint dim = get_dim_coord(volume.acc, worldPos); + if (dim > 1) { + float skip_step = 15.0; + tmin += skip_step; + skip = skip_step; + continue; + } float density = get_value_coord(volume.acc, worldPos) * _DensityScale; - if (density > 0.001) { - float3 S = density * float3(1, 1, 1); - color += transmittance * S * _StepSize; - transmittance *= exp(-density * _StepSize); + if (density < 0.001) { + float skip_step = 5.0; + tmin += skip_step; + skip = skip_step; + continue; } + + if (skip > 0) { + tmin -= skip * 0.8; + worldPos = _CameraPos + rayDir * tmin; + skip = 0; + } + + float3 S = density * float3(1, 1, 1); + color += transmittance * S * _StepSize; + transmittance *= exp(-density * _StepSize); + + tmin += _StepSize; } float alpha = 1.0 - transmittance;