【1】新建一个MFC窗口程序
【2】安装:nupengl.core(安装方法详见上一篇文章)
lib和dll,以及.h文件如下图
【3】添加头文件和库的包含目录
【4】添加opengl,头文件和lib库
#include "GL/glew.h"
#pragma comment(lib, "glew32.lib")
【5】添加功能函数和变量
#pragma once
#include "GL/glew.h"
#include "GL/glut.h"
#pragma comment(lib, "glew32.lib")
class WOpenGLInterface
{
public:
void InitShaderAndBuffer();
void Display();//绘制图形
void Reflesh();//刷新控件
//protected:
HDC m_hdc;//设备上下文
HGLRC m_hglrc;//opengl上下文
bool SetupPixelFormat(HDC hdc);//设置像素格式
void* m_pDlg; //要绘制内容的窗口
};
【6】添加顶点着色程序、片段着色程序,加载着色器并创建顶点缓存
#include "WOpenGLInterfaceDlg.h"
//顶点着色程序 字符串
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
//片段着色程序 字符串
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
GLuint shaderProgram; //着色器
GLuint VAO;//顶点缓冲
void TestOpenGL::InitShaderAndBuffer()//加载shader并创建顶点缓冲
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);//绑定着色器程序
glCompileShader(vertexShader);//编译
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);//创建片元着色器
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);///绑定着色器程序
glCompileShader(fragmentShader);//编译
shaderProgram = glCreateProgram();//创建着色器程序
//四边系三个顶点
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
GLuint indices[] = { // Note that we start from 0!
0, 1, 3, // First Triangle 第一个三角形索引
1, 2, 3 // Second Triangle 第二个三角形索引
};
GLuint VBO, EBO;
glGenVertexArrays(1, &VAO);//创建顶点缓冲
glGenBuffers(1, &VBO);//创建bufer
glGenBuffers(1, &EBO);//创建buffer
glBindVertexArray(VAO);//绑定
}
【7】其他函数实现
void WOpenGLInterface::Display()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//背景颜色
glUseProgram(shaderProgram);//使用着色器
glBindVertexArray(VAO);//绑定顶点缓冲
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//绘制命令
glBindVertexArray(0);//解绑
}
void WOpenGLInterface::Reflesh()
{
WOpenGLInterfaceDlg* dlg = (WOpenGLInterfaceDlg*)m_pDlg;
dlg->Invalidate(false);//使控件无效
dlg->UpdateWindow();//更新控件
}
bool WOpenGLInterface::SetupPixelFormat(HDC hdc)
{
PIXELFORMATDESCRIPTOR pfd = //像素格式
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | //绘制到窗口
PFD_SUPPORT_OPENGL |//支持opengl
PFD_DOUBLEBUFFER,//采用双缓冲
PFD_TYPE_RGBA,//像素类型 RGBA
24,//像素位数 4*8- 32
0, 0, 0, 0, 0, 0,//
0,
0,
0,
0, 0, 0, 0,
16,//深度缓冲区位数
0,//模板缓冲
0,
PFD_MAIN_PLANE,//
0,
0, 0, 0
};
int pixelformat;
if (0 == (pixelformat = ChoosePixelFormat(hdc, &pfd)))//匹配像素格式的索引
{
return FALSE;
}
if (FALSE == ::SetPixelFormat(hdc, pixelformat, &pfd))//设置像素格式
{
return FALSE;
}
return TRUE;
}
【8】新建一个类,继承自CWnd和WOpenGLInterface,类向导中添加WM_CREATE、WM_SIZE、WM_PAINT的消息处理
#pragma once
#include <afxwin.h>
#include "WOpenGLInterface.h"
class WOpenGLInterfaceDlg : public CWnd, WOpenGLInterface
{
public:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnTimer(UINT_PTR nIDEvent);
};
#include "pch.h"
#include "WOpenGLInterfaceDlg.h"
BEGIN_MESSAGE_MAP(WOpenGLInterfaceDlg, CWnd)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_TIMER()
END_MESSAGE_MAP()
void WOpenGLInterfaceDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CWnd::OnPaint()
wglMakeCurrent(m_hdc, m_hglrc);//hglrcopengl设备上下文--》绑定-->hdc当前设备上下文
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);//背景颜色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除颜色缓冲以及深度缓冲
Display();//绘制函数,在这个函数中绘制自己的图形
glFinish();//绘制结束
SwapBuffers(m_hdc);//交换前后缓冲区
wglMakeCurrent(m_hdc, NULL);//释放设备上下文
}
int WOpenGLInterfaceDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
m_hdc = ::GetDC(m_hWnd);//hdc设备上下文,m_hWnd窗口句柄
SetupPixelFormat(m_hdc);//设置像素格式
//CPaintDC dc(this);
m_hglrc = wglCreateContext(m_hdc);//hglrc :opengl设备上下文
wglMakeCurrent(m_hdc, m_hglrc);//hglrc绑定hdc; 绘制到当前设备上下文
glClearDepth(1.0f);//1.0是最大深度([0.0,1.0])
glEnable(GL_DEPTH_TEST);//启动深度检测
InitShaderAndBuffer();//加载shader并创建顶点缓冲
return 0;
}
void WOpenGLInterfaceDlg::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
GLdouble aspect_ratio;//窗口长宽比
if (0 >= cx || 0 >= cy)//窗口长、宽必须大于0
return;
glViewport(0, 0, cx, cy);//根据窗口的实时变化重绘窗口
}
void WOpenGLInterfaceDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
__super::OnTimer(nIDEvent);
}
【9】在主窗口OnInitDialog中添加如下代码:m_pOpenGLWndObject为WOpenGLInterfaceDlg*
CRect rect = CRect(10, 10, 620, 430);
m_pOpenGLWndObject->Create(NULL, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE, rect, this, 0);