Box Projected Cubemap Environment Mapping

本文探讨了立方体映射技术的发展历程,介绍了其在现代游戏中的三种主要应用:天空盒渲染、点光源阴影图及环境探针。重点讨论了立方体环境映射模拟实时反射的实现方式,并提出了修正传统映射误差的方法。

         立方体映射于1986年首次斯内德格林在他的论文“环境映射和预测世界其他应用程序”提出[ 2 ]吉姆·博林马丁·纽厄尔十年之后首次提出环境映射了。然而由于硬件在同时访问6纹理图像的能力限制,使其一直没有得以在实际中使用。随着Nvidia 的GeForce 256的发布这个问题彻底解决。。Nvidia的立方体映射硬件“是GeForce 256一个突破性的功能。它将允许开发人员创建精确的,实时的反射。

    在现代的任何一款游戏里CubeMap随处可见,大致分为三种用法:

 1.天空盒渲染

 2.用于点光源的shadowmap

 3.Env Probe(GI)

 4.模拟实时反射(Cubemap Environment Mapping)

这次讨论的重点是模拟反射,Cubemap Environment Mapping简单来说就是用一个虚拟的立方体(cube)包围住物体,我们需要一个类似天空盒般的6张纹理贴在这个虚拟的立方体上,按照X,Y,Z轴正负方向构建4个Camera,分别对场景进行拍照,每一张图片贴到Cube的一个面上,这就完成了CubeMap的生成。




下面就可以考虑如何将Cube上的像素映射到物体上,方法很直接了当:眼睛到某个像素的向量look经过反射(以x像素的法线进行反射),反射向量reflvec射到立方体上,就在该立方体上获得一个纹素了(见下图中的Original的ray)。这就是一般的传统的Cubemap Environment Mapping。

然而按照上面的做法会感觉反射和真实场景无法匹配上。


传统的环境映射


Parallax Error

针对这样的情况,有人提出了一种修正方法来解决这个问题,将Cube的实际尺寸记录下来,用反射的ray来和cube求交,这样就可以得到真正正确的映射像素了,看起来这个方法原理上很简单,但是也是经过Cubemap用了好多年后才提出的,修正后的原理图如下:最终的效果非常不错,感觉质量上直接上了一个档次,而这个做法本身也很cheap,性价比相当高

Posted Image

img1

img2

下面给出PS里计算ray和cube相交然后用这个corrected的向量采cubemap的代码。


float3 dir = WrlPos - CamPos;
float3 rdir = reflect(dir, WrlTexNorm);

//BPCEM
float3 nrdir = normalize(rdir);
float3 rbmax = (EnvBoxMax - WrlPos)/nrdir;
float3 rbmin = (EnvBoxMin - WrlPos)/nrdir;

float3 rbminmax = (nrdir>0.0f)?rbmax:rbmin;
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);

float3 posonbox = WrlPos + nrdir*fa;
rdir = posonbox - EnvBoxPos;
//PBCEM end

float3 env = texCUBE(envMap, rdir);

也可以对照原始链接结合一起看看。这个方法在Remember Me里得到了实际应用,Remember me的反射效果相当不错,基本原理就是从这里来的。

https://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/


### ROS2 中因 DURABILITY_QOS_POLICY 导致的消息无法发送问题解决方案 在 ROS2 的通信机制中,`/projected_map` 主题上的新发布者如果遇到 `DURABILITY_QOS_POLICY` 不兼容的情况,可能会导致消息无法被订阅者接收。这是因为 `DURABILITY_QOS_POLICY` 定义了数据持久性的行为[^1]。 #### 什么是 DURABILITY_QOS_POLICY? `DURABILITY_QOS_POLICY` 是一种服务质量策略 (Quality of Service, QoS),用于指定节点如何处理历史数据。它有两个主要选项: - **VOLATILE**:表示发布的数据仅对当前活动的订阅者可见。 - **TRANSIENT_LOCAL**:表示发布的数据会被缓存一段时间,以便后续加入的新订阅者可以接收到这些数据[^2]。 当发布者和订阅者的 `DURABILITY_QOS_POLICY` 设置不一致时,ROS2 将认为它们之间存在 QoS 不匹配,从而阻止两者之间的通信。 --- #### 解决方案 以下是几种可能的解决方法: 1. **统一设置 DURABILITY_QOS_POLICY** 发布者和订阅者应具有相同的 `DURABILITY_QOS_POLICY` 配置。可以通过显式配置 QoS 参数来实现这一点。例如,在 Python 和 C++ 节点中分别进行如下操作: - **Python 实现**: ```python import rclpy from rclpy.qos import QoSDurabilityPolicy, QoSProfile qos_profile = QoSProfile( durability=QoSDurabilityPolicy.TRANSIENT_LOCAL, depth=10 ) node = rclpy.create_node('my_node') publisher = node.create_publisher(String, '/projected_map', qos_profile=qos_profile) ``` - **C++ 实现**: ```cpp #include "rclcpp/rclcpp.hpp" using namespace rclcpp::qos; auto qos_profile = rclcpp::QoS(10).durability(DurabilityPolicy::TRANSIENT_LOCAL); this->create_publisher<std_msgs::msg::String>("/projected_map", qos_profile); ``` 这种方式通过强制双方采用相同的服务质量参数解决了不兼容问题[^3]。 2. **调整默认 QoS 策略** 如果不想手动修改每处代码中的 QoS 设置,可以在启动文件或 `.yaml` 文件中全局定义默认的 QoS 策略。例如: ```yaml /talker: ros__parameters: qos_overrides: /projected_map/publisher: durability: transient_local ``` 3. **启用自动适配功能** 使用 `rmw_qos_profile_sensor_data` 或其他预设的 QoS 配置文件作为起点,允许系统尝试动态协商兼容性。这种方法适用于某些特定场景下的传感器数据传输需求[^4]。 4. **调试工具辅助排查** 利用 `ros2 topic echo --qos-profile <profile_name>` 命令测试不同 QoS 配置下 `/projected_map` 是否能够正常工作。此外还可以借助 `rtiddsspy` 工具监控底层 DDS 层面的数据流动情况以进一步验证问题根源所在[^5]。 --- ### 总结 针对 `/projected_map` 上由于 `DURABILITY_QOS_POLICY` 不兼容引起的消息丢失现象,推荐优先考虑同步发布方与接收端所使用的具体策略设定;其次可探索利用更高层次抽象层面上所提供的灵活定制能力完成相应调整优化过程。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值