GLM中判定随机点是否在法向量定义的半球上半部分的方法咨询
判断半球内随机点的正确方法
嘿,这个问题我之前写光线追踪代码的时候也纠结过,咱们来好好理一理:
首先得明确——你提到的|N + P| ≥ 1这个判断方法是不正确的,原因很直观:
假设N和P都是单位向量(毕竟半球上的点一般都是归一化后的单位向量),咱们把模长的平方展开算一下:
|N + P|² = |N|² + 2*(N·P) + |P|² = 1 + 2*(N·P) + 1 = 2*(1 + N·P)
如果|N + P| ≥ 1,平方后就得到2*(1 + N·P) ≥ 1,换算一下就是N·P ≥ -0.5。这意味着P和N的夹角最大能到120度,这可比半球定义的90度范围宽多了,会把很多明明不在上半球的点都误判进来,完全不符合你的需求。
那正确的判断方式是什么呢?其实很简单,用向量点积就搞定了:
半球的核心定义是「所有与法向量N的夹角≤90度的点」,而两个单位向量的点积等于它们夹角的余弦值。当N·P ≥ 0时,说明夹角的余弦值非负,也就是夹角≤90度,这时候P就肯定在N定义的上半球里。
要是担心浮点计算的精度误差(比如刚好在半球边界上的点因为精度问题被误判),可以稍微放宽一点条件,比如判断N·P ≥ -1e-6,给个极小的容错空间。
至于GLM里的实现,那就更方便了,直接用GLM内置的点积函数就行:
// 假设N和P都是glm::vec3类型的单位向量 bool isInUpperHemisphere = glm::dot(N, P) >= 0.0f; // 带浮点精度容错的版本(推荐) const float epsilon = 1e-6f; bool isInUpperHemisphere = glm::dot(N, P) >= -epsilon;
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

