当前位置: 首页 > news >正文

光照解耦和重照明

项目地址:

GitHub - NJU-3DV/Relightable3DGaussian: [ECCV2024] 可重新照明的 3D 高斯:使用 BRDF 分解和光线追踪的实时点云重新照明

可优化参数

gaussians.training_setup(opt)

if is_pbr:: direct_env_light.training_setup(opt)

光照解耦

update_visibility

分块处理高斯

对每个高斯体,采样 sample_num 个入射方向,计算每个方向的可见性(是否被遮挡)、方向向量、该方向在球面上的面积权重,并将这些结果保存下来

 fibonacci_sphere_sampling斐波那契球面采样

输出

  1. incident_dirs:每个点/法线的 sample_num 个采样方向(单位向量),用于模拟不同角度的入射光。
  2.  normals 是 [N, 3],则输出 incident_dirs 是 [N, sample_num, 3]
  3. incident_areas:每个采样方向的面积权重(都相同),用于积分时加权。
  4. incident_dirs形状[N, sample_num, 1]

在 fibonacci_sphere_sampling 代码中,采样方向是围绕每个高斯体的法线方向生成的:

  • 首先在 z 轴方向上生成均匀分布的球面采样(fibonacci sphere)。
  • 然后通过旋转,把这些方向对齐到每个高斯体的法线方向(rotation_between_z(normals))。
  • 如果 random_rotate=True,还会加上一个随机旋转,使得每个高斯体的采样方向分布更加均匀、随机。

rotation_matrix = rotation_between_z(normals)

incident_dirs = rotation_matrix @ z_samples

  • 这里 rotation_matrix 是针对每个高斯体的法线单独计算的。
  • 所以 incident_dirs 是每个高斯体独立的一组方向。

render(is_training=true)

render_pkg = render_fn(viewpoint_cam, gaussians, pipe, background,opt=opt, is_training=True, dict_params=pbr_kwargs, iteration=iteration)pbr_kwargs['sample_num'] = pipe.sample_num#64pbr_kwargs["env_light"] = direct_env_light

高斯增加优化属性

  1. _base_color:表面基础色(反射率/漫反射色),PBR渲染的核心属性。
  2. _roughness:表面粗糙度,影响高光和反射的模糊程度。
  3. _incidents_dc/incidents_rest:每个高斯体的入射光照分布(用球谐函数表示),用于高效地近似全局光照。
  4. _visibility_dc/visibility_rest:每个高斯体的可见性分布(同样用球谐函数表示),用于阴影和遮挡的近似。
 first_iter = gaussians.create_from_ckpt(args.checkpoint, restore_optimizer=True)

 初始化这些属性为0

环境光照(IBL - Image-Based Lighting)​

  • 模拟全局光照​:环境贴图存储了来自各个方向的环境光强度与颜色,为物体表面提供非直接光照(如漫反射、镜面反射)。
  • PBR 材质依赖​:在基于物理的渲染中,环境贴图是计算材质反射、折射的基础输入(如金属高光、玻璃透射)

PBR最终像素颜色和渲染方程Rendering equation

 参考彻底看懂PBR/BRDF方程 - 张亚坤的文章 - 知乎
https://zhuanlan.zhihu.com/p/158025828

 base_color:点云的“固有色”。

 pbr:这个点在当前光照、视角、材质等条件下,真实应该呈现出来的颜色。

pbr​:最终像素颜色(Lambert 漫反射 + GGX 镜面反射)

输出结果brdf_color和extra_results

    extra_results = {"incident_dirs": incident_dirs,"incident_lights": incident_lights,"local_incident_lights": local_incident_lights,"global_incident_lights": global_incident_lights,"incident_visibility": incident_visibility,"diffuse_light": diffuse_light,"specular": specular,}

基于物理的渲染方程(PBR)​​:

