学习OpenGL建议从32位学起,因为64位有些细节可能需要特殊处理,因此初学者可以暂不考虑这些特殊情况,从简单开始入手,减少不必要的麻烦。
立即渲染模式(Immediate mode,也就是固定渲染管线),这个模式下绘制图形很方便。立即渲染模式确实容易使用和理解,但是效率太低,现在已经废弃。
核心模式迫使我们使用现代的函数,现代函数的优势是更高的灵活性和效率,然而也更难于学习。
OpenGL自身是一个巨大的状态机(State Machine):一系列的变量描述OpenGL此刻应当如何运行。OpenGL的状态通常被称为OpenGL上下文(Context)。我们通常使用如下途径去更改OpenGL状态:设置选项,操作缓冲。最后,我们使用当前OpenGL上下文来渲染。
OpenGL开发的时候引入了一些抽象层。“对象(Object)”就是其中一个。在OpenGL中一个对象是指一些选项的集合,它代表OpenGL状态的一个子集。在我们想绘制其中任何一个模型的时候,只需绑定一个包含对应模型数据的对象就可以了(当然,我们需要先创建并设置对象的选项)。
opengl库在vs2015的SDK中自带,不需要安装
glfw3的项目地址:https://www.glfw.org/download.html
该网址有现成的库文件,作为初学者,我建议自己编译。
怎么编译?答:使用CMake(不会的找几篇文章看看就会了,用不了10分钟肯定能学会)
(1)下载源码,并解压
(2)打开cmd,进入源码目录,执行:cmake .
(3)上一步执行成功后,会生成visual studio工程(具体是vs2015还是2017,cmake根据你的开发环境帮你自动配置),进入源码目录,打开FLFW.sln,如果学习的话,编译32位的Release版本就够了。
(4)把include和glfw3.lib(静态库)拷贝出来,备用。
这个最简单,直接配置就可以,配置地址:https://glad.dav1d.de/
只填一个gl版本就行(根据自己显卡确认,如果确定不了,就选3.3版本,其他新版本都是基于3.3扩展而来的,核心未变,可以兼容),最后点GENERATE,然后直接下载glad.zip,里面一个include一个glad.c,include加载到vs2015工程,glad.c直接作为源码加入你的opengl工程。
新建一个控制台空项目,控制台可以用printf或cout打印,便于自己调试。
先把glad.c加入到工程
把glfw3和glad的include添加到工程的附加目录
在依赖库里面新增2个新的:opengl32.lib和glfw3.lib
新建一个文件HelloWorld.cpp文件,copy下面源码进去编译,然后运行程序即可。代码来自opengl学习网站,我自己加了一点点注释。
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#define GL_PRINT(S) (printf("%s\n",#S),S)
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//将该窗口作为当前线程的主上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);//注册回调函数,这里是窗口大小改变时候调用framebuffer_size_callback,该函数还可以注册其他相关硬件的回调函数
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))//初始化glad库,只要用glad库都这么写,没什么可说的,glfwGetProcAddress这个函数返回指定的OpenGL或OpenGL ES核心或扩展函数的地址,如果它被当前上下文所支持的话。
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// render loop
// -----------
while (!glfwWindowShouldClose(window))//不阻塞,循环会一直执行
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);//交换缓冲区,这里用了双缓冲技术,用两个内存区域来保存数据,分为前缓冲区和后缓冲区,前缓冲区用于展示屏幕上的内容,而后缓冲区就用来绘制,然后每一帧开始的时候,将两个缓冲区交换,这样后缓冲区又可以画新的内容
glfwPollEvents();//轮询事件(如: 鼠标键盘事件)
}
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
GL_PRINT("Window Resize!");
}
原文:https://blog.51cto.com/14207158/2536415