美文网首页
OpenGL渲染技巧

OpenGL渲染技巧

作者: 大橘猪猪侠 | 来源:发表于2020-07-12 11:59 被阅读0次

深度测试

在之前我们已经讲过深度测试的大部分内容,这次就完善一下之前的内容。
首先深度测试解决的问题:当我们绘制的图形旋转时,会发生两个部分重叠的情况,而OpenGL无法分辨哪个图层在前,哪个图层在后,则会出现一部分存在缺口。
而隐藏面的消除除了可以使用正背面剔除外,还可以使用深度测试来解决,而深度测试还可以解决重叠部分的图案的绘制。

在OpenGL的坐标系中,像素点的z坐标距离观察者的距离,当观察者在z轴正半轴,z值越大则越靠近观察者。当观察者在z轴负半轴,z值越小越靠近观察者。


截屏2020-07-12 上午9.49.05.png 15945194638438.png

查看上面两张图,第一张在z轴正半轴,当观察者在z轴正半轴,图形的z轴越大,越靠近观察者,第二张图就不去解释了,道理都一样。

深度缓冲区

在我之前的的案例中,RenderScene函数在每次写时,都会调用一个函数来清除颜色缓冲区,深度缓冲区。防止之前的数据对现在的图形造成干扰。
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
深度缓冲区和颜色缓冲区是对应的。颜色缓冲区存储像素的颜色信息,而深度缓冲区存储像素的深度信息。在决定是否绘制一个物体表面时,首先要将表面对应的像素的深度值与当前深度缓冲区的值进行比较。如果大于深度缓冲区中的值,则丢弃这部分,否则利用这个像素对应的深度值和颜色值分别更新深度缓冲区和颜色缓冲区,这个过程称为深度测试。
深度缓冲区的默认值为1.0,表示最大深度值,他的范围在[0,1]之间。
我们经常通过glEnable(GL_DEPTH_TEST);glDisable(GL_DEPTH_TEST);来开启和关闭深度缓冲区。

z-fighting问题

在深度测试开启后,OpenGL就不会再去绘制模型被遮挡的部分,这样实现的显示更加真实。但是由于深度缓冲区精度的限制对于深度相差非常小的情况下,OpenGL就可能出现不能正确判断两者的深度值,会导致深度测试的结果不可预测,显示出来的现象交错闪烁,交错出现。

例如如下图所示:同一个位置上出现的图层,且深度值出现精度很低时,就使得两个物体靠的非常近,无法确定谁在前,谁在后


15945205942773.png

解决方法:
1、多边形偏移(Polygon Offset)
多边形偏移方法解决问题的原理主要是让深度值之间产生间隔,如果2个图形之间有间隔,那是不是意味着就不会产生干扰。可以理解为在执行深度测试前将立方体的深度值做一些细微的增加,于是就能将重叠的2个图形深度值之间有所区分。
启用多边形偏移方法:

```
glEnable(GL_POLYGON_OFFSET_FILL)
参数列列表:
GL_POLYGON_OFFSET_POINT   对应光栅化模式: GL_POINT
GL_POLYGON_OFFSET_LINE    对应光栅化模式: GL_LINE
GL_POLYGON_OFFSET_FILL    对应光栅化模式: GL_FILL
```

2、指定偏移量
通过glPolygonOffset来制定.glPolygonOffset需要两个参数:factor,units。
每个fragment的深度值都会增加如下所示的偏移量:offset = (m*factor)+(r*units);,m表示多边形深度的斜率最大值,可以理解为一个多边形越是与近裁剪面平行,m就越接近0,r表示能产生于窗口坐标系的深度值可分辨的差异最小值,r是由具体OpenGL平台制定的一个常量。

void glPolygonOffset(Glfloat factor,Glfloat units);
应⽤用到片段上总偏移计算方程式:
Depth Offset = (DZ * factor) + (r * units); DZ:深度值(Z值)
r:使得深度缓冲区产生变化的最小值
负值,将使得z值距离我们更近,⽽正值,将使得z值距离我们更远.

在我们开启了偏移之后,都需要调用关闭函数glDisable(GL_POLYGON_OFFSET_FILL).

在上面了解完zFighting问题之后,我们可以知道预防的方法可以加大两物体之间的距离和尽可能将近裁剪面设置的离观察者远一些。

混合

混合简单来说就是将两个不透明的或者在另一个物体上面的为半透明的图形重叠在一起产生的颜色变化。

我们都知道OpenGL渲染时会把颜色值存在颜色缓冲区中,每个片段的深度值也是放在深度缓冲区。当深度缓冲区被关闭时,新的颜色将简单的覆盖原来的颜色缓冲区颜色值,当深度缓冲区再次打开时,新的颜色片段只是当它比原来的值更接近邻近的裁剪平面才会替换原来的颜色片段。

开启颜色混合:glEnable(GL_BlEND);

下面介绍一下组合颜色的一些变量的概念:
目标颜色:已经存储在颜色缓冲区的颜色值
源颜色:作为当前渲染命令结果进入颜色缓冲区的颜色值。