其中:

    f_d = base_color[:, None] / np.pi

    f_s = GGX_specular(normals, viewdirs, incident_dirs, roughness, fresnel=0.04)

  • Lo​:出射光(最终颜色)
  • fdiffuse​:漫反射 BRDF
  • fspecular​:镜面反射 BRDF
  • Li​:入射光强度
  • n⋅ωi​:​余弦项​(法线与入射光方向的点积)

diffuse_light = transport.mean(dim=-2):: 表示表面接收到的总光照强度

rasterizer结果

变量名说明典型形状
num_rendered渲染的高斯点总数标量/int
num_contrib每像素有贡献的高斯点数[H, W]
rendered_image渲染出的RGB图像[3, H, W]
rendered_opacity渲染出的不透明度图[1, H, W]
rendered_depth渲染出的深度图[1, H, W]
rendered_feature渲染出的特征图(多通道)[C, H, W]
rendered_pseudo_normal渲染出的伪法线图[3, H, W]
rendered_surface_xyz渲染出的表面3D坐标[3, H, W]
weights高斯点对像素的贡献权重[N, H, W]
radii高斯点在屏幕上的半径[N]

render输出results

feature和rendered_image、rendered_pbr

   if is_training:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness, extra_results["diffuse_light"], extra_results["incident_visibility"].mean(-2)], dim=-1)else:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness,extra_results["diffuse_light"], extra_results["specular"], extra_results["incident_lights"].mean(-2),extra_results["local_incident_lights"].mean(-2),extra_results["global_incident_lights"].mean(-2),extra_results["incident_visibility"].mean(-2)], dim=-1)

 在gaussian_renderer\neilf.py里的render_view

 在gaussian_renderer\r3dg_rasterization.py中

num_rendered, num_contrib, color, opacity, depth, feature, normal, surface_xyz, weights, radii, geomBuffer, binningBuffer, imgBuffer = _C.rasterize_gaussians(*args)

在r3dg-rasterization\ext.cpp中

 在r3dg-rasterization\rasterize_points.cu中

return std::make_tuple(
rendered, n_contrib, out_color, out_opacity, out_depth, out_feature, out_normal, out_surface_xyz, out_weights, radii, geomBuffer, binningBuffer, imgBuffer);

与 下图一一对应

num_rendered, num_contrib, color, opacity, depth, feature, normal, surface_xyz, weights, radii, geomBuffer, binningBuffer, imgBuffer = _C.rasterize_gaussians(*args)

在r3dg-rasterization\cuda_rasterizer\forward.cu中 

rendered_image:是通过球谐函数(Spherical Harmonics, SH)渲染得到的图像,即上图中的out_color

rendered_pbr:是通过物理基础渲染(Physically Based Rendering, PBR)得到的图像,即上图中的out_feature(对应render_feature)中的一部分

pbr = rendered_pbr
rendered_pbr = pbr * rendered_opacity + (1 - rendered_opacity) * bg_color[:, None, None]

out_feature(对应render_feature)由features加权得出,rendered_pbr对应由brdf_color加权

   if is_training:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness, extra_results["diffuse_light"], extra_results["incident_visibility"].mean(-2)], dim=-1)else:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness,extra_results["diffuse_light"], extra_results["specular"], extra_results["incident_lights"].mean(-2),extra_results["local_incident_lights"].mean(-2),extra_results["global_incident_lights"].mean(-2),extra_results["incident_visibility"].mean(-2)], dim=-1)

 

重照明relighting.py

 文件路径变量
scene_config_file
路径:{args.config}/transform.json
作用:场景的空间变换配置文件,通常描述每个子场景或物体的变换矩阵(如平移、旋转、缩放)。
traject_config_file
路径:{args.config}/trajectory.json
作用:相机轨迹配置文件,通常描述渲染时相机的运动路径、每一帧的相机参数等。
light_config_file
路径:{args.config}/light_transform.json
作用:光源轨迹或光照变换配置文件,描述光源的位置、方向、变化等(如果有动态光照)。

 `scene_composition`

功能

scene_composition 的作用是:
将多个场景(或点云)的高斯体模型合成为一个整体高斯体模型,并做必要的初始化。

