OpenGL: glDepthRange的理解

与x和y窗口坐标不同,在OpenGL中,z坐标总是被认为位于0.0~1.0的范围之间。可通过glDepthRange()调整。

API中队glDepthRange的解释:
After clipping and division by w, depth coordinates range from -1 to 1,corresponding to the near and far clipping planes.glDepthRange specifies a linear mapping of the normalized depth coordinates in this range to window depth coordinates. Regardless of the actual depth buffer implementation, window coordinate depth values are treated as though they range from 0 through 1 (like color components). Thus, the values accepted by glDepthRange are both clamped to this range before they are accepted.

也就是说,在OpenGL中绘制的时候所使用的三维坐标(x,y,z),其深度坐标z最后都会被压缩到[0,1]的范围存储起来。

为了证明这一点,使用gluUnProject来进行验证:

#include <windows.h>
#include <GL/glut.h>
#include <GL/glaux.h>
#pragma comment(lib,"glut32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"opengl32.lib")

#include <math.h>
#include <iostream>
using namespace std;
GLfloat vertexArr1[] = {    -5.0,    0.0,    0.0,
5.0,    0.0,    0.0,
0.0,    10.0,    0.0,
-5.0,    5.0,    -5.0,
5.0,    5.0,    -5.0,
0.0,    -5.0,    -5.0};
int vertArrSize = 6;
double calcDist(GLdouble _x,GLdouble _y,GLdouble _z,GLdouble _wx0,GLdouble _wy0,GLdouble _wz0,GLdouble _wx1,GLdouble _wy1,GLdouble _wz1) {
	double tDx = _wx1 - _wx0;
	double tDy = _wy1 - _wy0;
	double tDz = _wz1 - _wz0;
	double tDisUnit = sqrt(tDx*tDx + tDy*tDy + tDz * tDz);
	tDx = tDx / tDisUnit;
	tDy = tDy / tDisUnit;
	tDz = tDz / tDisUnit;
	double tVecX = _wx0 - _x;
	double tVecY = _wy0 - _y;
	double tVecZ = _wz0 - _z;

	double tDisX = tDy*tVecZ - tDz*tVecY;
	double tDisY = -tDx*tVecZ + tDz*tVecX;
	double tDisZ = tDx*tVecY - tDy*tVecX;
	return sqrt(tDisX*tDisX + tDisY*tDisY + tDisZ*tDisZ);
}
int findClosestPt(GLdouble _wx0,GLdouble _wy0,GLdouble _wz0,GLdouble _wx1,GLdouble _wy1,GLdouble _wz1) {
	double minDis;
	int minDisPos;
	minDisPos = 0;
	minDis = calcDist((double)vertexArr1[0], (double)vertexArr1[1], (double)vertexArr1[2], _wx0, _wy0, _wz0, _wx1, _wy1, _wz1);
	for(int i=1; i<vertArrSize; i++) {
		int offset = i * 3;
		double tmpDis = calcDist(vertexArr1[offset], vertexArr1[offset+1], vertexArr1[offset+2], _wx0, _wy0, _wz0, _wx1, _wy1, _wz1);
		if(tmpDis < minDis) {
			minDis = tmpDis;
			minDisPos = i;
		}   
	}
	return minDisPos;
}
void init() {
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);
}
void display() {
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0, 1.0, 0.1, 500.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	glColor3f(1.0, 0.0, 0.0);
	glBegin(GL_LINE_LOOP);
	for(int i=0; i<3; i++) {
		int offset = i*3;
		glVertex3f(vertexArr1[offset], vertexArr1[offset+1], vertexArr1[offset+2]);
	}
	glEnd();
	glColor3f(0.0, 1.0, 0.0);
	glBegin(GL_LINE_LOOP);
	for(int i=3; i<6; i++) {
		int offset = i*3;
		glVertex3f(vertexArr1[offset], vertexArr1[offset+1], vertexArr1[offset+2]);
	}
	glEnd();
	glFlush();
}
void mouse(int button, int state, int x, int y) {
	GLint viewport[4];
	GLdouble mvmatrix[16], projmatrix[16];
	GLint realy;
	GLdouble wx0, wy0, wz0;
	GLdouble wx1, wy1, wz1;
	switch(button) {
	case GLUT_LEFT_BUTTON:
		if(state == GLUT_DOWN) {
			//printf(" %d %d \n", x, y);
			glGetIntegerv(GL_VIEWPORT, viewport);
			glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
			glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
			realy = viewport[3] - (GLint)y - 1;
			//printf("Coordinates at cursor are (M, M)\n", x, realy);
			gluUnProject((GLdouble)x, (GLdouble)realy, 0.0, mvmatrix, projmatrix, viewport,
				&wx0, &wy0, &wz0);
			printf("World coords at z=0.0 are (%.3f, %.3f, %.3f)\n", wx0, wy0, wz0);
			gluUnProject((GLdouble)x, (GLdouble)realy, 1.0, mvmatrix, projmatrix, viewport,
				&wx1, &wy1, &wz1);
			printf("World coords at z=1.0 are (%.3f, %.3f, %.3f)\n", wx1, wy1, wz1);
			int i = findClosestPt(wx0, wy0, wz0, wx1, wy1, wz1);
			int offset = i*3;
			printf("Choose Point (%.3f, %.3f, %.3f)\n\n", vertexArr1[offset], vertexArr1[offset+1], vertexArr1[offset+2]);
		}
		break;
	default:
		break;
	}
}
int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(300, 300);
	glutCreateWindow(argv[0]);
	init();
	glutDisplayFunc(display);
	glutMouseFunc(mouse);
	glutMainLoop();
	return 0;
}
结果如下:

上述代码的部分返回结果为:

World coords at z=0.0 are (0.000, 0.020, 49.900)
World coords at z=1.0 are (1.381, 100.795, -450.017)
Choose Point (0.000, 10.000, 0.000)

在z=0.0 & z=1.0反算出的三维点坐标的z相差刚好约为500,与视景体的设置(500)吻合。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值