在混合功能被启动时,源颜色和目标颜色的组合方式是混合方程式控制的,它的方程式为:
Cf = (Cs * S) + (Cd * D)
cf:最终计算参数的颜色
Cs:源颜色
Cd:目标颜色
S:源混合因子
D:目标混合因子

因此,在我们开启混合时,一般都需要开启混合因子的设置
下面这张图介绍了我们该如何设置两个混合因子
其中R,G,B,A分别代表红、绿、蓝、alpha。
S,D分别代表源、目标
C代表常量颜色(默认黑色)


15945222197911.png

例如:

//1、开启混合
glEnable(GL_BLEND);
//2、开启组合函数,计算混合因子
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

下面解释一下上面的混合因子计算:
如果颜色缓冲区已经有一种颜色(1.0f,0.0f,0.0f,1.0f),这个是目标颜色Cd,如果在这上面用一种alpha为半透明的蓝色(0.0f,0.0f,1.0f,0.5f)

那么
Cd = (1.0f,0.0f,0.0f,1.0f),
Cs = (0.0f,0.0f,1.0f,0.5f),
S = 0.5
D = 1-源alpha = 1-0.5f = 0.5f

方程式 Cf = (CsS)+(CdD)

等价于 = (Blue * 0.5f)+(Red * 0.5f)

其他的都一样,套公式。

混合方程式其实是还可以改变的,我们可以从5种不同的方程式中进行选择
选择方程式函数为:glbBlendEquation(GLenum mode);,函数中的参数可以在下面这张表中任意选择。

15945229025161.png

除了能使用glBlendFunc来设置混合因子,还可以有更灵活的选择。
void glBlendFuncSeparate(GLenum strRGB,GLenum dstRGB ,GLenum strAlpha,GLenum dstAlpha);

strRGB:源颜色混合因子
dstRGB:目标颜色的混合因子
strAlpha:源颜色的alpha值
dstAlpha:目标颜色的alpha值

glBlendFuncSeparate使用注意事项:

  glBlendFunc指定源和目标RGBA值的混合函数;但是glBlendFuncSeparate函数则允许为RGB和Alpha成分单独指定混合函数。
在混合因⼦子表中,GL_CONSTANT_COLOR,GL_ONE_MINUS_CONSTANT_COLOR,GL_CONSTANT_ALPHA,GL _ONE_MINUS_CONSTANT值允许混合方程式中引⼊一个常量混合颜色。

总结:
颜色混合的最终颜色是以目标颜色与后来的源颜色进行组合,在默认混合方程式下,源颜色的alpha值越高,添加的源颜色成分越高,目标颜色所保留的成分就越少。混合函数经常⽤于实现在其他⼀些不透明的物体前面绘制一个透明物体的效果。

在我们通常进行混合时,混合的颜色可能存在另一种颜色的上方或者下方,那么我们要实现混合,那么都必须要使上面的颜色设置一个透明度,否则不会出现颜色混合的情况。

下图是一个颜色混合的demo

15945234359083.png

相关文章

  • 六、OpenGL 渲染技巧:深度测试、多边形偏移、 混合

    OpenGL + OpenGL ES +Metal 系列文章汇总 深度测试 在上一篇五、OpenGL 渲染技巧:正...

  • OpenGL渲染技巧

      在OpenGL渲染中, 我们会碰到各种各样的问题,所以也会对应的产生各种各样的渲染技巧,接下来就介绍我们最经常...

  • OpenGL渲染技巧

    1、渲染过程产⽣的问题 在绘制3D场景的时候,我们需要决定哪些部分是对观察者 可见的,或者哪些部分是对观察者不可⻅...

  • OpenGL渲染技巧

    1、隐藏面消除 在渲染3D场景过程中可能会产生以下问题 我们需要决定哪些部分是对观察者可⻅的,或者哪些部分是对观察...

  • OpenGL渲染技巧

    OpenGL渲染技巧 了解了OpenGL的渲染流程和常用API后,就可以简单的绘制出图形了。但是在绘制中可能会碰到...

  • OpenGL渲染技巧

    首先,我们来绘制一个3D图形“甜甜圈”,示例程序运行效果如下: 咋看,似乎没什么问题。但当我们试着向右旋转它的时候...

  • OpenGL渲染技巧

    深度测试 在之前我们已经讲过深度测试的大部分内容,这次就完善一下之前的内容。首先深度测试解决的问题:当我们绘制的图...

  • OpenGL渲染技巧

    先引入一个案例: 设置一个甜甜圈,为了体现出阴影效果和立体效果,选取默认光源着色器开始渲染: 效果如下: 可以看到...

  • OpenGL 渲染技巧

    OpenGL 渲染技巧 提示: 这个挺重要的.在我们公司项目中这些代码还是经常看到. 当我们观察空间任意一个不透明...

  • OpenGL渲染技巧

    在绘制3D场景的时候,我们需要决定哪一部分对于观察者来说是可见,哪些是不可见,这样才可以做到隐藏面消除(Hidde...

网友评论

      本文标题:OpenGL渲染技巧

      本文链接:https://www.haomeiwen.com/subject/huugcktx.html