OpenGL中window(窗口)、viewport(视口)和裁剪区域

最近在学OpenGL,是个新手。在看蓝宝书的时候,发现上面解释的窗口、视口和剪裁区域有些难以理解(因为之前没有学习过计算机图形学或者MFC等GDI编程,所以对这些概念不好理解)。在谷歌上也搜过,发现有很多人解释这些词,不过还有些模糊。经过一段时间的郁闷与纠结,逐渐的了解了这些概念(不保证完全正确,只代表本人的观点,如有不对,请发邮件批评指正)。

之所以有这些概念,是因为图形的坐标需要转换。我们先以2维坐标系为例,3维的是一个道理,只不过加了一个z轴而已。

1.直角坐标系:是由两条相互垂直的轴确定了一个2维平面。你想要画的任何图形必须在这个坐标系中表示出来,也就是说图形中的每个点都必须有个坐标,这个比较容易理解。直角坐标系只是一个逻辑上的坐标系,也就是说这个坐标系是你自己想出来的,比如你自己想的这个直角坐标系的原点(0,0)在显示屏的左下角,向右为x轴正方向,向上为y轴正方向,又比如你自己想的这个坐标系的原点(0,0)位于显示屏的中间,向右为x轴正方向,向左为其负方向,向上为y轴正方向,向下为其负方向等等。这个坐标系只是你自己想出来的,假设你在这个直角坐标系中画了2个点,坐标为(1,0)和(100,100),你画的这两个点只是在你想的这个坐标系中而已,如果你要打印显示屏的话,这些点可能和你想象中的位置不一样,原因很简单,可能显示屏的坐标系与你自己想的这个坐标系不重合。比如你自己想的坐标系的原点是位于显示屏的左下角,而屏幕的坐标系(这个坐标系是由某些标准规定的,我这里只是随便举个例子)的原点位于显示屏的中间(假设在你想的坐标系中,显示屏的中间点的坐标为(300, 200),就是说屏幕宽600像素,高400像素),这时你画的两个点(1,0)和(100,100)在两个坐标系中表现的完全不一样。由此,可以得到两个概念,一个是显示屏的坐标系,即所说的设备坐标系;另一个是你自己想的坐标系,即逻辑坐标系。

2.裁剪区域:在上一步的逻辑坐标中,我们画了2个点(1,0)(100,100),但是,这个点只是出现在我们的逻辑坐标中,并不一定会出现在我们的设备坐标中,也就是说不一定会显示在我们的屏幕上。那么,我们怎么保证我们再逻辑坐标中画的图形能够显示到设备坐标中呢?这就让剪裁区域派上用场了。剪裁区域是处于逻辑坐标中的一个矩形区域,这个矩形区域可以自己设置大小,在这个矩形区域出现的任何图形都会被映射到设备坐标中,即你能在屏幕上看到这些图形,而在这个矩形区域之外的图形,不能够被映射到设备坐标中,当然就无法从屏幕上看到这些图形。举例来说,你自己设置的剪裁区域的左下角坐标为(0,0),右上角坐标为(50,50),也就是说这个剪裁区域宽50像素,高50像素,那么第一个点(1,0)处于这个剪裁区域内,而第二个点(100,100)在这个剪裁区域外,因此,第一个点能够从逻辑坐标系映射到设备坐标系中,在屏幕上显示出来,而第二个点不能被映射,也就不能被显示。所以,我们要把想要别人看到的图形放入到裁剪区域中,不想让别人看到的图形放到剪裁区域之外。剪裁区域的大小是自己设置的,不可能任何时候都和整个显示屏窗口一样大小。

3.视口:视口(viewport),作用就是把剪裁区域中的图形的坐标映射到设备坐标,使得转换后的图形能够看起来和在你想象的逻辑坐标系中位置、比例等等相同。视口也可以定义,可以定义为和整个显示屏的窗口一样大,也可以定义的和剪裁区域一样大,也可以设置的很小很小。当视口被定义为何窗口一样大时,你可以理解为剪裁区域内的图形被全屏放到了屏幕上;当定义的和剪裁区域一样大时,你可以理解为图形直接被原样大小的从剪裁区域映射到了相同大小的屏幕区域内而已。

4.窗口:窗口就是显示屏的整个屏幕了,这个没有必要解释太多了。