毕设做的是《基于四叉树的LOD地形渲染》,其中主要参考了潘李亮的《基于LOD的大规模真实感室外场景试试渲染技术的初步研究》一文,如有有兴趣做四叉树LOD的话,建议读一读这篇文章。但是在这篇文章的视椎体裁剪部分,说的不是很清除,而且在求解视椎体六个面的方程和判断AABB包围盒的与视椎体是否相交的方法上,不知道是我的理解问题还是他的实现有问题,裁剪出的结果总是有问题,查阅资料后,给出我的详细实现。

视椎体六个面方程的求解

在进行视椎体体剔除时,要求出视椎体六个面在局部坐标系中的方程才能进行判断。求解视椎体六个面的方程这篇文章给出了非常好的说明。此处就直接以来上文中的方法来说明吧。在进行了投影变换后,视椎体从平截头体变成了一个正方体(NDC规范化坐标),正方体的xyzzuo坐标都是(-1,1)之间。

假设空间中一点P(x,y,z,1)经过这一系列变换变成P1(x1/w1,y1/w1,z1/w1,1) 并且假设ProjectMatrix左乘ModelViewMatrix得到的第一行是(a,b,c,d),那么有

a*x+b*y+c*z+d=x1

假设变换矩阵的最后一行(e,f,g,h),那么有

e*x+f*y+g*z+h=w1

因为P1在NDC坐标系,范围是-1到1,那么在视景体左面上的点都符合x1/w1=-1,式子可以变为x1+w1=0

代入之前的等式:

a*x+b*y+c*z+d+e*x+f*y+g*z+h=0

于是得到:

(a+e)*x+(b+f)*y+(c+g)*z+(d+h)=0

一般的平面方程是:

A*x+B*y+C*z+D=0 (A,B,C)是平面的法向量

于是左侧平面的方程就是

(a+e)*x+(b+f)*y+(c+g)*z+(d+h)=0 其中的x,y,z就是空间中的点坐标。

以上是理论基础,具体各个面的方程计算方法如下(假设矩阵clip=project*view*model。下面的clip[n]代表clip矩阵的第几列,nomalize代表将向量进行归一化,即将向量的模长变为1):

上平面:nomalize(clip[3]-clip[1])下平面:nomalize(clip[3]+clip[1])左平面:nomalize(clip[3]+clip[0])右平面:nomalize(clip[3]-clip[0])近平面:nomalize(clip[3]+clip[2])远平面:nomalize(clip[3]-clip[2])

注意,以上计算的得到的结果是一个四维向量,向量中的xyzw值分别代表一个平面方程Ax+By+Cz+D=0中的A、B、C、D的值。另外需要注意的是,平面方程Ax+By+Cz+D=0中的(A,B,C)代表的是该平面的法向量,而且通过上式计算出的法向量(A,B,C)都是指向视椎体内部的。(指向外部也可以只需要Ax+By+Cz+D=0变成-Ax-By-Cz-D=0即可,此时法向量就是(-A,-B,-C))。

视椎体裁剪

视椎体裁剪就是将不在视椎体中的物体剔除掉不绘制,而在视椎体内部或与视椎体相交的物体绘制的方法,此举对性能的提升有着巨大 的帮助。通常,物体是不规则的,为了方便,我们通常制作一个包围体,判断包围体与视椎体的关系。包围体一般有球体和长方体两种。球包围体的判断非常简单,只需要判断球心到视椎体每个面的距离与半径的关系,此处不予讨论。主要说明长方体的判断,这也正是我认为潘李亮大神论文中有错误的地方。

首先说明,如何判断一个点在平面的某一侧的方法:已知平面方程为Ax+By+Cz+D=0,将一个点P(x,1y1,z1)的坐标带入平面方程得r=Ax1+By1+Cz1+D,如果计算结果r>0,,则表示P在法向量(A,B,C)指向的一侧,同理,r<0,表示在法向量的另一侧。潘李亮大神的判断正是基于此,将长方体包围盒的顶点带入视椎体六个面的方程,如果计算得到的六个值都大于0,则表示该点在视椎体内。通过这种方法,只要长方体包围盒的8个顶点有一个顶点在视椎体内,就说明实际物体模型能看得见,就需要绘制。但是这个方法有一个致命的缺陷,就是有些长方体的8个顶点全在视椎体外,但长形体仍然与视椎体有交集,不能被剔除,如下图所示,黄色长方体不应该剔除,但是用上述方法就会被错误剔除。另一种情况是,长方体包围盒很大,视椎体在长方体内部,也会被错误剔除,我用这种方法就是有一些地形块被错误剔除渲染不出来。

下面说查阅到的正确方法:判断时,只有当长方体所有的顶点位于同一平面的外侧时,才认为这个长方体包围盒在视椎体外面。这样会将一些在视椎体外面的包围盒错误的判断成在与视椎体有交集,但是数量很少,可以接受。下面给出程序实现:

bool IsVisable()
{glm::vec3 coner[8];//通过xyz最大最小值构造AABB包围盒coner[0].x = minx; coner[0].y = miny; coner[0].z = minz;coner[1].x = maxx; coner[1].y = miny; coner[1].z = minz;coner[2].x = maxx; coner[2].y = miny; coner[2].z = maxz;coner[3].x = minx; coner[3].y = miny; coner[3].z = maxz;coner[4].x = minx; coner[4].y = maxy; coner[4].z = minz;coner[5].x = maxx; coner[5].y = maxy; coner[5].z = minz;coner[6].x = maxx; coner[6].y = maxy; coner[6].z = maxz;  coner[7].x = minx; coner[7].y = maxy; coner[7].z = maxz;int in,out;for (int i = 0; i < 6;i++){in = out = 0;for (int k = 0; k < 8 && (in == 0 || out == 0);k++){if ((m_frustum[i].x*coner[k].x + m_frustum[i].y* coner[k].y + m_frustum[i].z*coner[k].z + m_frustum[i].w)>=0)in++;elseout++;}if (!in)return false;elsereturn true;}
}

