/LGC图形渲染/OpenGL 概念建立

来源:互联网 发布:软件测试考核 编辑:程序博客网 时间:2024/05/16 14:33
OpenGL 概念建立
作者: 刘鹏
日期: 2009-06-30
本文从概念、接口、工作流程、操作步骤等方面对 OpenGL 做了详细介绍,力图使读者阅读后能够对 OpenGL 有个综合性的把握。

What is OpenGL

  • OpenGL is a software interface to graphics hardware.
  • Library of about 250 commands, platform and hardware independent.
  • The base library supports very minimal shape primitives:points, lines and polygons
  • Higher level libraries add more rendering abilities and higher level operations (draw spheres, cylinders, teapots, etc)

OpenGL Extensions

Open Extensions: Other libraries add higher level constructs

  • GLU: GL Utility Library

    Adds support for textures, additional shapes (spheres, cylinders, disks)

  • GLUT: GL Utility Toolkit

    Adds UI level things like windows, menus, keyboard, mouse events, etc.

Naming Conventions

  • Function names indicate what library function belongs to:
    • glBegin(), glEnd(), glLight(), glPointSize()
    • gluBeginCurve(), glCylinder(), glSphere()
    • glutCreateWindow(), glutSetCursor()
  • Often indicate parameter types
    • void glVertex2d(GLdouble x, GLdouble y);
    • void glVertex2i(GLint x, GLint y);
    • void glVertex4f(GLfloat x, GLfloat y,GLfloat z, GLfloat w);
  • Parameter types
    • b signed char (8-bit)
    • s signed short (16-bit)
    • i signed int (32-bit)
    • f signed float (32-bit)
    • d signed double (64-bit)
    • ub unsigned char (8-bit)
    • us unsigned short (16-bit)
    • ui unsigned int (32-bit)

OpenGL 基本理解2

OpenGL 是一个与硬件图形发生器的软件接口,它包括了100多个图形操作函数,开发者可以利用这些函数来构造景物模型、进行三维图形交互软件的开发。OpenGL 是一个高性能的图形开发软件包。OpenGL 支持网络,在网络系统中用户可以在不同的图形终端上运行程序显示图形。OpenGL 作为一个与硬件独立的图形接口,它不提供与硬件密切相关的设备操作函数,同时,它也不提供描述类似于飞机、汽车、分子形状等复杂形体的图形操作函数。用户必须从点、线、面等最基本的图形单元开始构造自己的三维模型。当然,象 Blender 那样更高一级的基于 OpenGL 的三维图形建模开发软件包将提供方便的工具。因此 OpenGL 的图形操作函数十分基本、灵活。例如 OpenGL 中的模型绘制过程就多种多样,内容十分丰富,OpenGL 提供了以下的对三维物体的绘制方式:

  • 网格线绘图方式(wireframe):这种方式仅绘制三维物体的网格轮廓线。
  • 深度优先网格线绘图方式(depth_cued):用网格线方式绘图,增加模拟人眼看物体一样,远处的物体比近处的物体要暗些。
  • 反走样网格线绘图方式(antialiased):用网格线方式绘图,绘图时采用反走样技术以减少图形线条的参差不齐。
  • 平面消隐绘图方式(flat_shade):对模型的隐藏面进行消隐,对模型的平面单元按光照程度进行着色但不进行光滑处理。
  • 光滑消隐绘图方式(smooth_shade):对模型进行消隐按光照渲染着色的过程中再进行光滑处理,这种方式更接近于现实。
  • 加阴影和纹理的绘图方式(shadows、textures):在模型表面贴上纹理甚至于加上光照阴影,使得三维景观象照片一样。
  • 运动模糊的绘图方式(motion-blured):模拟物体运动时人眼观察所感觉的动感现象。
  • 大气环境效果(atmosphere-effects):在三维景观中加入如雾等大气环境效果,使人身临其境。
  • 深度域效果(depth-of-effects):类似于照相机镜头效果,模型在聚焦点处清晰,反之则模糊。

