gluOrtho2D 函数设置二维正交裁剪区域。 相当于调用 zNear = -1 且 zFar = 1 的 glOrtho 。
glOrtho定义二维正交投影矩阵,这个矩阵会把视图(摄像机)空间的坐标转换到一个裁剪空间,一言以蔽之:glOrtho定义了裁剪空间(Clip Space)
void WINAPI glOrtho(
GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble zNear,
GLdouble zFar
);
参数
left, right 指定可视空间的左边界和右边界
bottom, top 指定可视空间的下边界和上边界
zNear:距离较近的深度剪裁平面。
zFar:到更远深度剪裁平面的距离。
正交投影的裁剪空间如图:
我们写gl代码时候,glOrtho是用来指定屏幕绘制区域的逻辑坐标范围的,调用glOrtho后,我们代码中要传给着色器的顶点坐标值,就不再是规范化了的取值范围,不再是-1~1;而是我们自定义的一个范围, 我们自己所绘制的图形的坐标必须设置在这个范围内,不然不能看到自己绘制的图形。
如果想把逻辑坐标范围变成规范化坐标(-1~1)只需要这样调用:
glOrtho(-1,1,-1,1,-1,1); 这样调用所产生的坐标系为:原点在中间 x:[-1,1],y:[-1,1]。
看来glOrtho同时也定义了原点(0,0)的方位。
- 例1我们这样调:glOrtho(0,100,0,100,-100,100);那么我们的坐标空间范围是:
x:[0,100](x取0在最左边,x取100在最右边)
y:[0,100](y为0在最下方bottom,y为100在最上方top)
因此得到原点在左下角
- 例2 glOrtho(100,0,100,0,-100,100);坐标空间范围是:
x:[0,100](100最左边,0最右边)
y:[0,100](100在最下方,0在最上方)
因此得到原点在右上角
- 例3 glOrtho(-100,100,-100,100,-100,100);坐标空间范围是:
x:[-100,100](-100最左边,100最右边)
y:[-100,100](-100在最下方,100在最上方)
因此得到原点在中心点
代码案例:
void render()
{
//! 指定以下的操作针对投影矩阵
glMatrixMode(GL_PROJECTION);
//! 将投影举证清空成单位矩阵
glLoadIdentity();
int WIDTH = 500;
int HEIGHT = 500;
glViewport(0, 0, WIDTH, HEIGHT);
glOrtho(0,500, 500,0,-100,100);//左上角为原点
//以0-500为坐标范围,画我们的坐标系空间矩形
Vertex viewRect[] =
{
{0, 0, 0, 0.5, 0.5, 0.5},
{WIDTH, 0, 0, 0.5, 0.5, 0.5},
{0, HEIGHT, 0, 0.5, 0.5, 0.5},
{WIDTH, HEIGHT, 0, 0.5, 0.5, 0.5},
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), viewRect);
glColorPointer(3, GL_FLOAT, sizeof(Vertex), &viewRect[0].r);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//以0-500为坐标范围 画三角形
Vertex vertex[] =
{
{10, 10, 0, 1, 0, 0},//红色顶点 //左上角
{490, 10, 0, 0, 1, 0},//绿色顶点 //右上角
{250, 250, 0, 0, 0, 1},//蓝色顶点 //中心点
};
glColor3f(1,0,1);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof(Vertex), vertex);
glColorPointer(3,GL_FLOAT,sizeof(Vertex),&vertex[0].r);
glDrawArrays(GL_LINE_LOOP,0,3);
glLoadIdentity();
//以-1-1为坐标范围 画三角形
glOrtho(-1,1, -1, 1, -100, 100);//中心为原点
Vertex vertex1[] =
{
{-0.9, -0.9, 0, 1, 0, 0},//红色顶点 //左下角
{0.9, -0.9, 0, 0, 1, 0},//绿色顶点 //右下角
{0, 0, 0, 0, 0, 1},//蓝色顶点 中心点
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), vertex1);
glColorPointer(3, GL_FLOAT, sizeof(Vertex), &vertex1[0].r);
glDrawArrays(GL_LINE_LOOP, 0, 3);
}
运行效果:灰色区域是我们的坐标范围x和y都是0-500,上面的三角形蓝色顶点坐标是(250,250),下面的三角形蓝色顶点坐标是(0,0),这两个点都在灰色矩形中心点
cocos2dx中创建正交投影矩阵的函数:
void Mat4::createOrthographicOffCenter(float left, float right, float bottom, float top,
float zNearPlane, float zFarPlane, Mat4* dst)
{
GP_ASSERT(dst);
GP_ASSERT(right != left);
GP_ASSERT(top != bottom);
GP_ASSERT(zFarPlane != zNearPlane);
memset(dst, 0, MATRIX_SIZE);
dst->m[0] = 2 / (right - left);
dst->m[5] = 2 / (top - bottom);
dst->m[10] = 2 / (zNearPlane - zFarPlane);
dst->m[12] = (left + right) / (left - right);
dst->m[13] = (top + bottom) / (bottom - top);
dst->m[14] = (zNearPlane + zFarPlane) / (zNearPlane - zFarPlane);
dst->m[15] = 1;
}
这个函数生成的矩阵大概是这个样式:
OpenGL中当前矩阵乘以这样一个正交投影矩阵时,对世界中的物体进行了缩放和位移,下面是变换矩阵各项元素的作用(列优先):
| m[0] m[4] m[8] m[12] |
| m[1] m[5] m[9] m[13] |
| m[2] m[6] m[10] m[14] |
| m[3] m[7] m[11] m[15] |
1.位置(平移):m[12], m[13], m[14]
m[12] 控制沿x轴的平移。
m[13] 控制沿y轴的平移。
m[14] 控制沿z轴的平移。
2.缩放:m[0], m[5], m[10] 和 m[15]
m[0], m[5], m[10] 控制沿x、y和z轴的缩放。这些值决定了物体在各个方向上的大小。例如,如果m[0] = 2,那么物体在x轴方向上将放大两倍。
m[15] 控制整体缩放。这个值会影响物体在所有方向上的大小。例如,如果m[15] = 0.5,那么物体在所有方向上都将缩小到原来的一半。
3.旋转:绕x轴旋转θ角度:
其他轴的旋转矩阵省略