openGL基础概念复习
程序员文章站
2022-07-04 11:10:29
...
重读LearnOpenGL CN,巩固下基础知识.
感谢Joey de Vries的LearnOpenGL,也感谢LearnOpenGL CN上各位大佬的翻译.
概念:
- OpenGL本身并不是一个API,仅仅是一个规范,由Khronos组织制定并维护。 实际的OpenGL库的开发者通常是显卡的生产商。
- 扩展(Extension): windows下opengl32.dll(opengl32.lib是导入库)中只包含openGL1.1以前的实现,新版本功能由显卡驱动实现,要想使用新版本功能,必须使用扩展机制,查找到相应的函数地址.
- 立即渲染模式 (Immediate mode): 固定管线;核心模式(Core-profile): 可编程管线.前者慢慢废弃,后者更加灵活高效.
- 状态机: OpenGL自身是一个巨大的状态机,OpenGL的状态通常被称为OpenGL上下文(Context)。我们通常使用如下途径去更改OpenGL 状态:设置一些选项,操作一些缓冲。最后,我们使用当前OpenGL上下文来渲染。
- 对象(Object): vbo是最常用的对象,但除了vbo还有很多对象,例如下面的例子:
// 创建对象
GLuint objectId = 0;
glGenObject(1, &objectId);
// 绑定对象至上下文
glBindObject(GL_WINDOW_TARGET, objectId);
// 设置GL_WINDOW_TARGET对象的一些选项
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH, 800);
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600);
// 将上下文的GL_WINDOW_TARGET对象设回默认
glBindObject(GL_WINDOW_TARGET, 0);
窗口系统:
最流行的几 个库有GLUT,SDL,SFML和GLFW。学习建议使用GLFW。
函数寻址:
openGL的函数及扩展中的函数,使用动态调用dll的方式使用,因此函数寻址比较麻烦,如下:
// 定义函数类型
typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
// 找到正确的函数并赋值给函数指针
GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
// 现在函数可以被正常调用了
GLuint buffer;
glGenBuffers(1, &buffer);
glew和glad都可以帮助方便的使用openGL及其扩展的函数,现在glad比较流行.
glad.h必须在glfw3.h前被包含.
一个最简单的框架,仅仅刷新背景颜色:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
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);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
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);
}