这些三维物体绘图和特殊效果处理方式,说明OpenGL已经能够模拟比较复杂的三维物体或自然景观。

OpenGL工作流程2

整个OpenGL的基本工作流程如下图:

其中几何顶点数据包括模型的顶点集、线集、多边形集,这些数据经过流程图的上部,包括运算器、逐个顶点操作等;图像数据包括象素集、影像集、位图集等,图像象素数据的处理方式与几何顶点数据的处理方式是不同的,但它们都经过光栅化、逐个片元(Fragment)处理直至把最后的光栅数据写入帧缓冲器。在OpenGL中的所有数据包括几何顶点数据和象素数据都可以被存储在显示列表中或者立即可以得到处理。OpenGL中,显示列表技术是一项重要的技术。

OpenGL要求把所有的几何图形单元都用顶点来描述,这样运算器和逐个顶点计算操作都可以针对每个顶点进行计算和操作,然后进行光栅化形成图形碎片;对于象素数据,象素操作结果被存储在纹理组装用的内存中,再象几何顶点操作一样光栅化形成图形片元。

整个流程操作的最后,图形片元都要进行一系列的逐个片元操作,这样最后的象素值BZ送入帧缓冲器实现图形的显示。

OpenGL图形操作步骤2

根据上面讲的 OpenGL 工作流程可以归纳出在 OpenGL 中进行主要的图形操作直至在计算机屏幕上渲染绘制出三维图形景观的基本步骤:

  1. 根据基本图形单元建立景物模型,并且对所建立的模型进行数学描述(OpenGL 中把:点、线、多边形、图像和位图都作为基本图形单元);
  2. 把景物模型放在三维空间中的合适的位置,并且设置视点(viewpoint)以观察所感兴趣的景观;
  3. 计算模型中所有物体的色彩,其中的色彩根据应用要求来确定,同时确定光照条件、纹理粘贴方式等;
  4. 把景物模型的数学描述及其色彩信息转换至计算机屏幕上的象素,这个过程也就是光栅化(rasterization)。

在这些步骤的执行过程中,OpenGL 可能执行其他的一些操作,例如自动消隐处理等。另外,景物光栅化之后被送入帧缓冲器之前还可以根据需要对象素数据进行操作,即所谓的片元(fragment)操作。

片元就是栅格化以后的像素点,它比像素多一些位置啊、法向量等属性。逐个片元操作有像素所有权操作(确定目标像素可见还是被一个重叠的窗口盖住了),剪切测试、Alpha测试、模板测试、混合等。比如,反走样时,OpenGL 要基于屏幕像素块所覆盖的区域, 对每一 块片元的覆盖范围值进行计算。在 RGBA 模块中, OpenGL 要用该值与片元的 alpha 值相乘, 然后, 利用结果alpha 值将片元与缓存中的对应像素混合。

从FRAGMENT到PIXEL(framebuffer 帧缓存)3

关于帧缓存

帧缓存包括颜色、scissor、alpha、stencil、depth 这些缓存,所以帧缓存不是一片缓存,而是所有这些缓存的组合,帧缓存它对应了屏幕上的每一个 pixel(不是真正的 pixel,而是一个 fragment 所对应的位置)的各种这些信息(颜色、ZBUFFER、等等),几何体的 fragment 是没有帧缓存的,帧缓存是屏幕上的,一个缓存的一位就对应一个位片面。

Colorbuffer是最终表现在屏幕上的,但是其他缓存决定了最后这些color是否和怎样绘制在屏幕上.,其中除了colorbuffer的那些帧缓存也称作辅助缓存。