具体流程如下:

  1. 遍历 scene_dict,为每个子场景加载高斯体点云(.ply 文件),并应用相应的变换(transform),把每个子场景的点云(高斯体)通过指定的 4x4 变换矩阵变换到全局坐标系,。

  2. 把所有加载好的高斯体模型合成为一个大模型(调用 GaussianModel.create_from_gaussians)。

  3. 对合成后的模型做一些初始化(如可见性、入射光参数等)。

  4. 返回合成后的高斯体模型。


输入

  • scene_dict: dict

    • 字典格式,key 是场景名,value 是一个字典,包含:

      • "path":点云文件路径(.ply)

      • "transform":4x4 的变换矩阵(list 或 array)

  • dataset: ModelParams

    • 数据集参数对象,至少包含 sh_degree 等高斯体模型初始化所需参数。


输出

  • gaussians_composite: GaussianModel

    • 合成后的高斯体模型对象,包含所有子场景的点云和参数,已经应用了各自的变换,并做了初始化。


代码流程简述

  1. 加载每个子场景的高斯体模型并变换

    for scene in scene_dict:gaussians = GaussianModel(dataset.sh_degree, render_type="neilf")gaussians.load_ply(scene_dict[scene]["path"])torch_transform = torch.tensor(scene_dict[scene]["transform"], device="cuda").reshape(4, 4)gaussians.set_transform(transform=torch_transform)gaussians_list.append(gaussians)
    
  2. 合成所有高斯体模型

    gaussians_composite = GaussianModel.create_from_gaussians(gaussians_list, dataset)
    
  3. 初始化可见性和入射光参数

    n = gaussians_composite.get_xyz.shape[0]
    gaussians_composite._visibility_rest = (torch.nn.Parameter(torch.cat([gaussians_composite._visibility_rest.data,torch.zeros(n, 5 ** 2 - 4 ** 2, 1, device="cuda", dtype=torch.float32)],dim=1).requires_grad_(True)))
    gaussians_composite._incidents_dc.data[:] = 0
    gaussians_composite._incidents_rest.data[:] = 0
    
  4. 返回合成后的模型

    return gaussians_composite
    

总结

  • 功能:合成多个高斯体点云为一个整体,并初始化相关参数。

  • 输入:场景字典(含路径和变换)、数据集参数。

  • 输出:合成后的高斯体模型对象(GaussianModel)。

render(is_training=false)

render_kwargs = {"pc": gaussians_composite,"pipe": pipe,"bg_color": background,"is_training": False,"dict_params": {"env_light": light,"sample_num": args.sample_num,#384},"bake": args.bake}
with torch.no_grad():render_pkg = render_fn(viewpoint_camera=custom_cam, **render_kwargs)

在 render_view 函数中,is_training 参数为 True 或 False 时,渲染流程和输出内容有明显区别is_training 为 True 时,流程更高效、特征更精简、用于训练和损失计算;为 False 时,流程更全面、特征更丰富、用于推理、评估和可视化。

主要体现在以下几个方面:


1. BRDF 计算方式不同

  • is_training=True
    • 直接对所有点一次性调用 rendering_equation,效率高,适合训练时的批量处理。
    • 代码片段:
      if is_training:brdf_color, extra_results = rendering_equation(base_color, roughness, normal.detach(), viewdirs, incidents,direct_light_env_light, visibility_precompute=pc._visibility_tracing, incident_dirs_precompute=pc._incident_dirs, incident_areas_precompute=pc._incident_areas)
      
  • is_training=False
    • 为了节省显存,采用分块(chunk)处理,每次只处理一部分点,适合测试/推理时大规模渲染。
    • 代码片段:
      else:chunk_size = 100000brdf_color = []extra_results = []for i in range(0, means3D.shape[0], chunk_size):_brdf_color, _extra_results = rendering_equation(...)brdf_color.append(_brdf_color)extra_results.append(_extra_results)brdf_color = torch.cat(brdf_color, dim=0)extra_results = {k: torch.cat([_extra_results[k] for _extra_results in extra_results], dim=0) for k in extra_results[0]}torch.cuda.empty_cache()
      

2. 特征拼接内容不同

  • is_training=True

    • 拼接的特征较少,只包含训练所需的内容。

    • 代码片段:
      features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness, extra_results["diffuse_light"], extra_results["incident_visibility"].mean(-2)], dim=-1)
      
  • is_training=False

    • 拼接的特征更丰富,包含更多渲染细节,便于评估和可视化。

    • 代码片段:
      features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness,extra_results["diffuse_light"], extra_results["specular"], extra_results["incident_lights"].mean(-2),extra_results["local_incident_lights"].mean(-2),extra_results["global_incident_lights"].mean(-2),extra_results["incident_visibility"].mean(-2)], dim=-1)
      

