Audio and video graphics display development -OpenGL common problems and solutions

Problems may arise in the rendering process

When drawing the 3D scene, we need to decide which part is ⻅ observer or viewer what part is not ⻅ For invisible part, should be discarded as soon as possible. For example, after a ⼀ opaque walls, should not be rendered. this situation is called a "hidden surface removal" (hidden surface elimination).

Painting algorithm

  1. First draw objects farther away from the viewer in the scene, then draw closer objects.
  2. For example, the following illustration: Draw the red part of the first, then draw the yellow section, and finally draw the gray, can solve the problem of the hidden surface removal
    Here Insert Picture Description
    using the painting algorithm, as long as the physical distance from the scene according to the observer's distance sort, from far and near the draw can be. so what will happen? If the situation three three ⻆ shape is superimposed, oil processing algorithm will become inoperable.
    Here Insert Picture Description

analysis

When we look at a cube, can only see up to three faces, the cube has six faces, then the other three face is invisible, so no need to render. So, we only need to render three faces we see!

So how to judge those faces are visible, which is not visible face of it? That is how to tell OpenGL which side is positive. Which side is the opposite?
The answer is by analyzing the sequence of vertex data

  • Obverse: connection sequence anticlockwise triangle vertices
  • Back: connection order in the clockwise triangle vertices

Here Insert Picture Description
analysis:

  • Left three ⻆ shaped vertex order: 1-> 2-> 3; the right side of the triangle vertex ordering is: 1-> 2-> 3
  • When the right side of the observer, the three-shaped ⻆ direction to the right as compared with positive anti- clockwise, the left ⽽ is a rear three-shaped clockwise compared ⻆
  • When an observer at the left side, the left side of the triangle is determined anti- clockwise rotation is a front, right side of the triangle is determined clockwise ⽽ BACK.

The screen and the back positive decision is common vertex of a triangle define the sequence and direction of the observer. ⻆ with the change of the direction of the viewer, back of the front will also change.

Front and back culling

从而引入OpenGL的正背面剔除概念

  1. 开启表面剔除(默认为背面剔除)
void glEnable(GL_CULL_FACE);
  1. 关闭表面剔除
void glDisable(GL_CULL_FACE);
  1. 用户选择剔除哪个面(正面/背面)
void glCullFace(GLenum mode);
//model参数为: GL_FRONT,GL_BACK,GL_FRONT_AND_BACK,默认GL_BACK
  1. 用户指定绕序哪个为正面
void glFrontFace(GLenum mode);
//mode参数为:GL_CW,GL_CCW,默认是为GL_CCW

代码举例:

  1. 剔除正面实现
glCullFace(GL_BACK);
glFrontFace(GL_CW);
  1. 剔除正面实现 2
void glCullFace(GL_FRONT);

深度测试

深度

深度其实就是该像素点在3D世界坐标系中,距离摄像机的距离,Z值

深度缓冲区

深度缓冲区,为一块内存区域,专门存储着每个像素点的深度值。深度值(Z值)越大,即像素点离摄像机越远,那当我们没有开启混合(Blend)的时候,两张图片在同一像素点有不同的Z值,那么我们会舍弃Z值较大的,渲染并显示Z值较小的。

为什么要使用深度缓冲区

在不使用深度测试的时候,如果我们先绘制一个距离比较近的物体,再绘制距离较远的物体,则距离远的位图因为后绘制,会把距离近的物体覆盖掉. 有了深度缓冲区后,绘制物体的顺序就不那么重要了. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写⼊到缓冲区中. 除⾮调⽤ glDepthMask(GL_FALSE).来禁⽌写入.

深度测试

那么深度测试在这种背景下产生了,他会比较同一个像素点的深度大小,来决定是否显示

深度缓冲区(DepthBuffer)和颜色缓存区(ColorBuffer)是对应的.颜色缓存区存储像素的颜色信息,⽽深度缓冲区存储像素的深度信息. 在决定是否绘制一个物体表面时, ⾸先要将表面对应的像素的深度值与当前深度缓冲区中的值进行比较. 如果大于深度缓冲区中的值,则丢弃这部分.否则 利用这个像素对应的深度值和颜色值.分别更新深度缓冲区和颜色缓存区. 这个过程称为”深度测 试”

深度值的计算

深度值一般由16位,24位或者32位值表示,位数越多越精确。值的范围位于[0,1]之间
但是我们通常设置Z值是不在[0,1]范围内的,那么就需要将Z值转换成深度值,下面的线性方程转换成深度值
Here Insert Picture Description
这的far和near参考下图中的观察者坐标系
Here Insert Picture Description
但正确投影特性的非线性深度方程是和1/z成正比的,非线性方程和1/z成正比
Here Insert Picture Description
当z值越大时,越接近于1,并且当深度精度越大时,越准确
Here Insert Picture Description

代码编写

  • 开启深度测试
glEnable(GL_DEPTH_TEST);
  • 在绘制场景前,我们需要清除深度缓冲区
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  • 制定深度测试判断模式
void glDepthFunc(GLEnum mode);

Here Insert Picture Description

  • 打开/阻断深度缓冲区写入
void glDepthMask(GLBool value);
value : GL_TURE 开启深度缓冲区写⼊入; GL_FALSE 关闭深度缓冲区写⼊入

ZFlighting闪烁问题

由于深度值是有精度的,当精度不够的时候,OpenGL就不能很好的区分深度值,如下图的重叠部分,深度值很接近,就会出现图片闪烁,上下交替。
Here Insert Picture Description
Here Insert Picture Description

Polygon Offset ⽅式

启用Polygon Offset

让深度值之间产⽣间隔.如果2个图形之间有间隔,是不是意味着就不会产⽣生干涉.可以理解为在执行深度测试前将⽴方体的深度值做⼀些细微的增加.于是就能将重叠的2个图形深度值之前有所区分.
//启⽤用Polygon Offset ⽅方式

glEnable(GL_POLYGON_OFFSET_FILL)

参数列列表:

GL_POLYGON_OFFSET_POINT 对应光栅化模式: GL_POINT 
GL_POLYGON_OFFSET_LINE 对应光栅化模式: GL_LINE
GL_POLYGON_OFFSET_FILL 对应光栅化模式: GL_FILL

指定偏移量

  • 通过glPolygonOffset 来指定.glPolygonOffset 需要2个参数: factor , units 每个Fragment 的深度值都会增加如下所示的偏移量:
    Offset = ( m * factor ) + ( r * units);
  • m : 多边形的深度的斜率的最大值,理解⼀个多边形越是与近裁剪面平⾏,m 就越接近于0.
  • r : 能产⽣于窗口坐标系的深度值中可分辨的差异最小值.r 是由具体是由具体OpenGL 平台指定的一个常量量.
  • A zoomed in Offset model will push to 0 from you (the camera) farther location, less than a corresponding model 0 Offset will narrow the gap
  • Shoots as usual, the only need to -1.0 and -1 so simple assignment underexposure to glPolygonOffset basically full enough demand.

Close Polygon Offset

glDisable(GL_POLYGON_OFFSET_FILL);

The two objects do not too close, to avoid rendering triangles stacked together. In this way the requirements of the scene objects into a small amount of offset, it is possible to avoid the phenomenon ZFighting. E.g. attention immediately ⽅ plane body and the screen for the problems, the flat ⾯ down 0.001f can solve this problem. Of course, the watch movement to Insert the small offset a price.

Guess you like

Origin blog.csdn.net/shengpeng3344/article/details/91410305