C++中逻辑||运算处理机制及视锥体剔除代码优化疑问
C++逻辑||的短路求值机制及视锥体剔除实现对比
核心问题解答
C标准明确规定,逻辑或运算符||采用短路求值策略:只要表达式链中出现第一个true结果,就会立即终止后续所有子表达式的计算,直接返回true。所有符合C标准的编译器都会遵循这一行为,不会执行后续判断逻辑。
视锥体剔除场景的等价性分析
你提到的两种视锥体剔除实现(连续if+continue和多||的单个if)在执行逻辑和性能上完全等价:
- 连续
if版本中,只要某一个顶点满足点积>=0的条件,就会触发continue跳过当前平面的剩余顶点判断; - 多
||的if版本中,||的短路求值会在第一个满足条件的顶点判断后停止计算,直接进入continue逻辑。
两种写法没有性能差异,选择哪种完全取决于代码可读性和个人编码习惯。
代码实现展示
仅使用if语句的版本
for (int i = 0; i < 6; i++) { if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-r, yC-r, zC-r})) >= 0.0f) continue; if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-r, yC-r, zC+r})) >= 0.0f) continue; if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-r, yC+r, zC-r})) >= 0.0f) continue; if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-r, yC+r, zC+r})) >= 0.0f) continue; if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+r, yC-r, zC-r})) >= 0.0f) continue; if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+r, yC-r, zC+r})) >= 0.0f) continue; if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+r, yC+r, zC-r})) >= 0.0f) continue; if (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+r, yC+r, zC+r})) >= 0.0f) continue; return false; }
使用单个含多个||的if语句版本
for (int i = 0; i < 6; i++) { if ((DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-rX, yC-rY, zC-rZ})) >= 0.0f) || (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-rX, yC-rY, zC+rZ})) >= 0.0f) || (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-rX, yC+rY, zC-rZ})) >= 0.0f) || (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC-rX, yC+rY, zC+rZ})) >= 0.0f) || (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+rX, yC-rY, zC-rZ})) >= 0.0f) || (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+rX, yC-rY, zC+rZ})) >= 0.0f) || (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+rX, yC+rY, zC-rZ})) >= 0.0f) || (DirectX::XMVectorGetX(DirectX::XMPlaneDotCoord(DirectX::XMLoadFloat4(&frustumPlanes[i]), {xC+rX, yC+rY, zC+rZ})) >= 0.0f)) continue; return false; }
额外优化建议
如果追求极致性能,可以提前预计算立方体的8个顶点坐标并存储到数组中,通过循环遍历顶点减少代码冗余;另外DirectX的SIMD指令支持批量计算,也可以考虑一次性计算多个顶点的点积,进一步提升剔除效率。
内容的提问来源于stack exchange,提问作者Atryx10
相关产品推荐
相关产品推荐

