优化体积渲染:使用 HDDA 树遍历器
改进内容: 1. 添加 get_hdda_hit 函数,使用 pnanovdb_hdda_tree_marcher 2. 添加 get_dim_coord 函数,检测空区域维度 3. 优化 ray marching: - 先用 HDDA 找到第一个有数据的点 - 遍历中检测 dim,跳过空区域 - 回溯机制避免跳过有效数据 效果:体积云渲染更完整,不再是只有框表面有数据
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user