废话
准备学习一下opengl
,现在成熟优秀的引擎一个接一个,在享受快速开发的同时,看看怎样造轮子也是挺好的。
之所以会选择opengl
是因为它是跨平台的3D图形底层库,现在什么东西不搭一点跨平台都不好意思说。于是编辑器界面我也选择了跨平台的wxwidgets
,除了wxwidgets
还有很多优秀的跨平台解决方案,比如Qt
Qt 是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。2008年,Qt Company科技被诺基亚公司收购,Qt也因此成为诺基亚旗下的编程语言工具。2012年,Qt被Digia收购。2014年4月,跨平台集成开发环境Qt Creator 3.1.0正式发布,实现了对于iOS的完全支持,新增WinRT、Beautifier等插件,废弃了无Python接口的GDB调试支持,集成了基于Clang的C/C++代码模块,并对Android支持做出了调整,至此实现了全面支持iOS、Android、WP,它提供给应用程序开发者建立艺术级的图形用户界面所需的所有功能。基本上,Qt 同 X Window 上的 Motif,Openwin,GTK 等图形界 面库和 Windows 平台上的 MFC,OWL,VCL,ATL 是同类型的东西。
然而我并没有选择Qt呢,原因嘛,我愿意选什么就选什么了
相关资料
wxwidgets:http://www.wxwidgets.org/
glew:https://sourceforge.net/projects/glew/files/
我大概用的就是这两个东西,关键字给得很明显的,剩下的就是查一下相关资料就可以了。
glfw:http://www.glfw.org/download.html
glad:http://glad.dav1d.de/
而这两个是另外一个解决方案了,glad是glew的最新代替的opengl的标准接口库,但是我并不知道怎么在wxwdigets中使用glad,所以还是暂时选择了glew
步骤
- 前面一些配置,已经窗口创建的步骤暂时略过…
- 新建一个类继承
wxGLCanvas
,并监听EVT_PAINT
和EVT_SIZE
事件,paint事件用来通知窗口绘制,size事件用来通知设置opengl的视窗大小
//绘制事件回调
void OnPaint(wxPaintEvent& event);
//事件绑定
BEGIN_EVENT_TABLE(OpenGLCanvas, wxGLCanvas)
EVT_PAINT(OpenGLCanvas::OnPaint)
EVT_SIZE(OpenGLCanvas::OnSize)
END_EVENT_TABLE()
- 然后在OnPaint函数中,准备绘制opengl的窗口,这里需要主要是使用glew的头文件时,需要放在
wx/glcanvas.h
之前
void OpenGLCanvas::OnPaint(wxPaintEvent& event)
{
//wxPaintDC dc(this);
//将当前窗口设置为opengl的渲染窗口
_glContext->SetCurrent(*this);
//初始化glew
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
//设置背景颜色
glClearColor(0.1f, 0.1f, 0.2f, 1.0);
//清空颜色缓冲
glClear(GL_COLOR_BUFFER_BIT);
//交换颜色缓冲,将其输出显示再屏幕上
SwapBuffers();
}
- 动态设置glViewport
void OpenGLCanvas::OnSize(wxSizeEvent& event)
{
wxSize size = event.GetSize();
glViewport(0, 0, size.x, size.y);
}
- 窗口截图
- 绘制三角形
新建一个函数DrawTriangle
,并在OnPaint
函数中,SwapBuffers();
交换颜色缓冲前调用,我已经尽量在代码用注释清楚功能,所以一次性粘贴完
void OpenGLCanvas::DrawTriangle()
{
//创建着色器对象
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
//将着色器源码附加到着色器对象上
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
//编译着色器
glCompileShader(vertexShader);
//检测shader是否编译成功
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
}
// 片段着色器 方法如上
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
}
// 完整的着色器对象
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
//链接着色器对象
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
}
//删除顶点与片段着色器
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//顶点数据
const float vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
//顶点缓冲对象,顶点数组对象
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
//针对不同的缓冲类型,绑定缓冲对象
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//将顶点数据复制到缓冲内存中
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//解析顶点数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
//以顶点属性位置值作为参数,启用顶点属性
glEnableVertexAttribArray(0);
//可以解除VBO的绑定
glBindBuffer(GL_ARRAY_BUFFER, 0);
//解除VAO
glBindVertexArray(0);
//使用当前激活的着色其
glUseProgram(shaderProgram);
//通过VAO绑定,之前的顶点数据以及属性
glBindVertexArray(VAO);
//绘制三角形 GL_TRIANGLES: 表明绘制三角形 0:顶点数组索引 3:顶点数
glDrawArrays(GL_TRIANGLES, 0, 3);
}
- 三角形截图
- 顶点vertex shader源码
const char* vertexShaderSource = "#version 330 core\n"
"layout(location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\n";
- 片段fragment shader源码
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0,0.85,0.23,1.0);\n"
"}\n";
- 绘制三角函数的关键词
- 顶点数组对象:Vertex Array Object,VAO
- 顶点缓冲对象:Vertex Buffer Object,VBO
- 索引缓冲对象:Element Buffer Object,EBO或Index Buffer Object,IBO