diff --git a/docs/深入方向规划.md b/docs/深入方向规划.md new file mode 100644 index 00000000..f3a55b6e --- /dev/null +++ b/docs/深入方向规划.md @@ -0,0 +1,1309 @@ +# XCVolumeRenderer 深入方向规划 + +本文档详细列出本科毕业设计可深入的所有方向,供选择和规划。 + +--- + +## 一、渲染效果提升 + +### 1.1 多散射 (Multiple Scattering) + +#### 背景 +当前实现的是单散射(Single Scattering),光线只从光源到体素再到相机弹射一次。真实云层中,光线会在体积内多次弹射,产生柔和的边缘和通透的内部效果。 + +#### 当前问题 +- 云内部过暗,缺乏体积感 +- 边缘过于锐利,不自然 +- 逆光效果不明显 + +#### 解决方案 + +**方法A:迭代多散射** +``` +for (散射次数) { + for (每个采样点) { + 计算该点的入射光(来自光源 + 其他体素的散射光) + 累积散射光 + } +} +``` +- 优点:物理正确 +- 缺点:性能开销大,O(n²) 或更高 + +**方法B:近似多散射** +``` +// 使用扩散近似(Diffusion Approximation) +// 参考: Jensen et al. "A Practical Model for Subsurface Light Transport" +float multiScatter = exp(-sigmaT * d) * diffusionTerm; +``` +- 优点:性能好 +- 缺点:近似,不够精确 + +**方法C:预计算多散射** +``` +// 离线预计算散射LUT +// 运行时查表 +Texture3D scatteringLUT; +float multiScatter = scatteringLUT.Sample(sampler, uvw); +``` +- 优点:运行时快 +- 缺点:需要额外存储 + +#### 实现步骤 +1. 实现简单的双散射(Double Scattering) +2. 观察效果变化 +3. 优化性能(重要性采样) +4. 扩展到多阶散射 + +#### 参考资料 +- Jensen, H. W., et al. "A Practical Model for Subsurface Light Transport" (SIGGRAPH 2001) +- Hachisuka, T., et al. "Progressive Photon Mapping" (SIGGRAPH 2008) +- Kutz, P., et al. "Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes" (SIGGRAPH 2017) + +#### 工作量估计 +- 双散射基础实现:1周 +- 完整多散射:2-3周 +- 性能优化:1周 + +--- + +### 1.2 相函数 (Phase Function) + +#### 背景 +相函数描述光线在介质中散射的方向分布。当前使用的是均匀相函数 `return 1.0`,即各向同性散射。真实云层的相函数是各向异性的,具有强烈的前向散射特性。 + +#### 当前问题 +- 光照效果过于均匀 +- 缺乏真实云层的光晕效果 +- 逆光时的"银边"效果不明显 + +#### 相函数类型 + +**1. Henyey-Greenstein (HG) 相函数** +```hlsl +float hg_phase(float cosTheta, float g) { + float g2 = g * g; + return (1 - g2) / pow(1 + g2 - 2 * g * cosTheta, 1.5) / (4 * PI); +} +``` +- `g = 0`: 各向同性 +- `g > 0`: 前向散射(云层特性) +- `g < 0`: 后向散射 +- 参数 `g` 范围:(-1, 1) + +**2. 双 Henyey-Greenstein 相函数** +```hlsl +float double_hg_phase(float cosTheta, float g1, float g2, float w) { + return w * hg_phase(cosTheta, g1) + (1 - w) * hg_phase(cosTheta, g2); +} +``` +- 结合两个HG相函数 +- 更好地模拟真实云层 +- `g1 ≈ 0.8`(强前向),`g2 ≈ -0.2`(弱后向) + +**3. Mie 相函数** +```hlsl +// 查表实现,更精确但复杂 +// 通常用HG近似 +``` +- 物理最正确 +- 计算复杂 +- 通常用双HG近似 + +**4. Rayleigh 相函数** +```hlsl +float rayleigh_phase(float cosTheta) { + return (3 / (16 * PI)) * (1 + cosTheta * cosTheta); +} +``` +- 适用于大气散射 +- 小粒子(空气分子) + +#### 实现步骤 +1. 实现 HG 相函数 +2. 添加参数 UI 控制 `g` 值 +3. 观察不同 `g` 值的效果 +4. 实现双 HG 相函数 +5. 对比效果 + +#### 参数建议 +| 场景 | g 值 | 说明 | +|------|------|------| +| 云层 | 0.7 ~ 0.9 | 强前向散射 | +| 雾 | 0.1 ~ 0.3 | 弱前向散射 | +| 烟雾 | -0.2 ~ 0.2 | 接近各向同性 | + +#### 参考资料 +- Henyey, L. G., & Greenstein, J. L. "Diffuse radiation in the galaxy" (1941) +- Nishita, T., et al. "Display of clouds taking into account multiple anisotropic scattering and sky light" (SIGGRAPH 1996) + +#### 工作量估计 +- HG相函数实现:1-2天 +- 双HG相函数:2-3天 +- 参数UI:1天 + +--- + +### 1.3 体积自发光 (Volumetric Emission) + +#### 背景 +火焰、熔岩、霓虹气体等发光体积。除了散射外部光源,自身也发出光。 + +#### 实现方法 +```hlsl +// 在着色器中添加自发光项 +float3 emission = emissionColor * emissionIntensity * emissionMask; +float3 S = sigmaS * phase_function() * shadow * float3(1, 1, 1) + emission; +``` + +#### 扩展 +- 温度场驱动发光颜色(黑体辐射) +- 发光影响周围体积(需多散射支持) + +#### 工作量估计 +- 基础实现:1-2天 +- 温度场驱动:3-4天 + +--- + +## 二、性能优化 + +### 2.1 Temporal Reprojection + +#### 背景 +当前渲染存在噪点,尤其是阴影采样。Temporal Reprojection 利用历史帧信息进行降噪。 + +#### 原理 +``` +当前帧颜色 = α * 当前帧渲染 + (1-α) * 历史帧重投影颜色 +``` + +#### 核心步骤 + +**1. 速度缓冲 (Motion Vector)** +```hlsl +// 计算当前像素在上一帧的位置 +float2 motionVector = currentPos - previousPos; +float2 prevUV = currentUV - motionVector; +``` + +**2. 历史帧采样** +```hlsl +float3 historyColor = historyTexture.Sample(sampler, prevUV); +``` + +**3. 颜色约束 (Clamping)** +```hlsl +// 防止鬼影 +float3 minColor = min(neighbors); +float3 maxColor = max(neighbors); +historyColor = clamp(historyColor, minColor, maxColor); +``` + +**4. 混合** +```hlsl +float3 finalColor = lerp(currentColor, historyColor, 0.9); +``` + +#### 需要的资源 +- 历史帧颜色缓冲 +- 深度缓冲(当前帧 + 历史帧) +- Motion Vector 缓冲 + +#### 实现步骤 +1. 创建历史帧缓冲 +2. 实现 Motion Vector 计算 +3. 实现重投影逻辑 +4. 实现颜色约束 +5. 调试和参数调优 + +#### 注意事项 +- 相机快速移动时会产生鬼影 +- 需要处理物体移动(动态场景) +- 需要处理体积自身的旋转/移动 + +#### 参考资料 +- Karis, B. "High Quality Temporal Supersampling" (SIGGRAPH 2014) +- Schied, C., et al. "Temporal Sample Anti-Aliasing" (EGSR 2020) + +#### 工作量估计 +- 基础实现:1周 +- 调优和调试:1周 + +--- + +### 2.2 Compute Shader 重构 + +#### 背景 +当前使用 Pixel Shader 进行 Ray Marching,每个像素独立计算。Compute Shader 可以更灵活地控制线程,实现更好的优化。 + +#### 优势 + +**1. 线程组共享内存** +```hlsl +groupshared float sharedDensity[8][8]; +// 相邻像素可共享中间计算结果 +``` + +**2. 自适应工作分配** +```hlsl +// 可以跳过空像素,让活跃线程处理更多 +``` + +**3. 更好的缓存利用** +```hlsl +// 可以手动控制数据加载,优化缓存 +``` + +#### 实现架构 +``` +Compute Shader Dispatch (32x32 线程组) + ↓ +每个线程处理一个像素 + ↓ +Ray Marching + ↓ +输出到 UAV 纹理 +``` + +#### 代码示例 +```hlsl +[numthreads(8, 8, 1)] +void MainCS(uint3 DTid : SV_DispatchThreadID) +{ + float2 uv = (float2(DTid.xy) + 0.5) / Resolution; + float3 color = RayMarch(uv); + OutputTexture[DTid.xy] = float4(color, 1); +} +``` + +#### 可实现的高级优化 +- 波前追踪 (Wavefront Tracing) +- 空间跳跃优化 +- 自适应采样 + +#### 工作量估计 +- 基础重构:1-2周 +- 高级优化:2-3周 + +--- + +### 2.3 自适应步长 + +#### 背景 +当前使用固定步长,但在低密度区域可以加大步长,高密度区域减小步长。 + +#### 实现方法 + +**方法A:基于密度** +```hlsl +float density = SampleDensity(pos); +float stepSize = baseStep * (1 + (1 - density) * maxScale); +``` + +**方法B:基于梯度** +```hlsl +float gradient = length(SampleGradient(pos)); +float stepSize = baseStep / (1 + gradient * gradientScale); +``` + +**方法C:预计算重要性场** +```hlsl +// 离线预计算每个区域的重要性 +// 运行时根据重要性调整步长 +``` + +#### 注意事项 +- 步长变化过大可能导致伪影 +- 需要注意光线一致性 + +#### 工作量估计 +- 基础实现:2-3天 +- 调优:1周 + +--- + +## 三、功能扩展 + +### 3.1 多光源支持 + +#### 背景 +当前只支持单一方向光。真实场景可能有多个光源(太阳 + 天光 + 点光源)。 + +#### 实现内容 + +**1. 多方向光** +```hlsl +struct DirectionalLight { + float3 direction; + float3 color; + float intensity; +}; + +#define MAX_DIR_LIGHTS 4 +DirectionalLight dirLights[MAX_DIR_LIGHTS]; +``` + +**2. 点光源** +```hlsl +struct PointLight { + float3 position; + float3 color; + float intensity; + float radius; +}; + +float3 SamplePointLight(PointLight light, float3 pos) { + float3 dir = light.position - pos; + float dist = length(dir); + dir /= dist; + + // 衰减 + float attenuation = 1.0 / (1.0 + dist * dist); + + // 阴影采样 + float shadow = VolumetricShadow(pos, dir, dist); + + return light.color * light.intensity * attenuation * shadow; +} +``` + +**3. 聚光灯** +```hlsl +struct SpotLight { + float3 position; + float3 direction; + float3 color; + float intensity; + float innerAngle; + float outerAngle; + float range; +}; +``` + +#### 实现步骤 +1. 设计光源数据结构 +2. 实现多方向光循环 +3. 实现点光源阴影采样 +4. 实现聚光灯锥形衰减 +5. 添加参数 UI + +#### 性能考虑 +- 每个光源都需要额外的阴影采样 +- 限制光源数量或使用延迟渲染思路 + +#### 工作量估计 +- 多方向光:2-3天 +- 点光源:3-4天 +- 聚光灯:2-3天 +- UI和参数:1-2天 + +--- + +### 3.2 大气散射 + +#### 背景 +将体积渲染与天空大气结合,实现更真实的室外场景。 + +#### 核心算法 + +**1. Rayleigh 散射** +```hlsl +// 空气分子散射,产生蓝天 +float3 RayleighScattering(float cosTheta, float height) { + float3 betaR = float3(5.8e-6, 13.5e-6, 33.1e-6); // Rayleigh系数 + float density = exp(-height / 8500); // 大气密度衰减 + return betaR * density * (3 / (16 * PI)) * (1 + cosTheta * cosTheta); +} +``` + +**2. Mie 散射** +```hlsl +// 气溶胶散射,产生雾和光晕 +float3 MieScattering(float cosTheta, float g) { + float3 betaM = float3(21e-6, 21e-6, 21e-6); // Mie系数 + return betaM * HGPhase(cosTheta, g); +} +``` + +**3. 单次散射积分** +```hlsl +float3 IntegrateAtmosphere(float3 rayOrigin, float3 rayDir, float3 sunDir) { + float3 color = 0; + float transmittance = 1; + + for (int i = 0; i < steps; i++) { + float3 pos = rayOrigin + rayDir * t; + float height = length(pos) - earthRadius; + + // Rayleigh + float densityR = exp(-height / 8500); + float3 scatterR = RayleighScattering(dot(rayDir, sunDir), height); + + // Mie + float densityM = exp(-height / 1200); + float3 scatterM = MieScattering(dot(rayDir, sunDir), 0.76); + + // 光学深度 + float3 opticalDepth = (scatterR + scatterM) * stepSize; + transmittance *= exp(-opticalDepth); + color += transmittance * (scatterR + scatterM) * stepSize; + + t += stepSize; + } + + return color; +} +``` + +#### 效果 +- 蓝天 +- 日落/日出 +- 远山大气透视 +- 太阳光晕 + +#### 参考资料 +- Nishita, T., et al. "Display of The Earth Taking into Account Atmospheric Scattering" (SIGGRAPH 1993) +- Bruneton, E., & Neyret, F. "Precomputed Atmospheric Scattering" (EGSR 2008) +- Hillaire, S. "A Scalable and Production Ready Sky and Atmosphere Rendering Technique" (SIGGRAPH 2020) + +#### 工作量估计 +- 基础实现:1周 +- 优化和调参:1周 + +--- + +### 3.3 体积雾 + +#### 背景 +将体积渲染作为后处理效果,与场景几何体融合。 + +#### 实现方法 + +**1. 深度重建世界坐标** +```hlsl +float depth = depthTexture.Sample(sampler, uv); +float4 worldPos = mul(invViewProj, float4(ndc, depth, 1)); +worldPos /= worldPos.w; +``` + +**2. 沿视线积分** +```hlsl +float3 cameraPos = ...; +float3 rayDir = normalize(worldPos - cameraPos); +float dist = length(worldPos - cameraPos); + +float3 color = IntegrateVolume(cameraPos, rayDir, dist); +``` + +**3. 与场景混合** +```hlsl +float3 sceneColor = sceneTexture.Sample(sampler, uv); +float3 finalColor = lerp(sceneColor, volumeColor, volumeAlpha); +``` + +#### 工作量估计 +- 基础实现:3-4天 + +--- + +## 四、交互与控制 + +### 4.1 相机交互 + +#### 功能需求 +- 鼠标左键拖动:旋转视角 +- 鼠标右键拖动:平移 +- 鼠标滚轮:缩放 +- WASD:自由移动 + +#### 实现方法 + +**1. 弧球相机 (Arcball Camera)** +```cpp +// 围绕目标点旋转 +XMVECTOR target = XMVectorSet(0, 0, 0, 1); +float distance = 500.0f; +float yaw = 0, pitch = 0; + +void UpdateCamera() { + XMVECTOR eye = XMVectorSet( + sin(yaw) * cos(pitch) * distance, + sin(pitch) * distance, + cos(yaw) * cos(pitch) * distance, + 1.0f + ); + viewMatrix = XMMatrixLookAtLH(eye, target, XMVectorSet(0, 1, 0, 0)); +} +``` + +**2. 自由相机 (Free Camera)** +```cpp +XMVECTOR position; +float yaw = 0, pitch = 0; + +void Move(float dx, float dy, float dz) { + XMVECTOR forward = XMVectorSet(sin(yaw), 0, cos(yaw), 0); + XMVECTOR right = XMVectorSet(cos(yaw), 0, -sin(yaw), 0); + XMVECTOR up = XMVectorSet(0, 1, 0, 0); + + position += forward * dz + right * dx + up * dy; +} + +void Rotate(float dYaw, float dPitch) { + yaw += dYaw; + pitch += dPitch; + pitch = clamp(pitch, -PI/2 + 0.01f, PI/2 - 0.01f); +} +``` + +#### 输入处理 +```cpp +// Windows 消息处理 +case WM_LBUTTONDOWN: + isDragging = true; + lastMousePos = GET_MOUSE_POS(lParam); + break; + +case WM_MOUSEMOVE: + if (isDragging) { + POINT currentPos = GET_MOUSE_POS(lParam); + float dx = (currentPos.x - lastMousePos.x) * sensitivity; + float dy = (currentPos.y - lastMousePos.y) * sensitivity; + camera.Rotate(dx, dy); + lastMousePos = currentPos; + } + break; +``` + +#### 工作量估计 +- 弧球相机:2-3天 +- 自由相机:2-3天 +- 输入处理:1-2天 + +--- + +### 4.2 实时参数 UI + +#### 功能需求 +- 密度缩放 (Density Scale) +- 步长 (Step Size) +- 最大步数 (Max Steps) +- 光照方向 (Light Direction) +- 光照强度 (Light Intensity) +- 相函数参数 (Phase Function G) +- 阴影采样数 (Shadow Samples) + +#### UI 库选择 + +**选项A:Dear ImGui (推荐)** +```cpp +#include "imgui.h" + +void RenderUI() { + ImGui::Begin("Volume Parameters"); + + ImGui::SliderFloat("Density Scale", &densityScale, 0.0f, 1.0f); + ImGui::SliderFloat("Step Size", &stepSize, 0.1f, 5.0f); + ImGui::SliderInt("Max Steps", &maxSteps, 100, 5000); + ImGui::SliderFloat3("Light Dir", lightDir, -1.0f, 1.0f); + ImGui::SliderFloat("Phase G", &phaseG, -0.99f, 0.99f); + + ImGui::End(); +} +``` + +**选项B:Win32 原生控件** +- 不需要额外库 +- 实现复杂 +- 样式受限 + +#### 集成步骤 +1. 添加 ImGui 到项目 +2. 实现 D3D12 后端 +3. 创建参数面板 +4. 绑定参数到常量缓冲区 + +#### 工作量估计 +- ImGui 集成:2-3天 +- 参数面板:1-2天 + +--- + +### 4.3 体积数据编辑 + +#### 功能需求 +- 实时修改体积密度 +- 添加/删除体素 +- 画笔工具 + +#### 实现思路 + +**1. CPU 端编辑** +```cpp +// 读取当前体积数据 +std::vector volumeData = ReadVolumeData(); + +// 修改 +int x = floor(pos.x / voxelSize); +int y = floor(pos.y / voxelSize); +int z = floor(pos.z / voxelSize); +volumeData[index(x,y,z)] += strength; + +// 重新上传 GPU +UpdateGPUBuffer(volumeData); +``` + +**2. 画笔工具** +```cpp +void PaintVolume(float3 center, float radius, float strength) { + for each voxel in range: + float dist = length(voxelPos - center); + if (dist < radius) { + float falloff = 1 - dist / radius; + voxel.density += strength * falloff; + } +} +``` + +#### 挑战 +- NanoVDB 是只读结构,需要重建 +- 或改用 3D Texture + +#### 工作量估计 +- 基础编辑:1周 +- 画笔工具:3-4天 + +--- + +## 五、数据生成 + +### 5.1 程序化云生成 + +#### 背景 +使用 Noise 函数程序化生成云层,无需外部数据文件。 + +#### 核心算法 + +**1. Perlin Noise** +```hlsl +float perlinNoise(float3 p) { + // 梯度噪声实现 + float3 i = floor(p); + float3 f = frac(p); + float3 u = f * f * (3 - 2 * f); // smoothstep + + return lerp( + lerp(lerp(hash(i + float3(0,0,0)), hash(i + float3(1,0,0)), u.x), + lerp(hash(i + float3(0,1,0)), hash(i + float3(1,1,0)), u.x), u.y), + lerp(lerp(hash(i + float3(0,0,1)), hash(i + float3(1,0,1)), u.x), + lerp(hash(i + float3(0,1,1)), hash(i + float3(1,1,1)), u.x), u.y), + u.z + ); +} +``` + +**2. Fractal Brownian Motion (FBM)** +```hlsl +float fbm(float3 p, int octaves) { + float value = 0; + float amplitude = 0.5; + float frequency = 1; + + for (int i = 0; i < octaves; i++) { + value += amplitude * perlinNoise(p * frequency); + amplitude *= 0.5; + frequency *= 2; + } + + return value; +} +``` + +**3. 云密度函数** +```hlsl +float cloudDensity(float3 pos) { + // 基础形状(球体或盒子) + float shape = sphere(pos, center, radius); + + // 噪声扰动 + float noise = fbm(pos * scale, 5); + + // 密度 + float density = shape * noise; + + // 阈值和锐化 + density = smoothstep(threshold, threshold + edgeSoftness, density); + + return density; +} +``` + +**4. Worley Noise (细胞噪声)** +```hlsl +// 用于云的细节和孔洞 +float worleyNoise(float3 p) { + float minDist = 1e10; + int3 cell = floor(p); + + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) + for (int z = -1; z <= 1; z++) { + int3 neighbor = cell + int3(x, y, z); + float3 point = neighbor + hash3(neighbor); + float dist = distance(p, point); + minDist = min(minDist, dist); + } + + return minDist; +} +``` + +#### 云层模型 + +**Cumulus (积云)** +- 底部平坦,顶部蓬松 +- 使用多个 FBM 叠加 +- 高度衰减 + +**Stratus (层云)** +- 薄层状 +- 低频噪声 +- 均匀分布 + +**Cirrus (卷云)** +- 高空,纤维状 +- 高频噪声 +- 方向性 + +#### 动态演化 +```hlsl +// 随时间演化 +float density = cloudDensity(pos + wind * time); + +// 形态变化 +float growth = sin(time * growthSpeed); +density *= 1 + growth * 0.2; +``` + +#### 参考资料 +- Ebert, D. S., et al. "Texturing & Modeling: A Procedural Approach" +- Gili, A. "The Real-Time Volumetric Cloudscapes of Horizon Zero Dawn" (SIGGRAPH 2015) +- Hillaire, S. "Physically Based Sky, Atmosphere and Cloud Rendering in Frostbite" (SIGGRAPH 2016) + +#### 工作量估计 +- Perlin/FBM 实现:2-3天 +- Worley Noise:2天 +- 云密度函数:3-4天 +- 参数调优:1周 + +--- + +### 5.2 离线流体模拟器 + +#### 背景 +实现 CPU 端流体模拟,导出 OpenVDB/NanoVDB 格式。 + +#### 核心算法:Navier-Stokes 方程 + +``` +∂u/∂t = -(u·∇)u - ∇p/ρ + ν∇²u + f +∇·u = 0 +``` + +其中: +- u:速度场 +- p:压力场 +- ρ:密度 +- ν:粘度 +- f:外力 + +#### 求解步骤 + +**1. 对流 (Advection)** +```cpp +void advect(VelocityField& u, ScalarField& q, float dt) { + for each cell (i, j, k): + // 回溯粒子位置 + Vec3 pos = Vec3(i, j, k) - u(i, j, k) * dt; + // 插值采样 + q_new(i, j, k) = interpolate(q, pos); +} +``` + +**2. 扩散 (Diffusion)** +```cpp +void diffuse(ScalarField& q, float viscosity, float dt) { + // Jacobi 迭代 + for (int iter = 0; iter < iterations; iter++) { + for each cell (i, j, k): + q_new(i, j, k) = (q(i-1,j,k) + q(i+1,j,k) + + q(i,j-1,k) + q(i,j+1,k) + + q(i,j,k-1) + q(i,j,k+1) + + q_old(i,j,k) * alpha) / (6 + alpha); + } +} +``` + +**3. 压力求解 (Pressure Solve)** +```cpp +void project(VelocityField& u) { + // 计算散度 + for each cell: + divergence(i, j, k) = -0.5 * (u(i+1,j,k).x - u(i-1,j,k).x + + u(i,j+1,k).y - u(i,j-1,k).y + + u(i,j,k+1).z - u(i,j,k-1).z); + + // Jacobi 迭代求解压力 + for (int iter = 0; iter < iterations; iter++) { + for each cell: + p_new(i, j, k) = (p(i-1,j,k) + p(i+1,j,k) + + p(i,j-1,k) + p(i,j+1,k) + + p(i,j,k-1) + p(i,j,k+1) + - divergence(i,j,k)) / 6; + } + + // 速度校正 + for each cell: + u(i, j, k).x -= 0.5 * (p(i+1,j,k) - p(i-1,j,k)); + u(i, j, k).y -= 0.5 * (p(i,j+1,k) - p(i,j-1,k)); + u(i, j, k).z -= 0.5 * (p(i,j,k+1) - p(i,j,k-1)); +} +``` + +**4. 外力 (External Forces)** +```cpp +void addForce(VelocityField& u, Vec3 forcePos, Vec3 forceDir, float strength) { + for each cell near forcePos: + u(i, j, k) += forceDir * strength * falloff(distance); +} +``` + +#### 烟雾模拟扩展 + +**密度场** +```cpp +// 对流密度 +advect(u, density, dt); + +// 添加烟雾源 +for each source cell: + density(i, j, k) = sourceStrength; + +// 衰减 +density *= (1 - decay * dt); +``` + +**温度场** +```cpp +// 浮力 +for each cell: + float buoyancy = temperature(i,j,k) * buoyancyStrength; + u(i,j,k).y += buoyancy * dt; +``` + +**涡度约束 (Vorticity Confinement)** +```cpp +// 增加细节 +Vec3 curl = computeCurl(u); +Vec3 N = normalize(curl); +Vec3 omega = curl; +u += dt * vorticityStrength * N * omega; +``` + +#### OpenVDB 集成 + +```cpp +#include +#include + +void exportToVDB(const ScalarField& density, const std::string& filename) { + openvdb::initialize(); + + // 创建网格 + openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create(); + openvdb::FloatGrid::Accessor accessor = grid->getAccessor(); + + // 填充数据 + for each active voxel (i, j, k): + openvdb::Coord coord(i, j, k); + accessor.setValue(coord, density(i, j, k)); + + // 保存 + openvdb::io::File file(filename); + file.write({grid}); + file.close(); +} +``` + +#### NanoVDB 转换 + +```cpp +#include + +void convertToNanoVDB(const std::string& openvdbFile, const std::string& nanovdbFile) { + // 读取 OpenVDB + openvdb::io::File file(openvdbFile); + openvdb::GridBase::Ptr baseGrid = file.readGrid("density"); + + // 转换 + auto handle = nanovdb::openToNanoVDB(baseGrid); + + // 保存 + nanovdb::io::writeToFile(nanovdbFile, handle); +} +``` + +#### 工作流程 +``` +1. 初始化网格和场 +2. 循环帧: + a. 对流速度场 + b. 添加外力 + c. 扩散(粘度) + d. 压力求解 + e. 对流密度/温度 + f. 导出当前帧 +3. 批量转换为 NanoVDB +``` + +#### 参考资料 +- Bridson, R. "Fluid Simulation for Computer Graphics" (书籍) +- Stam, J. "Stable Fluids" (SIGGRAPH 1999) +- Fedkiw, R., et al. "Visual Simulation of Smoke" (SIGGRAPH 2001) + +#### 工作量估计 +- 基础流体求解器:2周 +- 烟雾扩展:1周 +- OpenVDB 集成:1周 +- NanoVDB 导出:3-4天 +- UI 和参数:1周 + +--- + +### 5.3 多格式导入 + +#### 支持格式 + +| 格式 | 描述 | 库 | +|------|------|-----| +| OpenVDB (.vdb) | 行业标准 | openvdb 库 | +| DDS 体积纹理 | DirectX 格式 | DirectX | +| Raw 体素数据 | 自定义格式 | 手动解析 | + +#### 实现思路 +```cpp +class VolumeLoader { +public: + virtual bool load(const std::string& path) = 0; + virtual float sample(int x, int y, int z) const = 0; + virtual Vec3 size() const = 0; +}; + +class OpenVDBLoader : public VolumeLoader { ... }; +class DDSLoader : public VolumeLoader { ... }; +class RawLoader : public VolumeLoader { ... }; +``` + +#### 工作量估计 +- OpenVDB 支持:3-4天 +- DDS 支持:2-3天 +- 统一接口:1-2天 + +--- + +## 六、高级算法 + +### 6.1 重要性采样 + +#### 背景 +根据体积密度分布,在重要区域增加采样密度,在空区域减少采样。 + +#### 方法 + +**1. 基于密度的重要性采样** +```hlsl +// 根据密度调整采样概率 +float pdf = density / totalDensity; +float step = baseStep / pdf; +``` + +**2. 分层采样** +```hlsl +// 将光线分成段,每段内均匀采样 +for each segment: + float randomOffset = rand(); + float samplePos = segmentStart + randomOffset * segmentLength; +``` + +**3. 多重要性采样** +```hlsl +// 结合多种采样策略 +float sampleByDensity = ...; +float sampleByLight = ...; +float weight = misWeight(densityWeight, lightWeight); +``` + +#### 工作量估计 +- 基础实现:3-4天 +- 优化:1周 + +--- + +### 6.2 屏幕空间降噪 + +#### 背景 +低采样率导致的噪点,通过屏幕空间滤波器降噪。 + +#### 算法 + +**1. 双边滤波 (Bilateral Filter)** +```hlsl +float3 bilateralFilter(float2 uv, float3 centerColor, float centerDepth) { + float3 sum = 0; + float weightSum = 0; + + for each neighbor: + float3 neighborColor = sample(neighborUV); + float neighborDepth = sampleDepth(neighborUV); + + float spatialWeight = gaussian(distance); + float rangeWeight = gaussian(length(neighborColor - centerColor)); + float depthWeight = gaussian(abs(neighborDepth - centerDepth)); + + float weight = spatialWeight * rangeWeight * depthWeight; + sum += neighborColor * weight; + weightSum += weight; + + return sum / weightSum; +} +``` + +**2. SVGF (Spatiotemporal Variance-Guided Filtering)** +- Temporal 累积 +- 空间滤波 +- 方差估计 + +**3. BMFR (Blockwise Multi-Order Feature Regression)** +- 块处理 +- 特征回归 + +#### 参考资料 +- Schied, C., et al. "Spatiotemporal Variance-Guided Filtering" (EGSR 2017) + +#### 工作量估计 +- 双边滤波:2-3天 +- SVGF:2-3周 + +--- + +## 七、场景融合 + +### 7.1 体积与场景遮挡 + +#### 问题 +当前体积渲染不考虑场景几何体的遮挡。 + +#### 解决方案 + +**1. 深度测试** +```hlsl +// 从深度缓冲重建世界坐标 +float depth = depthTexture.Sample(sampler, uv); +float3 sceneWorldPos = reconstructWorldPos(uv, depth); + +// 计算到场景的距离 +float sceneDist = length(sceneWorldPos - cameraPos); + +// Ray Marching 时限制最大距离 +float tmax = min(rayTmax, sceneDist); +``` + +**2. 阴影遮挡** +```hlsl +// 场景几何体遮挡体积 +float sceneShadow = 1.0; +if (isOccludedByScene(pos)) { + sceneShadow = 0.0; +} +``` + +#### 工作量估计 +- 深度测试:2-3天 +- 完整遮挡:1周 + +--- + +### 7.2 阴影接收 + +#### 问题 +体积应该接收场景几何体的阴影。 + +#### 解决方案 +```hlsl +float sceneShadow = SampleSceneShadowMap(pos); +float3 S = sigmaS * phase_function() * shadow * sceneShadow; +``` + +#### 工作量估计 +- 基础实现:2-3天 + +--- + +## 八、应用场景 + +### 8.1 动态天气系统 + +#### 功能 +- 云层动态演化 +- 日出日落光照变化 +- 雨雾效果 + +#### 实现 +```hlsl +// 云层演化 +float timeOfDay = sin(time * dayCycleSpeed); +float cloudDensity = baseDensity * (0.5 + 0.5 * timeOfDay); + +// 光照变化 +float3 sunColor = lerp(sunriseColor, noonColor, timeOfDay); +float3 ambientColor = lerp(nightAmbient, dayAmbient, timeOfDay); + +// 雾气 +float fogDensity = fogBase + fogVariation * sin(time); +``` + +#### 工作量估计 +- 1-2周 + +--- + +### 8.2 火焰/爆炸效果 + +#### 需求 +- 温度场驱动 +- 黑体辐射颜色 +- 自发光 + +#### 实现 +```hlsl +// 温度到颜色 (黑体辐射) +float3 temperatureToColor(float T) { + // Planck 定律近似 + float x = T / 10000.0; + float3 color; + color.r = 1.0; + color.g = clamp(1.0 - exp(-5.0 * x), 0, 1); + color.b = clamp(1.0 - exp(-10.0 * x), 0, 1); + return color; +} + +// 发光 +float3 emission = temperatureToColor(temperature) * emissionIntensity; +float3 S = sigmaS * phase_function() * shadow + emission; +``` + +#### 工作量估计 +- 1周 + +--- + +## 九、推荐方案总结 + +### 方案A:渲染深化(学术向) +``` +多散射 + 相函数 + Temporal Reprojection +``` +- 难度:⭐⭐⭐⭐ +- 工作量:4-5周 +- 论文价值:高 +- 适合:想发论文/读研 + +### 方案B:工程完整(展示向) +``` +相机交互 + 参数UI + 多光源 + 大气散射 +``` +- 难度:⭐⭐⭐ +- 工作量:3-4周 +- 展示效果:好 +- 适合:答辩演示 + +### 方案C:离线工具链(创新向) +``` +离线流体模拟器 + OpenVDB集成 + NanoVDB导出 +``` +- 难度:⭐⭐⭐⭐⭐ +- 工作量:6-8周 +- 创新性:强 +- 适合:想深入图形学 + +### 方案D:程序化生成(创意向) +``` +程序化云生成 + 参数控制 + 动态天气 +``` +- 难度:⭐⭐⭐⭐ +- 工作量:3-4周 +- 展示性:强 +- 适合:想展示效果 + +### 方案E:平衡方案(推荐) +``` +多散射 + Temporal Reprojection + 相函数 + 程序化扰动动画 +``` +- 难度:⭐⭐⭐⭐ +- 工作量:4-5周 +- 效果提升明显 +- 有技术深度 +- 工作量可控 + +--- + +## 十、时间规划建议 + +### 单方向深入(4-5周) + +| 阶段 | 内容 | 时间 | +|------|------|------| +| 第1周 | 多散射基础实现 | 7天 | +| 第2周 | 多散射优化 + 相函数 | 7天 | +| 第3周 | Temporal Reprojection | 7天 | +| 第4周 | 程序化扰动 + 效果调优 | 7天 | +| 第5周 | 文档 + 测试 | 7天 | + +### 多方向扩展(6-8周) + +| 阶段 | 内容 | 时间 | +|------|------|------| +| 第1-2周 | 渲染效果提升 | 14天 | +| 第3-4周 | 性能优化 | 14天 | +| 第5-6周 | 交互与控制 | 14天 | +| 第7周 | 效果调优 | 7天 | +| 第8周 | 文档 + 测试 | 7天 | + +--- + +## 十一、参考资料汇总 + +### 论文 +1. Jensen, H. W., et al. "A Practical Model for Subsurface Light Transport" (SIGGRAPH 2001) +2. Kutz, P., et al. "Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes" (SIGGRAPH 2017) +3. Stam, J. "Stable Fluids" (SIGGRAPH 1999) +4. Fedkiw, R., et al. "Visual Simulation of Smoke" (SIGGRAPH 2001) +5. Karis, B. "High Quality Temporal Supersampling" (SIGGRAPH 2014) +6. Schied, C., et al. "Spatiotemporal Variance-Guided Filtering" (EGSR 2017) + +### 书籍 +1. Bridson, R. "Fluid Simulation for Computer Graphics" +2. Ebert, D. S., et al. "Texturing & Modeling: A Procedural Approach" +3. Pharr, M., et al. "Physically Based Rendering: From Theory to Implementation" + +### 开源项目 +1. OpenVDB: https://github.com/AcademySoftwareFoundation/openvdb +2. NanoVDB: https://github.com/AcademySoftwareFoundation/nanovdb +3. Mantaflow: https://mantaflow.uni-mainz.de/ +4. Dear ImGui: https://github.com/ocornut/imgui + +--- + +*文档版本: 1.0* +*更新日期: 2026年3月* \ No newline at end of file