OpenGL 圆环绘制展示问题解决--正背面剔除,深度测试

渲染中出现的问题

我们通过默认光源着色器绘制圆环后,旋转圆环发现出现黑色部分,黑色相当于光源无法照射到的面即背面,也就是说在旋转过程中,OpenGL将背面的三角形覆盖到正面的三角形之上.


绘制圆环

旋转后

解决办法

1.油画算法
油画算法绘制过程

如上图 油画算法会先对三角形进行排序,先绘制较远的三角形,然后在绘制较近的,这样我们不需要看的部分三角形面就会被需要我们看的图形所遮挡,上面圆环旋转绘制中背面出现的问题也可以得到解决

交叉问题

局限性 :

  • 如上图 几个三角形交叉,计算机无法计算三角形远近
  • 效率低下,重叠部分像素需要进行多次改变,三角形排序开销过高
  • 不推荐使用
2.正背面剔除

换一个思路,如果计算机可以直接知道哪一个三角形在正面,背面的直接不绘制岂不是美哉,答案是当然可以了,在OpenGL中我们通过判断三角形的顶点链接方向来确定它在正面还是背面

  • 正⾯: 按照逆时针顶点连接顺序的三⻆形⾯
  • 背⾯: 按照顺时针顶点连接顺序的三⻆形⾯


    正方体中的正背面

    结合观察者的位置综合判断,如上图中的观察者移动到左侧时,左边的三角形在观察者眼中又变成逆时针链接即为正面.当然这是默认的规则,开发者也可以随意更改,但是要注意的是OpenGL是一个状态机当你在一个地方更改了规则后可能会对其他地方造成影响,在不适用的时候要记得恢复,上代码

// 开启表⾯剔除(默认背⾯剔除) 
void glEnable(GL_CULL_FACE); 
//关闭表⾯剔除(默认背⾯剔除) 
void glDisable(GL_CULL_FACE); 
// ⽤户选择剔除那个⾯(正⾯/背⾯) 
void glCullFace(GLenum mode); 
//mode参数为: GL_FRONT,GL_BACK,GL_FRONT_AND_BACK ,默认GL_BACK 
//⽤户指定绕序那个为正⾯
void glFrontFace(GLenum mode); 
//mode参数为: GL_CW,GL_CCW,默认值:GL_CCW 
//例如,剔除正⾯实现(1) 
glCullFace(GL_BACK); 
glFrontFace(GL_CW); 
// 例如,剔除正⾯实现(2) 
glCullFace(GL_FRONT);

在我们开启背面剔除后旋转圆环发现黑色部分已经消失了但是又出现新的问题如下图


新问题
3.深度测试

上面的问题是因为在旋转到如上图位置时,其实在计算机看来是拥有多个正面的,计算机无法确定应该显示哪个正面,所以我们引入了深度的概念

  • 深度
    深度就是在openGL坐标系中,像素点的 Z 坐标距离观察者的距离也可以说像素点3D世界中距离摄像机的距离
  • 深度缓冲区(DepthBuffer)
    深度缓存区,就是⼀块内存区域,专⻔存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越⼤,则离摄像机就越远
    在不使⽤深度测试的时候,如果我们先绘制⼀个距离⽐较近的物理,再绘制距离较远的物理,则距离远的位图因为后绘制,会把距离近的物体覆盖掉. 有了深度缓冲区后,绘制物体的顺序就不那么重要了. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写⼊到缓冲区中. 除⾮调⽤glDepthMask(GL_FALSE).来禁⽌写⼊
    -深度测试
    深度缓冲区(DepthBuffer)和颜⾊缓存区(ColorBuffer)是对应的.颜⾊缓存区存储像素的颜⾊信息,⽽深度缓冲区存储像素的深度信息. 在决定是否绘制⼀个物体表⾯时, ⾸先要将表⾯对应的像素的深度值与当前深度缓冲区中的值进⾏⽐较. 如果⼤于深度缓冲区中的值,则丢弃这部分.否则利⽤这个像素对应的深度值和颜⾊值.分别更新深度缓冲区和颜⾊缓存区. 这个过程称为”深度测试”
//申请一个颜色缓冲区和一个深度缓冲区
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
//要启用深度测试
glEnable(GL_DEPTH_TEST);
//关闭深度测试
glDisable(GL_DEPTH_TEST);
//在绘制场景前,清除颜色缓冲区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//指定深度测试判断模式
void glDepthFunc(GLEnum mode);
判断模式说明
开启深度测试后
  • 清除深度缓冲区默认值为1.0,表示最⼤的深度值,深度值的范围为(0,1)之间. 值越⼩表示越靠近观察者,值越⼤表示越远离观察者,但当深度比较接近(例如在同⼀平⾯上进⾏2次绘制),当前精度无法确定深度值大小时,就会出现新的问题(真是没完没了)


    闪烁问题

z-fighting(z冲突、闪烁)

其表现为部分重叠部分不停闪烁,无法确定当前像素点颜色 ,解决办法:

  • 启⽤ Polygon Offset,让深度值之间产生间隔,如果两个图形之间有间隔,就可以在深度测试之前将其深度值做增加并区分开来
//启⽤Polygon Offset ⽅式
//参数列表: 
//GL_POLYGON_OFFSET_POINT 对应光栅化模式: GL_POINT 
//GL_POLYGON_OFFSET_LINE 对应光栅化模式: GL_LINE 
//GL_POLYGON_OFFSET_FILL 对应光栅化模式: GL_FILL 
glEnable(GL_POLYGON_OFFSET_FILL)
  • 使用更高位数的深度缓冲区,通常使用的深度缓冲区是24位的,现在有一些硬件使用使用32位的缓冲区,使精确度得到提高
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349