Ⅰ OpenGL图像渲染过程3.0
背景: 3D图形渲染的时候,需要决定哪些部分是对观察者可见的,哪些部分对观察者是不可见的,对不可见的部分,应该丢弃。
这个过程叫做隐藏面消除(hidden surface elimination)。
先绘制场景中距离观察者较远的物体,再绘制场景中离观察者较近的物体。
OpenGL不去渲染视角看不到的面
OPenGL可以做到检查正面朝着观察者的面,丢弃背向的面,节约片元着色器的性能。
正背面的区分:按照逆时针顶点连接顺序的面为正面。
深度缓冲区(DepthBuffer)和颜色缓冲区(ColorBuffer)是对应的。深度缓冲区存储像素的深度信息,颜色缓冲区存储像素的颜色信息。在决定是否绘制一个物体表面时候,首先要将物体表面的像素的深度值和当前深度缓冲区中的数据进行比较,如果大于深度缓冲区中的深度,就丢弃物体表面的颜色值和深度值,如果小于就使用物体表面的颜色值,并更新这个像素的深度值和颜色值。这个过程叫做深度测试。
清除深度缓冲区的时候,默认值是1.范围是(0-1) 之间,值越小,表示越靠近观察者。
类型快查
启用polygon offset,让深度之间产生一个间隔,如果两个图形之间有间隔,将间隔值略微增加,让重叠的两个图形与之前的有所区分。
每个片元(Fragment)的深度值都会增加一些偏移量
m多边形深度斜率最大值
r常量,窗口坐标系能分辨的最小差值
offset是负值将使z值距离我们更近。一般都设置成-1 -1.factor和units.
当深度缓冲区被关闭的时候,新的颜色将简单的覆盖原来的颜色缓存区存在的颜色值。
当深度缓冲弄区再次被打开时候,新的颜色片段只有当离原来的值更接近裁剪平面时候才会替换原来的颜色片段。????
目标颜色:已经存储在颜色缓存区的颜色
源颜色:作为当前渲染命令结果,进入颜色缓存区的颜色
最终颜色的计算是由颜色混合方程式决定的
Cf :最终的参数颜色
Cs :源颜色
Cd :目标颜色
S :源混合因子
D: 目标混合因子
混合方程式快查
S源混合因子
D目标混合因子
C表示常量颜色,黑色
混合因子计算方法快查
混合函数经常用于实现在其他一些不透明物体前绘制一个透明物体的效果。
Ⅱ 零基础入门OpenGL系列教程(六、早期OpenGL绘图属性)
点的属性恐怕就只有点的大小了,通过调用 void glPointSize(GLfloat size) 函数可以设置点的大小,传入的参数是一个浮点数代表点的像素。
这个设置是支持 反走样 (antialiasing)的,如果你设置了反走样这个函数同样适用。
线的属性大致有两种,一是线宽,二是样式。
设置线宽和设置点大小一样,通过 void glLineWidth(GLfloat width) 函数来设置,传入的参数也是浮点数。同样支持反走样。
线的样式设置比较有意思,通过 void glLineStipple(GLint factor,GLushort pattern) 函数来设置。第一个参数是因子,我把它简单的理解为线条样式拉伸的系数,第二个参数比较有趣,它是用来描绘具体样式的16位整数。1对应实线,0对应空白,通过这种方法表现出来样式。
这是我画的虚线,对应的样式是0x0A0A。在设置样式的时候需要调用 glEnable(GL_LINE_STIPPLE) 函数打开线段样式渲染状态。
即使是二维的平面也分为正面和背面,比如说如果我顺时针方向渲染的点为正面,那么逆时针渲染的点就是背面了。有了这一概念我们就可以单独的对图形的某一个面操作,比如说正面填充背面描边。
void glFrontFace(GLenum mode) 可以设置图形的正面与背面(相反的为背面),参数是顺时针或逆时针。 void glPolygonMode(GLenum face,GLenum mode) 可以分别对正面或背面以不同方式渲染。举个例子。
我通过顺时针和逆时针两种方式画的两个三角形,渲染结果是不同的。
此外, void glEdgeFlag( GLboolean flag) 函数可以指定边是否是边界,如果不是可以隐藏它。
通过这个特性我简单的画了一个“二”。
关于面的属性还有很多。比如样式、纹理甚至雾化效果,这个在现代OpenGL里面再说吧。
Ⅲ 缺少OpenGL32.dll文件该怎么弄
解决win10缺少“某某某.dll”文件的方法:
方法一:下载丢失的.dll文件,复制到系统盘的C:WindowsSystem32文件夹中。
1、网络搜索输入“某某某.dll”下载,查找适当的“某某某.dll”文件下载网页,点击打开下载;
以上就是win10系统缺少“某某某.dll”文件的解决方法。
Ⅳ OpenGL ES手册翻译---3.栅格化(一)
栅格化是一个把图元转换成二维图像的过程。图像的每个点都包含了颜色和深度这样的信息。因此,栅格化一个图元包含了两个部分。第一步是要确定图元在窗口坐标中所占的整数网格的方块。第二步,给每个方块分配颜色和深度值。处理的结果传递给GL的下一个阶段(对每个片段的操作),GL使用这些信息更新帧缓冲区中的相应合适的位置。图3.1是栅格化处理过程。碎片的颜色由片段着色器决定(见3.8节),片段着色器使用由栅格化操作(见3.3到3.6节)产生的varying变量来实现。最后的深度值由栅格化操作决定栅格化点,线或者多边形的结果都是通过片段着色器来规定的。
一个网格和z(深度)方向的参数以及varying数据被合称为一个碎片(fragment);这些参数被统称为关联数据。一个碎片基于整数网格坐标系,从左下角开始栅格化操作也有一个指定的碎片的中心,这个中心是从左下角开始的(1/2,1/2)偏移量的地方(也就是基于半整数坐标系)。
在GL中网格不要求完全是方形的。栅格化规则不会受网格实际长宽比的影响。显示非方形的网格会导致栅格化的点和线段呈现出来在一个方向上比另一个方向上胖一点。我们指定碎片是正方形的,这样可以简化抗锯齿和纹理操作。
几个因素会影响栅格化。点可能会有不同的直径,线段会有不同的宽度。多重采样必须被用在栅格化抗锯齿的图元中(见3.2节)。
考虑在窗口坐标系中,把图元 平移(x,y),得到 ,其中x和y是整数。只要 和 不会被裁剪,那么每从 产生的每个碎片 和相对应的 产生的每个碎片 是相同的,只是 和 的中心偏移
多重采样是一种GL图元:点,线和三角形抗锯齿的机制。这个技术是在所有图元上的每个像素进行多次采样。每次像素更新后,颜色采样值会被解析成一个单一的,可以显示的颜色,抗锯齿操作在应用层面会被自动处理。因为每个采样点都包括颜色,深度和模板信息,颜色(包括纹理操作),深度和模板函数和单次采样模式下效果是一样的。
还有另外一个缓冲区,叫做多采样缓冲区,被添加在帧缓冲区上。像素的采样值,包括颜色,深度,模板值,都储存在这个缓冲中。当帧缓冲包含了一个多重采样缓冲,帧缓冲就没有深度和模板缓冲了,甚至多采样缓冲也不会存储深度和模板的值。但是,颜色缓冲和多采样缓冲是共存的。
多重采样抗锯齿对渲染三角形是非常有用的,因为它不需要用排序来消除隐藏的表面,它可以正确的处理相邻的三角形,对象的轮廓甚至是相交的三角形。
如果 SAMPLE_BUFFERS 的值是一,所有图元的栅格化就变了,而是指多重采样的栅格化。而图元的栅格化是指单采样的栅格化。将 GetIntegerv 函数的 pname 设置为 SAMPLE_BUFFERS 就可以查询到 SAMPLE_BUFFERS 的值。
一个像素碎片的内容在多重渲染期间有两种方式。第一种,每个碎片都包含一个 SAMPLE 位数的信息值。这个 SAMPLE 值是依赖实现的常量,可以通过把函数 GetIntegerv 的 pname 设置为 SAMPLES 来查询。
第二种,每个碎片都包含了 SAMPLES 的深度值,一些varying值,而不是在单采样渲染模式下的单一的深度值和一些varying变量。GL实现时可能会选择给多个采样值分配相同的varying变量。评估varying值的位置可以是在像素内的任何位置,包括碎片中心或者采样位置。在同一个位置的varying值不需要评估。每个像素碎片因此由网格坐标的整数x和y, SAMPLES 的varying值,和一个最大 SAMPLES 的位数信息组成。
多重采样的栅格化在GL上下文创建后是不能打开或者关闭的。如果 SAMPLE_BUFFER 是一就是打开的,不是一,那么就是关闭的。
图元的多采样的栅格化很大程度上和单采样的栅格化是不同的。可以理解为在帧缓冲的每个像素有对应的 SAMPLES 位置相关联。这些位置不是一个区域或者面积,而是一个准确的位置,每个位置被称为一个采样点。和像素相关联的采样点的位置可能在正方形单元的里面或者外面,这个正方形单元是指像素的边界。不仅如此,采样点的相关位置可能和帧缓冲中的每个像素相同也有可能不同。
如果采样点位置和像素不同,那么采样点位置应该和窗口对齐,而不是屏幕。另外,渲染结果也是通过窗口位置指定的。在3.1节中描述的不变性要求对所有的多重采样栅格化是宽松的,因为采样位置可能是像素位置的一个函数。
查询像素的实际采样位置是不可能的。
点的大小是从着色器的内建变量 gl_PointSize 获取,受到依赖实现的点的大小范围的钳制。如果 gl_PointSize 小于等于0,将产生未定义的结果。点大小的范围由 ALIASED_POINT_SIZE_RANGE 决定,可以通过第六章的描述中那样查询到。支持的点的最大大小至少是1.
点的栅格化为每个帧缓冲的像素产生一个碎片,像素中心在中心点为
的方形中,方形的边长和点的大小相同。
栅格化点产生的所有碎片分配给相同的关联数据,即对应于该点的顶点的数据。同时, gl_PointCoord 片段着色器的输入定义了一个机遇每个碎片单元的坐标系空间(s,t),s变量是水平的从左到右0到1的点,t是垂直的从上到下为0到1的点。
下面的公式用来评估(s,t)的值:
size 是点的大小, 是碎片的窗口坐标的整数值, 是该点顶点的精确的,无边界的窗口坐标。
如果 SAMPLE_BUFFERS 是1,点的栅格化将使用下面的方式。点的栅格化对每个帧缓冲的像素生成一个碎片,这些像素有一个或者多个采样点,这些采样点交汇在一个以点 为中心的区域中。这个区域是一个正方形的,边长等于像素大小。和这个区域相交的对应的采样点的所有的覆盖位为1,其他的覆盖位为0。碎片的每个样本相关联的数据就是和点的栅格化相关联的数据。点大小的支持范围和没有多重采样的点是一样的。
线段有线条,线回路,或者一系列的分开的线段。线的宽度可以通过调用函数
来设置,一个合适的正数来控制栅格化线段的宽度。默认宽度是1.0。小于或者等于0.0的值会产生 INVALID_VALUE 错误。
线段光栅化首先将线段描述为x-major或y-major。x-major线段在闭合区间[-1,1]内有斜率;所有其他线段都是y-major线段(斜率由线段的端点确定)。我们将只为x-major部分指定光栅化,除非y-major部分的改变不明显。
理想情况下,GL使用“菱形退出”规则来确定通过对线段进行栅格化而产生的那些碎片。对于中心位于窗口坐标 和 的每个片段f,定义四个半平面相交的菱形区域:
本质上,一条线段从 点到 点结束产生了一些和 相交的碎片f,除非 包含了 ,见图3.2。
为了避免结束点在 的边界上的困难,我们在原则上会对结束点进行少量的扰动。 点和 点各自的窗口坐标为 和 。扰动端点 和 的坐标为 和 。从 到 的线段产生了这些片段f,就是线段从 到 的线段和 相交后产生的,除非 点是在 中, ε是一个在栅格化线段时,为了使线段产生相同的碎片而选择的非常小的量,而δ就是对任何一个ε都有0 < δ ≤ ε的替换量。
当 和 在碎片的中心是,碎片的特征化处理简化到使用Bresenham算法做一处修改即可:这种情形下的产生的线段叫做“半开放”,这意味着没有绘制最后的片段(对应于 )。这意味着当栅格化一系列的相互连接的,共享端点的线段时,将只会作用一次而不是两次(就像Bresenham算法那样)。
由于菱形退出规则的初始条件和最终条件可能难以实现,因此允许其他线段光栅化算法,遵循以下规则:
下一步,我们必须说明每个栅格化的碎片相关联的数据如何获取。一个产生的碎片的中心的窗口坐标值为 以及 ,那么就有
(注意在 点的t = 0,在 点的t = 1)。碎片的相关数据f的值,不论它是裁剪w坐标还是一个顶点着色器varying变量输出的元素,都可以被表示为
是线段的起始点和终点的相关的数据。 是线段的裁剪坐标系w中的起始点和终点。窗口z是深度值,必须使用线性插值:
我们仅仅描述了非抗锯齿的线段的栅格化。现在我们介绍线段栅格化化操作时一些通用的参数。
实际的非抗锯齿线的宽度是把需要的宽度四舍五入到整数的值来决定的,然后把这个数牵拉到实现相关的最大的非抗锯齿线的宽度。如果指定的宽度取整的结果是0,那么这个值被认为是1。
除了非抗锯齿的线段的宽度为1的线段之外,都是通过在次要方向(对于x-主要线,次要方向是y,对于y-主要线,次要方向是x)做偏移或者在次要方向复制碎片来进行栅格化操作(如图3.3)。w表示取整的宽度(如果w=0时,w设为1)。如果线段在窗口坐标系中为 ,栅格化后线段的端点是 和 ,这样产生的并不是一个单一的碎片,而是在每个x的位置(y-major是y)产生一个高为w(对于y-major的线段来说w是一行碎片的长度)的列。这列的位置最低的这个碎片,就是在修正过的坐标系中宽度为1的线段栅格化后产生的碎片。
GL状态要求线的栅格化由线宽为浮点数构成。线宽的初始值是1.0。
如果 SAMPLE_BUFFERS 的值是1,线的栅格化将会使用下面的算法。每个帧缓冲像素,有一个或者多个采样点,和中心在线段上的矩形相交,线的栅格化为每个这样的像素产生一个碎片(如图3.4)。两条边和指定的线段平行;每条边到线段的距离是线宽的一半:一条在线段的上方,一条在下方。另外两条边穿过线段的端点和指定线段的方向垂直。
和矩形相交的采样点的覆盖位为1,其他的覆盖位为0。顶点着色器varying变量的输出值和深度值通过置换等式3.1中对应的采样位置的值做插值计算得出,得出的结果再用来计算等式3.2的值。实现过程可能会在多于一个采样值上使用相同的varying变量的值。
并不是所有的宽度都需要支持线段的多重采样,但是宽度为1.0的线段必须要提供支持。正如点的宽度一样,GL实现时可能会查询多重采样线段宽度的等级的范围和数目。
Ⅳ Windows7电脑初始化OpenGL4.6时出错怎么办
Windows7电脑初始化OpenGL4.6时出错处理办法:
1、重新安装平台并重启电脑。
2、关闭防火墙与杀毒软件。
3、测试dns。
4、进入计算机控制面板-系统属性,新建系统变量【变量名QT_OPENGL变量值:angle】并重启电脑。
5、更新显卡驱动,以及观察驱动是否和本地硬件兼容。
6、盲输登录,在平台登录页面按照印象输入账号密码,回车登录。
Ⅵ OpenGL 渲染技巧:正背面剔除、深度测试、多边形偏移、 混合
在绘制3D场景时,我们需要决定哪些部分是对观察者可⻅的,或者哪些部分是不可见的。对于不可⻅的部分,应该及早丢弃,这种做法叫做 隐藏⾯消除 。
先绘制红色部分,再绘制⻩色部分,最后再绘制灰⾊部分,即可解决隐藏面消除的问题。即将场景按照物理距离和观察者的距离远近排序,由远及近的绘制即可。
弊端: 如果三个三⻆形是相互重叠的,油画算法将⽆法处理。
从任何⼀个⽅向去观察一个立方体,最多可以看到3个⾯。如果我们能以某种⽅式去丢弃这部分数据。OpenGL在渲染的性能即可提高超过50%。
任何平⾯都有2个⾯:正⾯和背面,⼀个时刻我们只能看到一面。 通过分析顶点数据的顺序 ,OpenGL可以做到检查所有正面朝向观察者的面,并渲染它们;从⽽丢弃背面朝向的面。
⚠️注意: 正⾯和背⾯是有三角形的顶点定义顺序和观察者方向共同决定的。若观察者的观察⽅向发生改变,正⾯和背面也会发生相应的改变。
弊端: 如果前后两个点都是正面或是背面,这时OpenGL无法区分哪个面在前,哪个面在后,就可能出现下图所示的问题。
深度,就是像素点在3D世界中距离摄像机的距离,即Z值。
深度缓存区,就是⼀块内存区域,专门存储每个像素点的深度值。深度值(Z值)越⼤,则离摄像机就越远。
为什么需要深度缓冲区?
深度缓冲区和颜⾊缓存区是对应的。颜⾊缓存区存储 像素的颜⾊信息 ,而深度缓冲区存储 像素的深度信息 。
在决定是否绘制⼀个物体表⾯时,首先要将表面对应的像素的深度值与当前深度缓冲区中的值进⾏⽐较。如果大于深度缓冲区中的值,则丢弃这部分;否则利⽤这个像素对应的深度值和颜⾊值,分别更新深度缓冲区和颜色缓存区。这个过程称为 深度测试 。
深度值,⼀般由16位、24位或者32位值表示,通常是24位。
使⽤正⾯/背面剔除法和深度测试法解决了OpenGL的渲染效率问题。
由于精度的限制,对于相差非常小的深度值(比如在同一个深度进行2次渲染),就可能出现不能正确区分两个深度值的问题,导致测试的结果随机出现。所以,显示时2个画⾯交错出现,就会出现闪烁问题。
增大重叠或深度值接近的2个图形的深度值差距,使得OpenGL可以区分两个深度值。
步骤三: 关闭Polygon Offset
在OpenGL中提⾼渲染效率的⼀种⽅式。 只刷新屏幕上发⽣变化的部分。
OpenGL渲染时会把颜色值存在颜⾊缓存区中,每个⽚段的深度值也是放在深度缓冲区。
当混合功能被开启时,源颜色和⽬标颜色的组合方式是 混合方程式 控制的。在默认情况下,混合方程式如下所示:
混合函数经常用于实现在其他一些不透明的物体前面绘制一个透明物体的效果。
实际上不止一种颜色混合方程式,OpenGL有5个不同的方程式进行选择。
表中R、G、B、A 分别代表 红、绿、蓝、Alpha
表中下标S、D,分别代表源、⽬标
表中C 代表常量颜⾊(默认⿊色)
下⾯通过一个常见的混合函数组合来说明问题:
如果颜色缓存区已经有一种颜⾊红色(1, 0, 0, 0)
在这上面混合一种alpha为0.6的蓝色(0, 0, 1, 0.6)
最终颜色是以原先的红色(⽬标颜色)与后来的蓝色(源颜色)进⾏组合。源颜色的alpha值越高,添加的蓝色颜色成分越高,⽬标颜⾊所保留的成分就会越少。
Ⅶ 3.OpenGL渲染技巧
1.渲染过程产生的问题
看到了不透明墙壁后面的东西,不应该渲染墙壁后的东西(隐藏面消除)
2.油画渲染
距离观察者由远及近的绘制物体,可以解决。
但是这出现了新的问题,如果3个三角形互相叠加,油画算法将无法渲染。
3.正背面剔除
OpenGL可以检查朝向观察者的面并渲染它们,而丢弃背面。
OpenGL如何区分正背面?
通过分析顶点数据的顺序。
4.深度测试
深度:3D世界中像素点距离摄像机的距离。
深度缓冲区:一块内存区域、存储着每个像素点的深度值,值越大距离摄像机越远。
为何需要深度缓冲区?绘制顺序就不重要了。
深度测试:是否绘制物体表面,表面深度值和当前缓冲区深度值比较,大于则丢弃,否则更新像素颜色值和深度值。
5.多边形模型
6.多边形偏移
7.裁剪
8.颜色混合
1.谈谈图形图像渲染中的深度缓冲区?
一块内存区域、存储着每个像素点的深度值,值越大距离摄像机越远。
为何需要深度缓冲区?绘制顺序就不重要了。
2.阐述隐藏面消除解决方案?
正背面剔除、深度测试
3.阐述深度缓冲区带来的隐患、解决方案、预防方案?
原因:深度缓冲区的限制导致深度相差很小。
隐患:交错闪烁出现2个画面
解决方案:让深度值之间产生间隔,在执行深度测试前将立方体的深度值做一些细微的增加,区分重叠的2个图形深度值。
第一步:Polygon Offset方式解决。
glEnable(GL_POLYGON_OFFSET_FILL)
第二步:指定偏移量
void glPolygonOffset(Glfloat factor,Glfloat units);
第三步: 关闭Polygon Offset
glDisable(GL_POLYGON_OFFSET_FILL)
预防方案:
不要将2个物体靠的太近;将裁剪面设置的离观察者远一些;使用高位数的深度缓冲区。
1.深度测试
2.OpenGL 裁剪
3.OpenGL混合
Ⅷ OpenGL 渲染常见问题
在绘制3D场景的时候,我们需要决定哪些部分是对观察者可⻅的,或者哪些部分是对观察者不可⻅的.对于不可⻅的部分,应该及早丢弃.例如在⼀个不透明的墙壁后,就不应该渲染.这种情况叫做”隐藏⾯消除”(Hidden surface elimination).
判断模式glDepthFunc可以传如下表所示参数,默认为GL_LESS
解决:
让深度值之间产⽣间隔.可以理解为在执⾏深度测试前将⽴⽅体的深度值做⼀些细微的增加.于是就能将重叠的2个图形深度值之前有所区分.
ZFighting闪烁问题预防
• 不要将两个物体靠的太近,避免渲染时三⻆形叠在⼀起。这种⽅式要求对场景中物体插⼊⼀个少量的偏移,那么就可能避免ZFighting现象。例如上⾯的⽴⽅体和平⾯问题中,将平⾯下移0.001f就可以解决这个问题。当然⼿动去插⼊这个⼩的偏移是要付出代价的。
• 尽可能将近裁剪⾯设置得离观察者远⼀些。上⾯我们看到,在近裁剪平⾯附近,深度的精确度是很⾼的,因此尽可能让近裁剪⾯远⼀些的话,会使整个裁剪范围内的精确度变⾼⼀些。但是这种⽅式会使离观察者较近的物体被裁减掉,因此需要调试好裁剪⾯参数。
• 使⽤更⾼位数的深度缓冲区,通常使⽤的深度缓冲区是24位的,现在有⼀些硬件使⽤使⽤32位的缓冲区,使精确度得到提⾼
在OpenGL 中提⾼渲染的⼀种⽅式.只刷新屏幕上发⽣变化的部分.OpenGL 允许将要进⾏渲染的窗⼝只去指定⼀个裁剪框.
基本原理:⽤于渲染时限制绘制区域,通过此技术可以再屏幕(帧缓冲)指定⼀个矩形区域。启⽤剪裁测试之后,不在此矩形区域内的⽚元被丢弃,只有在此矩形区域内的⽚元才有可能进⼊帧缓冲。因此实际达到的效果就是在屏幕上开辟了⼀个⼩窗⼝,可以再其中进⾏指定内容的绘制。
混合函数经常⽤于实现在其他⼀些不透明的物体前⾯绘制⼀个透明物体的效果
我们把OpenGL 渲染时会把颜⾊值存在颜⾊缓存区中,每个⽚段的深度值也是放在深度缓冲区。当深度缓冲区被关闭时,新的颜⾊将简单的覆盖原来颜⾊缓存区存在的颜⾊值,当深度缓冲区再次打开时,新的颜⾊⽚段只是当它们⽐原来的值更接近邻近的裁剪平⾯才会替换原来的颜⾊⽚段
表中R、G、B、A 分别代表 红、绿、蓝、alpha。
表中下标S、D,分别代表源、⽬标
表中C 代表常量颜⾊(默认⿊⾊)
glBlendFunc 指定 源和⽬标 RGBA值的混合函数;但是glBlendFuncSeparate函数则允许为RGB 和Alpha 成分单独指定混合函数
在混合因⼦表中,
GL_CONSTANT_COLOR,GL_ONE_MINUS_CONSTANT_COLOR,GL_CONSTANT_ALPHA,GL_ONE_MINUS_CONSTANT值允许混合⽅程式中引⼊⼀个常量混合颜⾊。
多重采样缓存区在默认情况下使⽤⽚段RGB值,并不包含颜⾊的alpha成分,我们可以通过调⽤glEnable来修改这个⾏为:
(本文为学习笔记,图片来自cc老师)