补充:基本框架添加成员变量初始化代码
COpenglbaseView::COpenglbaseView()
{
// TODO: add construction code here
m_hRC=NULL;
m_pDC=NULL;
}
关闭纹理映射
否则不能显示三维图元。因为这里我们没有用到纹理,所以把初始化中的启用纹理映射函数注释掉
BOOL COpenglbaseView::InitializeOpenGL(CDC *pDC)
{
m_pDC=pDC;
if(!SetupPixelFormat())
return FALSE;
m_hRC=::wglCreateContext(m_pDC->GetSafeHdc());//产生一个新的opengl绘图描述表使之适合在参数hdc给出的设备上画图
::wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC);
// SetLight();//设置光照环境
// LoadGLTextures();//设置绘图环境
// glEnable(GL_TEXTURE_2D);//启用纹理映射
return TRUE;
}
----------------------------------------------------------------------------------
在②中只是讲了怎样制作二维图形,其默认为正视投影
将OnSize函数
void COpenglbaseView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
//添加窗口缩放时的图形变换函数
glViewport(0,0,cx,cy);
}
修改为
void COpenglbaseView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
//添加窗口缩放时的图形变换函数
//添加窗口缩放时的变换函数
GLsizei width, height;
GLdouble aspect;
width = cx;
height = cy;
if (cy==0)
aspect = (GLdouble)width;
else
aspect = (GLdouble)width/(GLdouble)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0*aspect, 0.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
如果你缩放窗口,图形也会跟着缩放。这是因为 OnSize通过 glViewport(0, 0, width, height)定义了视口和视口坐标。 glViewport的第一、二个参数是视口左下角的像素坐标,第三、四个参数是视口的宽度和高度。
OnSize中的glMatrixMode是用来设置矩阵模式的,它有三个选项:GL_MODELVIEW、GL_PROJECTION、GL_TEXTURE。
GL_MODELVIEW表示从实体坐标系转到人眼坐标系。
GL_PROJECTION表示从人眼坐标系转到剪裁坐标系。
GL_TEXTURE表示从定义纹理的坐标系到粘贴纹理的坐标系的变换。
glLoadIdentity初始化工程矩阵(project matrix);
gluOrtho2D把工程矩阵设置成显示一个二维直角显示区域。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
生成三维图形
三维和二维的坐标系统不同,三维的图形比二维的图形多一个z坐标。我们在生成简单的二维图形时,用的是gluOrtho2D;我们在生成三维图形时,需要两个远近裁剪平面,以生成透视效果。实际上,二维图形只是视线的近裁剪平面z= -1,远裁剪平面z=1;这样z坐标始终当作0,两者没有本质的差别。
在上述基础之上,我们只做简单的变化,就可以生成三维物体。
1、三维透视坐标设置
在 OnSize()中,把 gluOrtho2D(0.0, 500.0*aspect,0.0, 500.0)换成
gluPerspective(45, aspect, 0.1f, 100.0f);
这样就实现了三维透视坐标系的设置。该语句说明了视点在原点,透视角是45度,近裁剪面在z=0.1处,远裁剪面在z=100.0f处。在离相机0.1-100单位距离内的物体是可以成像的。这里的近远裁剪面的距离都是相对相机的距离,所以都是正值。
透视投影为例,
2、设置观察点(相机在世界坐标系中的位置)
gluLookAt(0,0,-1,0,0,0,0,1,0);
RenderScene();//渲染场景
void COpenglbaseView::OnDraw(CDC* pDC)
{
COpenglbaseDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
static BOOL bBusy = FALSE;
if (bBusy)
{
return;
}
bBusy=TRUE; //双缓存应用
//
gluLookAt(0,0,-1,0,0,0,0,1,0);
RenderScene();//渲染场景
//
glFlush();
glFinish();//完成绘制
SwapBuffers(m_pDC->GetSafeHdc());//双缓存应用
bBusy=FALSE;
}
BOOL COpenglbaseView::RenderScene()
{
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//
//三维测试
glBegin(GL_POLYGON);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-2.0f, -2.0f, 5.0f);
glVertex3f( 2.0f, -2.0f, 5.0f);
glVertex3f( 2.0f, 2.0f,5.0f);
glVertex3f(-2.0f, 2.0f,5.0f);
glEnd();
//
return TRUE;
}
显示结果如下,在正中央有一正方形
但是有一个问题是正方形不停地闪烁,这是因为我们框架里有一个Timer定时器定时刷新,为了消除闪烁
Delete删除OnTimer函数
在View的OnCreate函数中注释掉
// SetTimer(1,20,NULL);
在OnDestroy中注释掉
// KillTimer(1);
----------------------------------------------------------------------------------------------------------------------------------
验证gluLookAt函数
将人眼位置向x轴正方向即右移动100个单位,视线方向不变,此时屏幕内显示为黑屏,将图元的x坐标加100,又如上图所示。
可见,gluLookAt只是改变人眼(摄像机)的位置,绘制图元时还是以世界坐标系为参考系。
void COpenglbaseView::OnDraw(CDC* pDC)
{
COpenglbaseDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
static BOOL bBusy = FALSE;
if (bBusy)
{
return;
}
bBusy=TRUE; //双缓存应用
//
gluLookAt(100,0,-1,100,0,0,0,1,0);
RenderScene();//渲染场景
//
glFlush();
glFinish();//完成绘制
SwapBuffers(wglGetCurrentDC());//双缓存应用
bBusy=FALSE;
}
BOOL COpenglbaseView::RenderScene()
{
glClearColor(0.0f,0.0f,0.0f,0.0f);//背景为红色
glClearDepth(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//三维测试
glBegin(GL_POLYGON);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-2.0f+100.f, -2.0f, 5.0f);
glVertex3f( 2.0f+100.f, -2.0f, 5.0f);
glVertex3f( 2.0f+100.f, 2.0f,5.0f);
glVertex3f(-2.0f+100.f, 2.0f,5.0f);
glEnd();
return TRUE;
}