我正在使用OpenGL和GLUT构建一个简单的城市,我创建了一个纹理skydome,现在我想用平面连接它以呈现地平线的外观。为了给出相对大小,天幕是半径3.0,深度遮罩关闭,它只应用了摄像机旋转并坐在摄像机上。建筑物大小约为30.0,我从y = 500.0下来看它。
我有一个1000x1000的地平面,我使用1024x1024分辨率纹理进行纹理处理,当我靠近地面时看起来很近。我的纹理加载了纹理坐标为1000的GL_REPEAT,重复1000次。
将天幕与平坦的地平面连接是我遇到问题的地方。我将列出一些我尝试过的东西。
的问题:
1)当我旋转我的标题时,由于平面的方形性质,我看到的边缘就像附图而不是平坦的地平线。
2)我尝试了一个圆形地平面,但是我得到了一个曲线视野,当我飞起来时会变得更加弯曲。
3)为了避免无限天幕和我有限大小的平面之间的黑色差距,我设定了我可以飞多远的限制,并且当我上升时将天幕稍微向下移动,所以我不会&#39当我升高的时候,看到无限的天幕和我的平面之间的黑色间隙。是否还有其他方法可以将飞机褪色到天幕中,并在不同位置(即环绕一个正方形的圆圈)的间隙变化时处理间隙?我尝试应用地平线的雾色,但是我在白色地面上得到了紫色的阴霾。
4)如果我将地面作为天幕半球的底盖,那么当我放大和缩小时看起来很奇怪,看起来纹理地面滑动并与我的建筑物断开连接。
5)我试图通过设置w = 0来使用消失点概念绘制无限大的平面。 Rendering infinitely large plane 地平线确实看起来很平坦,但正确的纹理似乎很难,所以我坚持使用单一颜色。
6)如果我想为我的地平面启用照明,我会禁用天空照明,然后在某个俯仰角度,我的飞机看起来会变黑,但我的天空仍然完全亮起,看起来不自然。 / p> 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());
}
答案 0 :(得分:1)
尝试使用随机高度图,而不是使用平面。这不仅看起来更逼真,而且由于高度的变化,它将使地平面的边缘不可见。您还可以尝试添加一些顶点雾,以模糊天空盒和地平面相遇的区域。这大致就是我所做的here。
许多3D渲染都依赖于技巧来使事物看起来更逼真。如果你看一下大多数游戏,它们会有一大堆遮挡地平线的前景物体,或者它们在远处有一个“山脉”(高度图)也会遮挡地平线。
另一个想法是将地平面映射到球体上,使其像地球一样向下弯曲。这可能会使地平线看起来更像地球。这类似于您对圆形地平面所做的操作。