OpenGL

OpenGL基础之Depth Testing

就像color-buffer存储了所有片元的颜色一样,depth-buffer存储了每一个片元的深度信息。它是由窗口系统自动创建并存储深度值的,深度值的精度一般有16位、24位和32位float,比较常用的深度精度为24位。

当深度测试打开后,OpenGL会测试每个片元的深度值与depth-buffer中数值,如果测试通过,则会更新depth-buffer中的值,如果测试通不过,则会舍弃这个片元。

深度测试发生在片元着色器执行之后的屏幕空间,屏幕空间坐标与glViewport函数定义的视口大小直接相关,并且可以通过GLSL的内建变量gl_FragCoord来访问。gl_FragCoord代表了屏幕空间的坐标值(左下角为(0,0)),gl_FragCoord的z值就是片元的深度值,最后的深度测试就是对比这个值跟depth-buffer中的值。

现在大部分的GPU都支持一项称为early depth testing的特性,early depth testing允许在片元着色器执行之前进行深度测试,这样就可以避免那些根本看不到的片元进行片元着色,这样可以提高程序性能。但是,一旦使用了early depth testing,就不能再在片元着色器中写深度值。

OpenGL基础之Shadow Mapping

现有的实时渲染的阴影计算都是tricky的,还没有完美的阴影计算算法。但是有几种很不错的方法来计算阴影,这些方法或多或少都有一些问题,需要我们在实现的时候注意。

在现有的视频游戏领域,有一种称为shadow mapping的方法。该方法简单易懂,开销也低,可以提供一个不错的阴影效果,并且可以很方便地扩展到高级的阴影算法(OSM,CSM)。

shadow mapping的原理是:

我们从光源位置处渲染一遍场景(即将视点放在光源位置,渲染一次场景),所有在该视锥体中看到的物体,都是被光照照到的;所有没被看到的物体都是位于阴影中的。如图

OpenGL基础之Shadow Mapping

图中所有蓝色的片元都是被光照点亮的,而黑色的则处于阴影当中。

通过这种对比,我们可以利用深度图,来比较像素是否处于阴影当中,实现的方法是:

pass1:我们从光源位置渲染一遍场景,取得场景的深度buffer,输出为一张depth map或者叫shadow map的纹理;

OpenGL状态机理解

状态机是理论上的一种机器,呃这个说法非常非常的抽象。通俗一点理解,状态机描述了一个对象在其生命周期内所经历的各种状态,状态间的转变,发生转变的动因,条件及转变中所执行的活动。或者说,状态机是一种行为,说明对象在其生命周期中响应事件所经历的状态序列以及对那些状态事件的响应。因此具有以下特点:

1.有记忆功能,能记住其当前的状态;

2.可以接收输入,根据输入的内容和自己的原先状态,修改自己当前状态,并且可以有对应输出;

3.当进入特殊状态(停机状态)的时候,变不再接收输入,停止工作;

虽然还是很抽象,但结合实例理解就容易明白了,如身边的电脑,就是一典型的状态机,对照理解如下:

1. 电脑的存储器(内存、硬盘等),可以记住电脑自己当前的状态(如保存在电脑中的数据,即二进制的值,都属于当前的状态);

2. 电脑的输入设备接收输入(键盘和鼠标输入等),根据输入的内容和自己的状态,修改自己的状态(修改内存中的值),并且可以得到输出(将结果显示到屏幕)。

3. 当进入关机状态的时候,它不再接收输入,停止工作。

同理,OpenGL也可以类似这样的理解:

1. OpenGL可以记录自己的状态(如当前所使用的颜色、是否开启了混合功能等);

OpenGL绘制基本图形单元的方法

1.点绘制

OpenGL提供了一系列函数。它们都以glVertex开头,后面跟一个数字和1~2个字母。例如:
glVertex2d(x,y)
glVertex2f(x,y)
glVertex3f(x,y,z)

glVertex3fv(GLfloat *p)

数字表示参数的个数:

2表示有两个参数,3表示三个;

字母表示参数的类型:

i表示32位整数(OpenGL中将这个类型定义为GLint和GLsizei),
f表示32位浮点数(OpenGL中将这个类型定义为GLfloat和GLclampf),

d表示64位浮点数(OpenGL中将这个类型定义为GLdouble和GLclampd)。

glVertex2i(3, 3);
glVertex2f(3.0f, 3.0f);
glVertex3f(3.0f, 3.0f, 0.0f);

GLfloat p[] = { 3.0f,3.0f, 0.0f };

glVertex3fv(p)

注:OpenGL中定义的点可以有不同的尺寸,其函数形式为:

void glPointSize( GLfloat size );
  参数size设置点的宽度(以象素为单位),必须大于0.0,缺省时为1.0。

OpenGL学习——光照

OpenGL场景中模型颜色的产生,大致为如下的流程图所描述:

OpenGL学习——光照

(1)当不开启光照时,使用顶点颜色来产生整个表面的颜色。

用glShadeModel可以设置表面内部像素颜色产生的方式。GL_FLAT/GL_SMOOTH.