在光栅化得到fragment后,就要按照以下的顺序进行各种测试,那些通过测试了的像素才有资格最后放到屏幕上,在通过所有测试后,这些fragment将可能被写入原有的帧缓存(但是在最后混合出来的颜色值可能与屏幕原有的帧缓存中 的颜色缓存做各种运算,所以颜色缓存有时可能不会被简单覆盖,但其他缓存会。

颜色缓存的读写:glDrawBuffer和glReadBuffer(),然后调用GlwritePixel、glreadpixel等。

缓存掩码(MASK)

可以设置每种帧缓存的掩码,再写入相应缓存时就会被掩码作用,具体表现为

GlIndexmask(Glint mask):如果在索引模式下,当mask的第i位为0时,则第i个索引的颜色不会被写入到颜色缓存中,你会看到原本为那个颜色的区域变成空空的了,为1正常绘制,可以利用他进行层动画。

Glcolormask(GLboolean red,GLboolean green,GLboolean blue,GLbooleanalpha):它可以控制颜色值中的那个通道绘制那个不被绘制(1为绘制),这个可以让你查看各种颜色的渲染,如图是只显示红色的情形:

color maskcolor mask

GlDepthMask(GLboolean flag):当flag为真时写入深度缓存,否则就不写入。默认是写入的,那如果为否不写入你将看到什么效果呢?这样每一帧后绘制的那个物体它不写帧缓存,也就是它的帧缓存默认为最小的0,所以此时你永远看到后绘制的在前面(这跟正常情况下不带开深度测试看到的场景是一样的)。

深度缓存的掩码有很多的应用,例如你可以随时置它与FALSE控制以后的物体为后绘制的现实在最上层。

fragment的测试

注意这里要进行的所有测试都是在fragmen级别上的。测试的意义是;当一个被计算出来的fragment要最终成为屏幕的一个pixel时要按照下面顺序通过测试,如果在哪个阶段不被通过,就会不绘制,如果最后都通过了,确定要在屏幕的颜色缓存上绘制这一点时,还要将这点屏幕缓存该点原先颜色进行某种混合。

Scissor Test:这里通过glScissor()定义一个矩形区域(Scissor box),如果片段在这和矩形内,则通过,不在则不通过(不显示),这个相当于StencilTest的矩形版。效果如下:就像从一小窗口观看的感觉

scissor testscissor test

Alpha test:它的基本功能时利用alpha(RGBA的A) 缓存来判定是否绘制一个像素,虽然它的值经常被用来进行混合效果。用glAlphaFunc()来定义参考值和通过测试的条件。测试的过程是,用fragment的alpha值遇一个定义的参考值做比较,比较的方式由glAlphaFunc指定,通过这个比较来判断是否通过测试。

Alpha test可以制作镂空效果或是billboard,制作billboard的过程是:制作一个贴有rgba四通道的贴图,其中透明部分的alpha为0,反之为1,在场景中为一个细分的多边形贴上这个贴图作为纹理,其中顶点的ALPHA值就为其贴图的点的ALPHA值,最后使用alpha测试,并将比较函数设置为GL_GRETER,参考值为0.5,这样0的那部分就会不通过,变成完全透明的了。

Stencil test:它是一个模板测试,形象的比喻就是在stencil test处理中,会依据stencil buffer这个记忆体中所存放的资料,来决定是否要舍弃像素。它的测试过程是这样的,在所有像素的stencil buffer里面存储了一些值,然后定义了一个比较方法和一个参考值,如果参考值与该点的stencilbuffer里面的值在这种比较方式下通过,那么这点通过测试,被绘制。你不能直接写入stencilbuffer,但是可以通过glStencilOp()来间接写入,这个函数设定当一个fragment通过或者不通过Stencil缓存时Stencil缓存起什么变化。

Stencil test最常用的用途就是在屏幕上定义一块不规则的区域,然后限制在这个区域内显示。它的实现方法是这样的:

首先要清空当前的Stencil缓存为0:glClearStencil(0);glClear(GL_STENCIL_BUFFER_BIT)

然后设定glStencilFunc()为GLALWAYS,1,就是都通过该测试,并且设定GLSENCILOP(GL_REPLACE,GL_REPLACE,GL_REPLACE)接着绘制你希望的不规则区域的形状。这段代码的意思就是让你绘制的那个形状都通过Stencil测试,而且通过后都用1来取代那点的Stencil缓存。这样就把Stencil缓存变成了那块形状的区域为1,定制了一个这种形状的模板,注意每次RESIZE的时候stencil会自动清空掉。

最后要清空屏幕的颜色和深度缓存,然后设定glStencilFunc为GL_EQUAL,1,GLSENCILOP为GL_KEEP(不变Stencil缓存了,最后后绘制你要绘制的场景,这样那些等于1的stencil位置被绘制上了,不等于的就不绘制了,这是这种算法的效果:里面在一个人形的区域内绘制,这对一些游戏的GUI来说很有帮助。

stencil teststencil test

Depth test:通常进行深度测试的过程是这样的,在每一帧开始用一个很大的值来清空深度缓存,然后在绘制时,会自动产生当前的深度,默认采用的比较函数是较小的深度通过测试进行绘制,这样就剔除了背景。当然也可以用glDepthFunc来设置比较函数。

测试之后

当进行过上述测试后,所有即将认为要被写到同一屏幕位置的片段将混合他们的颜色值,作为最后的颜色在最后一步写在屏幕上,在这里可以设置这个混合方式。

Dithering:这一歩时用在索引模式,因为在索引模式下如果混合后的颜色不再索引中,他将找一种所颜色拼凑的方式来替代,打开GL_DITHER的开关即可。

最后一步逻辑操作:最后一步时逻辑操作,我们在前面生成了将写在屏幕上的颜色,而此时COLORBUFFER有刚才的颜色值,这是可以选择对这两个值进行操作,默认是GL_COPY,也就是单纯拷贝新值到屏幕上,但是事实上还有很多可选的逻辑操作,当然要打开GL_COLOR_LOGIC_OP/INDEX开关。其实这个操作时非常有用的,它可以直接控制最后在屏幕上的显示状况,它只是改变最后屏幕上的像素,所以可以很轻松的实现肯多小TRIK,如颜色反置,切换场景与清空等等。

关于Accumulation Buffer

这个framebuffer和测试无关,它用来累计颜色缓存上的值,也就是说他可以将每帧的颜色缓存的值类加到她这里,然后她还可以把他累加的内容重新写入颜色缓存,我们看上去就像一幅几张图像叠加的照片。我们可以控制这些过程。glAccum()控制对这个缓存的操作,通常有开始累加,清空重新累加、写到屏幕颜色缓存、数值运算等操作。可以利用buffer进行反走样和模糊处理。使用前要在最前面打开GLUT_ACCUM模式,这个缓存有很多用处:如反走样、模拟运动模糊、模拟多重曝光(即产生HDR图)、产生软影(soft shadow)等等。

OpenGL in Max OS X

Quartz uses OpenGL for all the whizzy effects like the genie effect when minimizing, Exposé and cube rotationscompiz effect.

FAQ

Q:How do I obtain the address of the OpenGL framebuffer, so I canwrite directly to it?

A:OpenGL doesn't provide a standard mechanism to let an application obtain the address of the framebuffer. If an implementation allows this, it's through an extension.

Typically, programmers who write graphics programs for a single standard graphics hardware format, such as the VGA standard under Microsoft Windows, will want the framebuffer's address. The programmers need to understand that OpenGL is designed to run on a wide variety of graphics hardware, many of which don't run on Microsoft Windows and therefore, don't support any kind of standard framebuffer format. Because a programmer will likely be unfamiliar with this proprietary framebuffer layout, writing directly to it would produce unpredictable results. Furthermore, some OpenGL devices might not have a framebuffer that the CPU can address.

You can read the contents of the color, depth, and stencil buffers with the glReadPixels() command. Likewise, glDrawPixels() and glCopyPixels() are available for sending images to and BLTing images around in the OpenGL buffers.

Online Tutorial

  • OpenGL 基础图形编程

See Also

  1. Mac OS X Cocoa Programming
  2. OpenGL基础图形编程 - OpenGL概念建立
  3. Opengl编程学习笔记(五)——从FRAGMENT到PIXEL(framebuffer 帧缓存)
原创粉丝点击