较真一下OpenGL Clip Space和NDC

在OpenGL ES 2.0 Programming Guide里面,有一段:

uniform mat4   u_mvpMatrix; // matrix to convert P from model
                                                   // space to normalized device space.

这个地方的注释将mvp矩阵解释为是将顶点变换到NDC的矩阵。看到这儿我困惑了一下,查了查以前写的博客,我是这样认为的:经过投影矩阵,顶点被变换到投影空间,即clip space,然后再经过透视除法,顶点被变换到NDC。
这个地方其实应该只是一处笔误(或者说作者意思nds是clip space而不是ndc),因为书后面讲图元装配的章节是说的很清楚的,无论如何,我还是把clip space和NDC再理一下,正好结合一下gles 2.0。

1) 顶点通过vertex shader,乘以mvp矩阵,被变换到clip space, 变换后的值写入gl_Position。
clip space中,顶点是4d齐次坐标(x,y,z,w),w=-Ze, 即eye空间z坐标的负值。这儿会有个错误的理解,以为x,y,z的范围是[-1,1],其实这是由于很多地方把clip space和NDC混为一谈了,NDC的范围是一个[-1,1]的立方体(OpenGL中,DX还不太一样),而clip sapce并不是NDC。clip space中的点经过透视除法,除以w之后,范围在[-1,1]的点进入NDC,其他的点被裁剪,因此才叫clip space。

参考:http://stackoverflow.com/questions/21841598/clip-space-and-screen-space

No, clip space and NDC space are not the same thing.

Clip space is actually 1 step away from NDC, all coordinates are divided by Clip.W to produce NDC. Anything outside of the range [-1,1] in resulting NDC space corresponds to a point that is outside of the clipping volume. There is a reason the coordinate space before NDC is called clip space ;)

Strictly speaking, however, NDC space is not necessarily cubic. True NDC space is a cube in OpenGL, but in Direct3D it is not. In D3D the Z coordinate in NDC space ranges from0.0 to 1.0, whereas it ranges from -1.0 to1.0 in GL. X and Y behave the same in GL's NDC as D3D's NDC (that is, they range from-1.0 to 1.0). NDC is a standard coordinate space, but it has different representation in different APIs.

Lastly, NDC space to screen space (AKA window space) occurs during rasterization and is defined by your viewport and depth range. Fragment locations really would not make sense in any other coordinate space, and this is what rasterization produces:fragments.



2)vs之后是图元装备阶段,图元装备包含3个步骤:clipping, 透视除法,viewport变换。

首先会进行的是剪裁(clipping)。clip会根据图元的类型进行处理,对于三角形如果图元部分处于clip space外面则三角形会被切割并生成新顶点形成一个三角扇。对于线如果部分剪裁就会被截断,也会生成新顶点。对于point sprite有点点特殊,点的位置只是用来检测是否在near,far plane之间,而quard会被用来检测是否在clip space之外,并且只要point sprite不被丢弃就直接保留原样(不会做部分剪裁),只是依靠scissor测试来做2d剪裁。
(clip volume的范围是[-w,w])

clipping之后就是透视除法了,通过clip的点(以及新生成的点)经过透视除法从clip齐次坐标变成了3d的NDC坐标。透视除法其实就是x/w,y/w,z/w。由于w=-Ze,因此这个除法就对x,y坐标产生了透视效果(近大远小),因此称为透视除法。显然NDC坐标(x,y,z)的范围是[-1,1],他是3d坐标,没有w。

再之后就是viewport变换,将3d的NDC坐标变换为3d的窗口坐标。x,y进过线性映射,变换到窗口坐标系x,y,而z会映射到depth range,经过z test后写入z buffer。viewport是由glViewport(x,y,w,h)定义的。depth range由glDepthRange(n,f)定义。

以上是自己的一些认识,也可能有错误,留待后看。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值