標題:MFC使用OpenGL繪製面並打光
MFC (OpenGLglutLight.cpp):
#include <afxwin.h>
#include "OpenGLglut.h"
#include "glut.h"
class DocBoxy : public CDocument {
public:
CClientDC *m_pDC;
HGLRC hrc;
DECLARE_DYNCREATE(DocBoxy) //宣告run-time類別
};
IMPLEMENT_DYNCREATE(DocBoxy, CDocument) //宣告DocBoxy為run-time類別
class FrameBoxy : public CFrameWnd {
public:
afx_msg void OnExit() { //宣告關閉檔案事件
if(MessageBox( TEXT("Are you sure you want to close this window?"), TEXT("DocViewBoxy"), MB_OKCANCEL | MB_ICONQUESTION ) == 1 ) {
DestroyWindow();
}
}
afx_msg void OnAbout() { //宣告關於事件
MessageBox( TEXT("DocViewBoxy Version 1.0\nCopyright (C) 2013, By QQBoxy Huang.\nEmail: gs1458@gmail.com"), TEXT("About"), MB_OK );
}
DECLARE_DYNCREATE(FrameBoxy) //宣告run-time類別
DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
IMPLEMENT_DYNCREATE(FrameBoxy, CFrameWnd) //宣告FrameBoxy為run-time類別
BEGIN_MESSAGE_MAP(FrameBoxy, CFrameWnd) //建立訊息映射表
ON_COMMAND(ID_FILE_EXIT, OnExit)
ON_COMMAND(ID_HELP_ABOUT, OnAbout)
END_MESSAGE_MAP()
class ViewBoxy : public CView {
public:
void OnDraw(CDC * aDC) { //必須覆寫的虛擬函數
DocBoxy *doc = (DocBoxy *)GetDocument();
ASSERT_VALID(doc);
glLoadIdentity();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0.0f, 0.0f, -7.0f);
glRotatef(-35.0f, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
/*glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_LINES);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(20.0f, 0.0f, 0.0f);
glEnd();
*/
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_TRIANGLES);
glNormal3f(-0.8944272f, 0.4472136f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glNormal3f(0.8944272f, 0.4472136f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, 0.4472136f, -0.8944272f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, 0.4472136f, 0.8944272f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
//glutWireTeapot(5.0);
//glutSolidTeapot(5.0);
glEnd();
glFinish();
SwapBuffers( doc->m_pDC->GetSafeHdc() );
}
BOOL PreCreateWindow(CREATESTRUCT& cs) {
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
}
BOOL OnEraseBkgnd(CDC* pDC) {
return true;
}
void OnDestroy() {
DocBoxy *doc = (DocBoxy *)GetDocument();
HGLRC hRC;
hRC= wglGetCurrentContext();
wglMakeCurrent(NULL, NULL);
if (doc->hrc)
wglDeleteContext(hRC);
if (doc->m_pDC)
delete doc->m_pDC;
CView::OnDestroy();
}
bool bSetupPixelFormat() {
DocBoxy *doc = (DocBoxy *)GetDocument();
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pixelformat;
if( (pixelformat = ChoosePixelFormat(doc->m_pDC->GetSafeHdc(), &pfd)) == 0 ) {
MessageBox(_TEXT("ChoosePixelFormat failed"));
return false;
}
if(SetPixelFormat(doc->m_pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE) {
MessageBox(_TEXT("SetPixelFormat failed"));
return false;
}
return true;
}
void init() {
DocBoxy *doc = (DocBoxy *)GetDocument();
PIXELFORMATDESCRIPTOR pfd; //宣告一個PixelFormat物件
int n;
doc->m_pDC = new CClientDC(this); //建立一個視窗繪圖物件
ASSERT(doc->m_pDC != NULL);
if (!bSetupPixelFormat()) return; //設定應用所需的像素格式
n = GetPixelFormat(doc->m_pDC->GetSafeHdc()); //從Windows裡找尋符合我們設定的
DescribePixelFormat(doc->m_pDC->GetSafeHdc(), n, sizeof(pfd), &pfd); //PixelFormat的索引值,並將之指定給pfd
doc->hrc = wglCreateContext(doc->m_pDC->GetSafeHdc()); //將RC物件給DC物件
wglMakeCurrent(doc->m_pDC->GetSafeHdc(), doc->hrc); //讓這個RC設定為作用中的物件
glDepthFunc(GL_GREATER);
glEnable(GL_DEPTH_TEST);
glClearDepth(-2.0f);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
void setLight() {
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; //環境光強度
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; //光源漫射強度
GLfloat LightPosition[]= { 1.0f, 0.0f, 0.0f, 0.0f }; //表示在x方向無限遠
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);
glEnable(GL_LIGHT0); //使用光源0
glEnable(GL_LIGHTING); //打光
glEnable(GL_COLOR_MATERIAL); //啟用材質顏色
}
int OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
init();
setLight();
return 0;
}
void OnSize(UINT nType, int cx, int cy) {
CView::OnSize(nType, cx, cy);
GLfloat nRange=20.f;
if(cy == 0)
{ cy = 1; }
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (cx <= cy) {
glOrtho(-nRange, nRange, -nRange*cy/cx, nRange*cy/cx, -nRange, nRange);
} else {
glOrtho(-nRange*cx/cy, nRange*cx/cy, -nRange, nRange, -nRange, nRange);
}
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, cx, cy);
}
DECLARE_DYNCREATE(ViewBoxy) //宣告run-time類別
DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
IMPLEMENT_DYNCREATE(ViewBoxy, CView) //宣告ViewBoxy為run-time類別
BEGIN_MESSAGE_MAP(ViewBoxy, CView) //建立訊息映射表
ON_WM_DESTROY()
ON_WM_CREATE()
ON_WM_SIZE()
END_MESSAGE_MAP()
class AppBoxy : public CWinApp {
public:
BOOL InitInstance() {
CDocument *doc; //宣告指向文件的指標
CSingleDocTemplate* DocTemplate; //宣告指向單文件樣版物件的指標
DocTemplate = new CSingleDocTemplate( //建立具有單文件樣版物件
IDR_MENU, //用於單文件框架之資源的識別子
RUNTIME_CLASS(DocBoxy), //單文件視窗的Document
RUNTIME_CLASS(FrameBoxy), //單文件視窗的視窗框架
RUNTIME_CLASS(ViewBoxy) //單文件視窗的View
);
AddDocTemplate(DocTemplate); //將單文件樣版物件設定給MyApp
doc = DocTemplate->CreateNewDocument(); //建立新的文件
m_pMainWnd = DocTemplate->CreateNewFrame( doc, NULL ); //建立一個視窗框架
DocTemplate->InitialUpdateFrame ( (CFrameWnd*)m_pMainWnd, doc ); //起始化視窗框架物件,並連結View物件
m_pMainWnd->ShowWindow(SW_SHOW); //顯示視窗
return true;
}
};
AppBoxy appboxy; //建立應用程式物件
說明:
基礎MFC使用OpenGL繪製面並且打光。