3. 输出的特征拆分不同

  • is_training=True

    • rendered_feature 只拆分出训练所需的特征(如 base_color、roughness、diffuse、visibility)。

  • is_training=False

    • rendered_feature 拆分出更多特征(如 specular、lights、local_lights、global_lights 等),便于评估和可视化。


4. 环境光相关输出不同

  • is_training=False

    • 还会输出 render_envpbr_envenv_only 等环境光相关的渲染结果,便于评估不同光照下的表现。

  • is_training=True

    • 这些环境光相关的输出不会被计算,节省计算资源。


5. 损失计算

  • is_training=True

    • 会进一步调用 calculate_loss 计算损失和训练日志。

  • is_training=False

    • 不计算损失,只输出渲染结果。


总结表

is_training

主要用途

BRDF计算

特征拼接

输出内容

损失计算

评估/可视化

True

训练

一次性

精简

精简

False

推理/评估

分块

丰富

丰富


render输出results

评估 

  • train.py 的评估是为了训练过程中的监控和调优,通常和训练流程绑定。
  • eval_nvs.py 是专门为独立评测和论文展示设计的,方便单独运行和批量评测。

 

http://www.dtcms.com/a/264994.html

相关文章:

  • 接口测试用例设计
  • Shader Graph学习——屏幕uv采样
  • 智能学号抽取系统 V3.7.5 —— 一个基于 Vue.js 的交互式网页应用
  • Arduino CH552 PWM的使用
  • 项目开发基本流程
  • 深入理解Unicode:字符编码的终极指南
  • RGB下的色彩变换:用线性代数解构色彩世界
  • vue3 JavaScript localeCompare 比较两个字符串 localeCompare is not a function
  • 如何将文件从 iPhone 传输到 Android(新指南)
  • Spring Boot 集成 GeoTools 详解
  • 昇腾机器节点磁盘状态检查与问题处理方法
  • 智能攻击原理和架构
  • 深入Flink核心概念:解锁大数据流处理的奥秘
  • vue-36(为组件编写单元测试:属性、事件和方法)
  • 【Linux】Rocky Linux 安装教程
  • vscode基本使用
  • armv8汇编码分析
  • QGIS+CesiumIon
  • 多模态进化论:GPT-5V图文推理能力在工业质检中的颠覆性应用
  • 媲美 GPT-4o,Kontext 实现高效文本驱动图像编辑
  • vscode、openocd 使用
  • Excel 如何让数据自动按要求排序或筛选?
  • Learning PostgresSQL读书笔记: 第16章 Configuration and Monitoring
  • PostgreSQL大表创建分区实战
  • Arduino CH552 ADC的使用
  • NumPy 或 PyTorch/TensorFlow 中的张量理解
  • Servlet开发流程(包含IntelliJ IDEA项目添加Tomcat依赖的详细教程)
  • 【论文阅读】DeepEyes: Incentivizing “Thinking with Images” via Reinforcement Learning
  • 【新手小白的嵌入式学习之路】-STM32的学习_GPIO 8种模式学习心得
  • JavaWeb笔记03