오디오 및 비디오 그래픽 디스플레이 개발 -OpenGL 일반적인 문제와 해결 방법

문제는 렌더링 과정에서 발생할 수있는

3D 장면을 그릴 때, 우리는 눈에 보이지 않는 부분을 들어 ⻅되지 않은 어떤 부분 ⻅ 관찰자 또는 뷰어는, 가능한 한 빨리 폐기해야하는 부분을 결정해야합니다. 예를 들어, ⼀ 불투명 한 벽 후, 렌더링 할 수 없습니다.이 상황은 "숨겨진 표면 제거"(숨겨진 표면 제거)이라고합니다.

회화 알고리즘

  1. 첫 번째 무승부는 가까운 물체를 그릴, 멀리 장면 뷰어에서 객체.
  2. 예를 들어, 다음 그림은 : 숨겨진 표면 제거의 문제를 해결할 수, 첫 번째의 붉은 부분을 그립니다 다음 노란색 부분을 그리고 마지막으로 회색을 그릴
    여기에 그림 삽입 설명
    에서 원근, 한 장면에서의 물리적 거리로 관찰자의 거리 종류에 따라, 그림 알고리즘을 사용하여 추첨은 상황 삼 세 ⻆ 형태가 중첩되어있는 경우 그래서 무슨 일이 일어날 지?, 오일 처리 알고리즘이 작동하지 않을 것입니다.이 될 수 있습니다.
    여기에 그림 삽입 설명

분석

우리는 큐브를 볼 때, 단 큐브는 여섯 후 다른 세 얼굴이 보이지 않는 얼굴, 그래서 렌더링 할 필요가 있습니다, 세 얼굴까지 볼 수 있습니다. 그래서, 우리는 우리가 보는 세 가지 얼굴을 렌더링 할 필요가!

어떻게 그 얼굴이 보이는 얼굴이하지 않은, 볼 수 있습니다 판단 하는가? 즉 긍정적 인 측면의 OpenGL을 확인하는 방법입니다. 반대는 어느 쪽?
그 대답은 정점 데이터의 시퀀스를 분석하는 것이다

  • 앞면 : 연결 순서를 시계 반대 방향으로 삼각형의 꼭지점
  • 뒤로 : 시계 방향으로 삼각형의 꼭지점에 연결 순서

여기에 그림 삽입 설명
분석 :

  • 세 왼쪽 ⻆ 형상 정점 순서 : 1-> 2-> 3; 삼각형 정점 순서의 우측은 : 1-> 2-> 3
  • 포지티브 반 시계와 비교할 때, 관찰자의 오른쪽에서, 오른쪽 방향 ⻆ 세 자형 때 왼쪽 ⽽ 세 리어 형 시계 비교이다 ⻆
  • 왼쪽에있는 관찰자는, 삼각형의 왼쪽 결정 안티 시계 방향 회전은 전방에있을 때, 삼각형의 오른쪽 방향으로 결정된다 ⽽ BACK한다.

스크린과 양성으로 판정이 삼각형의 정점 공통 관찰자의 순서 및 방향을 정의한다. ⻆ 뷰어의 방향의 변화, 다시 전면도 변경된다.

전면 및 후면 컬링

从而引入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值转换成深度值,下面的线性方程转换成深度值
여기에 그림 삽입 설명
这的far和near参考下图中的观察者坐标系
여기에 그림 삽입 설명
但正确投影特性的非线性深度方程是和1/z成正比的,非线性方程和1/z成正比
여기에 그림 삽입 설명
当z值越大时,越接近于1,并且当深度精度越大时,越准确
여기에 그림 삽입 설명

代码编写

  • 开启深度测试
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);

여기에 그림 삽입 설명

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

ZFlighting闪烁问题

由于深度值是有精度的,当精度不够的时候,OpenGL就不能很好的区分深度值,如下图的重叠部分,深度值很接近,就会出现图片闪烁,上下交替。
여기에 그림 삽입 설명
여기에 그림 삽입 설명

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는 적은 격차를 좁힐 것 오프셋 해당 모델 0보다 당신 (카메라) 멀리 위치에서 0으로 밀어 버린다
  • 평소와 같이 촬영의 -1.0 만 필요하고 glPolygonOffset -1 너무 간단 할당 노출 부족 기본적으로 전체 충분한 수요.

닫기 다각형 오프셋

glDisable (GL_POLYGON_OFFSET_FILL);

두 개체가 함께 쌓아 삼각형을 렌더링하지 않도록, 너무 가까이하지 않습니다. 소량으로 장면 객체 요구 오프셋이 방식으로, 현상 ZFighting을 회피 할 수있다. 예를 들어,주의 즉시 ⽅ 비행기 본체와 문제에 대한 화면은 평면 ⾯ 아래 0.001f이 문제를 해결할 수 있습니다. 물론, 시계 무브먼트는 작은이 가격을 상쇄 삽입합니다.

추천

출처blog.csdn.net/shengpeng3344/article/details/91410305