这样,视椎体裁剪就完成了,如有错误,欢迎批评指正。

毕设快做完了,其中遇到了挺多问题,等答辩结束了将整个四叉树LOD的构造过程写一个系列博客吧。

OpenGL视椎体 裁剪和剔除相关推荐

  1. DirectX11进阶5_硬件实例化与视锥体裁剪及鼠标拾取交互

    一.硬件实例化(Hardware Instancing) 硬件实例化指的是在场景中绘制同一个物体多次,但是是以不同的位置.旋转.缩放.材质以及纹理来绘制(比如一棵树可能会被多次使用以构建出一片森林). ...

  2. Cesium卫星视椎体(四棱锥体)

    Cesium卫星视椎体(四棱锥体) 效果图 效果图 详情参见 Cesium实战项目

  3. Unity HybridRender 视锥体裁剪

    Unity HybridRender 使用Unity.Rendering.FrustumPlanes 结构体来实现视锥体裁剪.这个结构体基本都为静态函数,其中使用NativeArray<Plan ...

  4. 基于 React hooks + Typescript + Cesium 绘制四棱锥(视椎体)

    文章目录 效果截图 功能介绍 实现思路 实现步骤 安装 react-dat-gui 库 创建四棱锥 根据参数面板更新视椎体参数 整体代码 效果截图 先上截图: 功能介绍 本例子基于 React hoo ...

  5. Cesium|xt3d 卫星视椎体(四棱锥体)

    Cesium|xt3d 卫星视椎体(四棱锥体) 效果 代码 预览地址 效果 代码 <!DOCTYPE html> <html lang="zh-CN">&l ...

  6. DirectX11 With Windows SDK--20 硬件实例化与视锥体裁剪

    DirectX11 With Windows SDK--20 硬件实例化与视锥体裁剪 原文:DirectX11 With Windows SDK--20 硬件实例化与视锥体裁剪 前言 这一章将了解如何 ...

  7. OpenGL 视景体裁剪

    视锥体(frustum),是指场景中摄像机的可见的一个锥体范围.它有上.下.左.右.近.远,共6个面组成.在视锥体内的景物可见,反之则不可见.为提高性能,只对其中与视锥体有交集的对象进行绘制.我们计算 ...

  8. 视锥体裁剪(从矩阵中提取6个裁剪面)

    视锥体(frustum),是指场景中摄像机的可见的一个锥体范围.它有上.下.左.右.近.远,共6个面组成.在视锥体内的景物可见,反之则不可见.为提高性能,只对其中与视锥体有交集的对象进行绘制. 视锥体 ...

  9. OpenGL基础32:面剔除

    一个标准的立方体总共6个面,对于每个面又有里外之分,因此若要绘制一个正方形的话,总共需要绘制12个面,然而事实上,对于每个面,在玩家视角一定只能看到它的一个朝向 换句话说,对于一个六个面的正方体,我们 ...

最新文章

  1. spring源码之—Assert.notNull
  2. oracle 11g rac手册(第2版) 高清,Oracle Database11g RAC手册(第2版)_IT教程网
  3. Xamarin.Forms教程开发的Xcode的下载安装
  4. 大厂没有方法论(上)
  5. 「12306奇葩验证码」反例背后的产品观
  6. 获取用户精准地理位置信息(百度地图)
  7. 一些常见http状态码
  8. Hadoop日常管理与维护
  9. 神龙架构没那么难理解—图解世界领先的阿里云神龙架构(二)神龙出世
  10. Linux sed 替换第一次出现的字符串
  11. IOS自己主动布局中的浮动布局(6)----MyFloatLayout横空出世
  12. cublas中执行矩阵乘法运算的函数 首先要注意的是cublas使用的是以列为主的存储方式,和c/c++中的以行为主的方式是不一样的。处理方法可参考下面的注释代码
  13. 如何在线修改图片分辨率?怎么调整300dpi分辨率?
  14. discuz二次开发 教你识别程序目录和文件列表
  15. 一点小感受:界面和程序的分离
  16. Hi3518的uboot中播放音频
  17. ES索引数据迁移 _reindex
  18. 计算机必记快捷键,26个超实用电脑快捷键分享,电脑新手必备!
  19. 使用linux c开源库libwebsockets编写的websocket客户端
  20. 外网访问Newifi路由器Web、SSH、Samba

热门文章

  1. 安天防线 2008 v6.0.8 免费下载
  2. 木马防线:一切木马都是纸老虎(中)(转)
  3. OpenMP入门及基本用法
  4. 模拟技术可以预测喷气发动机用合金材料在制造前的微观结构
  5. axure element ui素材_【Axure分享】基于Element UI的Axure Web组件
  6. 2022-4-16 基于单片机的PM2.5检测报警设计(传感器)
  7. 2020年第十二届数学竞赛初赛(非数学)填空题解析
  8. 天相投顾这么看新钢钒
  9. 阅读书《电子电路原理》截取的一些最核心的思想,找了个课程上海交通大学 郑益慧主讲做辅助(保证基本的理解是对的)。电路要以基本特性为基础从设计角度理解
  10. 无盘服务器一个千兆网卡,网吧无盘上千兆网卡显示成百兆怎么解决?千兆网线打法!...