【发布时间】:2014-03-31 16:14:56
【问题描述】:
我正在使用 OpenGL 和 GLUT 构建一个简单的城市,我创建了一个带纹理的天穹,现在我想将它与一个平面连接起来以呈现地平线的外观。为了给出相对大小,天穹的半径为 3.0,深度遮罩关闭,它只应用了相机旋转并位于相机上方。一座建筑物的大小约为 30.0,我从 y=500.0 向下看。
我有一个 1000x1000 的地平面,我正在使用 1024x1024 分辨率的纹理进行纹理处理,当我靠在地面上时,近距离看起来不错。我的纹理加载了纹理坐标为 1000 的 GL_REPEAT 以重复 1000 次。
将天穹与平坦的地平面连接起来是我遇到的一些问题。我将列出我尝试过的一些事情。
问题:
1) 当我旋转我的航向时,由于飞机的方形特性,我看到的边缘就像所附图片一样,而不是平坦的地平线。
2) 我尝试了一个圆形地平面,但我得到了一个曲线地平线,当我飞起来时变得更加弯曲。
3)为了避免无限天穹和我有限尺寸的平面之间的黑色间隙,我限制了我可以飞多远,并在我上升时稍微向下移动天穹,所以我不当我在高处时,看到无限天穹和我的平面之间的黑色间隙。当间隙在不同位置的大小变化时(即圆形外接正方形),是否有其他方法可以将飞机淡入天穹并处理间隙?我尝试应用地平线的雾色,但在白色的地面上出现了紫色的雾气。
4) 如果我将地面作为天穹半球的底盖,那么当我放大和缩小时看起来很奇怪,看起来带纹理的地面正在滑动并与我的建筑物断开连接。
5) 我试图通过设置 w=0 来使用消失点概念绘制无限大的平面。 Rendering infinitely large plane 地平线看起来确实很平坦,但正确地纹理化似乎很困难,所以我被单一颜色困住了。
6) 我正在禁用天穹的照明,如果我想为我的地平面启用照明,那么在某个俯仰角,我的飞机会看起来是黑色的,但我的天空仍然是完全亮的,而且看起来不自然。
7) 如果我把我的飞机变大,比如 10000x10000,那么地平线看起来会很平坦,但是,如果我按箭头键调整我的航向,地平线会在稳定之前摇晃几秒钟,什么是导致它,我该如何防止它。与此相关的一个问题,似乎平铺和纹理 1000x1000 地平面和 10000x10000 不会影响我的帧速率,这是为什么呢?更多的平铺不是意味着更多的工作吗?
8)我阅读了一些基于数学的方法来计算剪切矩形来绘制地平线,但我想知道是否有更简单的方法http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-super-simple-method-for-creating-infinite-sce-r2769
我读到的关于地平线的大多数帖子都会说,使用天空盒,使用天空穹顶,但我还没有遇到过关于将天空穹顶与大型地平面很好地合并的具体教程。指向这样一个教程的指针会很棒。随意通过指出数字来回答问题的任何部分,我不想分解它们,因为它们都是相关的。谢谢。
这是我设置的一些相关代码:
void Display()
{
// Clear frame buffer and depth buffer
glClearColor (0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camera.Update();
GLfloat accumulated_camera_rotation_matrix[16];
GetAccumulatedRotationMatrix(accumulated_camera_rotation_matrix);
SkyDome_Draw(accumulated_camera_rotation_matrix);
FlatGroundPlane_Draw();
// draw buildings
// swap buffers when GLUT_DOUBLE double buffering is enabled
glutSwapBuffers();
}
void SkyDome_Draw(GLfloat (&accumulated_camera_rotation_matrix)[16])
{
glPushMatrix();
glLoadIdentity();
glDepthMask(GL_FALSE);
glDisable(GL_LIGHTING);
glMultMatrixf(accumulated_camera_rotation_matrix);
// 3.0f is the radius of the skydome
// If we offset by 0.5f in camera.ground_plane_y_offset, we can offset by another 1.5f
// at skydome_sky_celing_y_offset of 500. 500 is our max allowable altitude
glTranslatef( 0, -camera.ground_plane_y_offset - camera.GetCameraPosition().y /c amera.skydome_sky_celing_y_offset/1.5f, 0);
skyDome->Draw();
glEnable(GL_LIGHTING);
glDepthMask(GL_TRUE);
glEnable(GL_CULL_FACE);
glPopMatrix();
}
void GetAccumulatedRotationMatrix(GLfloat (&accumulated_rotation_matrix)[16])
{
glGetFloatv(GL_MODELVIEW_MATRIX, accumulated_rotation_matrix);
// zero out translation is in elements m12, m13, m14
accumulated_rotation_matrix[12] = 0;
accumulated_rotation_matrix[13] = 0;
accumulated_rotation_matrix[14] = 0;
}
GLfloat GROUND_PLANE_WIDTH = 1000.0f;
void FlatGroundPlane_Draw(void)
{
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, concreteTextureId);
glBegin(GL_QUADS);
glNormal3f(0, 1, 0);
glTexCoord2d(0, 0);
// repeat 1000 times for a plane 1000 times in width
GLfloat textCoord = GROUND_PLANE_WIDTH;
glVertex3f( -GROUND_PLANE_WIDTH, 0, -GROUND_PLANE_WIDTH);
// go beyond 1 for texture coordinate so it repeats
glTexCoord2d(0, textCoord);
glVertex3f( -GROUND_PLANE_WIDTH, 0, GROUND_PLANE_WIDTH);
glTexCoord2d(textCoord, textCoord);
glVertex3f( GROUND_PLANE_WIDTH, 0, GROUND_PLANE_WIDTH);
glTexCoord2d(textCoord, 0);
glVertex3f( GROUND_PLANE_WIDTH, 0, -GROUND_PLANE_WIDTH);
glEnd();
glDisable(GL_TEXTURE_2D);
}
Void Init()
{
concreteTextureId = modelParser->LoadTiledTextureFromFile(concreteTexturePath);
}
ModelParser::LoadTiledTextureFromFile(string texturePath)
{
RGBImage image; // wrapping 2-d array of data
image.LoadData(texturePath);
GLuint texture_id;
UploadTiledTexture(texture_id, image);
image.ReleaseData();
return texture_id;
}
void ModelParser::UploadTiledTexture(unsigned int &iTexture, const RGBImage &img)
{
glGenTextures(1, &iTexture); // create the texture
glBindTexture(GL_TEXTURE_2D, iTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// the texture would wrap over at the edges (repeat)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, img.Width(), img.Height(), GL_RGB, GL_UNSIGNED_BYTE, img.Data());
}
【问题讨论】:
-
关于 [2],随着高度的增加,地平线会变得越来越弯曲,这也是现实生活中发生的事情。所以也许这还不错。
-
@MattFichman,谢谢马特,是的,它看起来并不算太糟糕,除非可能在相对于圆圈大小更高的高度,然后它变得非常弯曲。但高度可能会受到限制。