(2)一般而言,开启光照后,在场景中至少需要有一个光源(GL_LIGHT0...GL_LIGHT7)

通过glEnable(GL_LIGHT0) glDisable(GL_LIGHT0) 来开启和关闭指定的光源。

--- 全局环境光 ---

GLfloat gAmbient[] = {0.6, 0,6, 0,6, 1.0};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, gAmbient);

(3)设置光源的光分量 -- 环境光/漫色光/镜面光

默认情况下:

GPU渲染之OpenGL的GPU管线

GPU渲染流水线,是硬件真正体现渲染概念的操作过程,也是最终将图元画到2D屏幕上的阶段。GPU管线涵盖了渲染流程的几何阶段和光栅化阶段,但对开发者而言,只有对顶点和片段着色器有可编程控制权,其他一律不可编程。如下图:

GPU渲染之OpenGL的GPU管线

简单总结GPU管线,这阶段中主要是对图元进行操作。首先,将由应用阶段加载到显存中的顶点数据(由drawCall指定后)作为输入传递给顶点着色器。接着,顶点着色器首先对图元的每个顶点设置模型视图变换及投影变换(即右乘MVP矩阵),然后将变换后的顶点按照摄像机视椎体定义(即透视投影,或正投影)进行裁剪,将不在视野内的顶点去掉并剔除某些三角面片。最后到几何阶段的屏幕映射,负责把修改过的图元的坐标转换到屏幕坐标系中(即投影到屏幕上)。

关于OpenGL的绘制上下文

什么是绘制上下文(Rendering Context)

初学OpenGL,打开红宝书,会告诉你OpenGL是个状态机,OpenGL采用了客户端-服务器模式,那时觉得好抽象,直到后来了解了绘制上下文才把这些联系起来。我们可以认为每一个硬件GPU是个服务器,每一个绘制上下文对应于申请的一个客户端,一个客户端维护着一套状态机,如果两个窗口分别对应两个不同的绘制上下文,则两个窗口彼此状态独立。申请绘制上下文,意味着系统资源的申请,每个绘制上下文还是需要不少资源的,记得曾经试过在chrome的TAB页不断加载WebGL页面,由于WebGL使用的是OpenGL ES,同样需要绘制上下文,当加载三十多个页面的时候,Chrome整个崩溃了。

所有的OpenGL调用,都需要指定是在哪个上下文环境下调用的。不同的上下文中,同样的资源ID,可能对应于各自上下文中不同类型的资源。

不同的操作系统,都有各自的绘制上下文创建、和设置当前绘制上下文的API。

如何创建绘制上下文

[译]OpenGL像素缓冲区对象

OpenGL ARB_pixel_buffer_object 扩展与ARB_vertex_buffer_object.很相似。为了把像素数据你储存在缓冲区对象中,而非顶点数据,它简单地扩展了 ARB_vertex_buffer_object extension。储存像素数据的缓冲区对象称为Pixel Buffer Object (PBO). ARB_pixel_buffer_object extension借用了VBO所有的架构及API,但多了两个"target" 标签。target协助PBO储存管理器(OpenGL驱动)决定缓冲区对象的最佳位置: system 内存, AGP (共享内存)或显卡内存。Target标志指定PBO的两种不同的操作:GL_PIXEL_PACK_BUFFER_ARB 传递像素数据到PBO中。或GL_PIXEL_UNPACK_BUFFER_ARB 从PBO中传回数据。

OpenGL像素缓冲区对象

OpenGL——混合的基本知识

混合是一种常用的技巧,通常可以用来实现半透明。但其实它也是十分灵活的,你可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象。

混合是什么呢?混合就是把两种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。

假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新的颜色,看上去就好像玻璃是半透明的。

要使用OpenGL的混合功能,只需要调用:glEnable(GL_BLEND);即可。
要关闭OpenGL的混合功能,只需要调用:glDisable(GL_BLEND);即可。

注意:只有在RGBA模式下,才可以使用混合功能,颜色索引模式下是无法使用混合功能的。

一、源因子和目标因子

前面我们已经提到,混合需要把原来的颜色和将要画上去的颜色找出来,经过某种方式处理后得到一种新的颜色。这里把将要画上去的颜色称为“源颜色”,把原来的颜色称为“目标颜色”。

OpenGL中的坐标系和变换

坐标系

模型坐标

模型坐标是以物体某一点为原点而建立的坐标系,该坐标系仅对该物体适用,用来简化对物体各部分坐标的描述。物体放到场景中时,各部分经历的坐标变换相同,相对位置不变,所以可视为一个整体,与人类的思维习惯一致。

世界坐标

世界坐标系以屏幕中心为原点(0,0,0)。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定: 窗口范围按此单位恰好是(-1,-1)到(1,1)。

相机坐标

相机坐标以视点为原点,以视线的方向为Z+轴正方向的坐标系中的方向。OpenGL管道会将世界坐标先变换到眼坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算。

投影坐标

同步内容
--电子创新网--
粤ICP备12070055号