glUnproject 和重绘场景后出现奇怪的结果
对于我正在编写的算法,我需要取消投影屏幕坐标并将它们重新投影到光空间中。如下所示:我填充从我的视点观看的深度缓冲区(使用 glLookAt),然后将所有可见像素取消投影到世界空间。然后我将它们重新投影到光空间中。
我正在检查一切以确保我没有犯错误(此后我必须做一些其他事情),所以我画了从光空间看到的新投影像素。为了确保得到正确的结果,我假设我的灯与我的眼睛位于同一位置。
是原来的场景。然后我取消投影并重新绘制它们,得到以下结果:
void getObjectCoords(){
std::vector<GLfloat> z(800*600, 0);
std::vector< Vertex > lightPoints;
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLdouble posX, posY, posZ;
//Setting our original viewpoint for unprojecting
gluLookAt(4.0,4.0,15.0, 0.0,0.0,0.0,0.0,1.0,0.0);
//Getting Modelviewx, Projection and viewport matrix
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
//Reset the modelview
glLoadIdentity();
//Get the depth coordinate of the original points
glReadPixels( 0, 0,800, 600,GL_DEPTH_COMPONENT,GL_FLOAT, &z[0] );
//Unprojecting X and Y.
int count = 0;
Vertex temp;
for( int X = 0; X < 800; ++X){
for( int Y = 0; Y < 600; ++Y){
gluUnProject( X, Y, z[X*600 + Y], modelview, projection, viewport, &posX, &posY, &posZ);
if( z[X*600 + Y] < 1){
++count;
temp.x = posX;
temp.y = posY;
temp.z = posZ;
lightPoints.push_back(temp);
}
}
}
std::cout << count << " pixels closer to the viewpoint" << std::endl;
//Projecting the original points to lightspace
gluLookAt( 4.0, 4.0, 15.0, 0.0,0.0,0.0,0.0,1.0,0.0);
//We get the new modelview matrix
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
//We reset the modelview matrix
glLoadIdentity();
GLdouble winX, winY, winZ;
//Projecting the points into lightspace and saving the sample points
for(vector<Vertex>::iterator vertex = lightPoints.begin(); vertex != lightPoints.end(); ++vertex){
gluProject( vertex->x, vertex->y, vertex->z,modelview, projection, viewport, &winX, &winY, &winZ );
temp.x = winX;
temp.y = winY;
temp.z = winZ;
samplePoints.push_back(temp);
}
//std::cout << count << " pixels with depth greater or smaller than 1 " << std::endl;
// Duplicate code below is to draw the sample points
gluLookAt( 4.0, 4.0, 15.0, 0.0,0.0,0.0,0.0,1.0,0.0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBegin(GL_POINTS);
for(vector<Vertex>::iterator vertex = lightPoints.begin(); vertex != lightPoints.end(); ++vertex){
glColor3f(0.0,1.0,0.0);
glVertex3f(vertex->x, vertex->y, vertex->z);
}
glEnd();
}
在我看来,场景是偏向一边的,尽管我不知道为什么。您还可以在不同的高度看到部分场景,如果这些都在同一高度,则我的图像是完整的(并且我有正确的结果)。
那么,是什么原因让它偏向一边并如此分散呢? (有件事告诉我这两件事可能有联系)。
编辑: 按照下面给出的建议,我开始尝试不同的像素存储选项: GL_PACK_ALIGNMENT似乎没有任何效果,我尝试了1,2,4和8。 GL_PACK_ROW_LENGTH 正确为 0,它采用 readpixels 中指定的宽度。 由于我不想跳过任何内容,因此“跳过”选项也应保持为零。
For an algorithm I'm writing I need to unproject my screen coordinates and reproject them into lightspace. This goes as follows: I fill the depth buffer viewing from my eye point (using glLookAt), I then unproject all visible pixels to world space. Then I reproject them into light space.
I was checking everything to make sure I made no mistakes (I have to do some other stuff after this), so I drew my newly projected pixels seeing from lightspace. To be sure I got the right result I made the presumption that my light was at the same spot as my eye.
Is the original scene. I then unproject and redraw them, i get this result:
void getObjectCoords(){
std::vector<GLfloat> z(800*600, 0);
std::vector< Vertex > lightPoints;
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLdouble posX, posY, posZ;
//Setting our original viewpoint for unprojecting
gluLookAt(4.0,4.0,15.0, 0.0,0.0,0.0,0.0,1.0,0.0);
//Getting Modelviewx, Projection and viewport matrix
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
//Reset the modelview
glLoadIdentity();
//Get the depth coordinate of the original points
glReadPixels( 0, 0,800, 600,GL_DEPTH_COMPONENT,GL_FLOAT, &z[0] );
//Unprojecting X and Y.
int count = 0;
Vertex temp;
for( int X = 0; X < 800; ++X){
for( int Y = 0; Y < 600; ++Y){
gluUnProject( X, Y, z[X*600 + Y], modelview, projection, viewport, &posX, &posY, &posZ);
if( z[X*600 + Y] < 1){
++count;
temp.x = posX;
temp.y = posY;
temp.z = posZ;
lightPoints.push_back(temp);
}
}
}
std::cout << count << " pixels closer to the viewpoint" << std::endl;
//Projecting the original points to lightspace
gluLookAt( 4.0, 4.0, 15.0, 0.0,0.0,0.0,0.0,1.0,0.0);
//We get the new modelview matrix
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
//We reset the modelview matrix
glLoadIdentity();
GLdouble winX, winY, winZ;
//Projecting the points into lightspace and saving the sample points
for(vector<Vertex>::iterator vertex = lightPoints.begin(); vertex != lightPoints.end(); ++vertex){
gluProject( vertex->x, vertex->y, vertex->z,modelview, projection, viewport, &winX, &winY, &winZ );
temp.x = winX;
temp.y = winY;
temp.z = winZ;
samplePoints.push_back(temp);
}
//std::cout << count << " pixels with depth greater or smaller than 1 " << std::endl;
// Duplicate code below is to draw the sample points
gluLookAt( 4.0, 4.0, 15.0, 0.0,0.0,0.0,0.0,1.0,0.0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBegin(GL_POINTS);
for(vector<Vertex>::iterator vertex = lightPoints.begin(); vertex != lightPoints.end(); ++vertex){
glColor3f(0.0,1.0,0.0);
glVertex3f(vertex->x, vertex->y, vertex->z);
}
glEnd();
}
It seems to me the scene is on its side, though I have no idea why. You can also see the scene partially at different heights, if these are all on the same height my image is complete (and I have the correct result).
So, what is the reason that it's on it's side and so spread out? (Something tells me these two things might be connected).
EDIT:
Following the suggestion given below I started experimenting with the different pixelstore options:
GL_PACK_ALIGNEMENT does not seem to be having any effect, I tried 1,2,4 and 8.
GL_PACK_ROW_LENGTH is correct at 0, it takes the width specified in readpixels.
Seeing that I don't want to skip anything, the SKIP options should remain zero aswell.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看来您没有正确设置像素存储参数(步幅、对齐方式等),尤其是 PACK 参数。看看 http://www.opengl.org/sdk/docs /man/xhtml/glPixelStore.xml 获取完整的选项集。在您的情况下,您希望
在调用 glReadPixels 之前
进行设置编辑/更新:
您的代码中还有另一个问题:您处理像素数组的方式。你写的
这是错误的。每行(在您的情况下)都是 800 像素宽,因此要前进一行,您必须偏移 800 个元素。因此,要在(宽度,高度)线性数组中寻址像素(x,y),您必须
在您的情况下编写或,
而不是硬编码800×600,您应该使用变量或命名常量;保持您的代码可维护。
This looks like you've not properly set your pixel store parameters (stride, alignment, the like), notably the PACK parameters. Have a look at http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml for the full set of options. In your case you want to set
right before calling glReadPixels
EDIT/Update:
There's another issue in your code: The way you address your pixel array. You wrote
This is wrong. Each row (in your case) is 800 pixels wide, so to advance one row you must offset by 800 elements. Thus to address pixel (x,y) in a linear array of (width, height) you must write
or in your case
Instead of hardcoding 800×600 you should use variables or named constants by the way; keeps your code maintainable.