1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-22 20:25:28 +08:00

Update 01-03

This commit is contained in:
Meow J
2017-06-16 22:09:56 +08:00
parent 6ee7a87860
commit afe2ca1998
4 changed files with 147 additions and 63 deletions

View File

@@ -32,4 +32,71 @@ GLEW是OpenGL Extension Wrangler Library的缩写它能解决我们上面提
对于用GCC编译的Linux用户建议使用这个命令行选项`-lGLEW -lglfw3 -lGL -lX11 -lpthread -lXrandr -lXi`。没有正确链接相应的库会产生 *undefined reference*(未定义的引用) 这个错误。
我们现在成功编译了GLFW和GLEW库我们已经准备好将进入[下一节](03 Hello Window.md)去真正使用GLFW和GLEW来设置OpenGL上下文并创建窗口。记得确保你的头文件和库文件的目录设置正确以及链接器里引用的库文件名正确。如果仍然遇到错误可以先看一下评论有没有人遇到类似的问题请参考额外资源中的例子或者在下面的评论区提问。
我们现在成功编译了GLFW和GLEW库我们已经准备好将进入[下一节](01 Getting started/03 Hello Window.md)去真正使用GLFW和GLEW来设置OpenGL上下文并创建窗口。记得确保你的头文件和库文件的目录设置正确以及链接器里引用的库文件名正确。如果仍然遇到错误可以先看一下评论有没有人遇到类似的问题请参考额外资源中的例子或者在下面的评论区提问。
## 01-03 你好,窗口
### GLEW
在之前的教程中已经提到过GLEW是用来管理OpenGL的函数指针的所以在调用任何OpenGL的函数之前我们需要初始化GLEW。
```c++
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
```
请注意我们在初始化GLEW之前设置<var>glewExperimental</var>变量的值为`GL_TRUE`这样做能让GLEW在管理OpenGL的函数指针时更多地使用现代化的技术如果把它设置为`GL_FALSE`的话可能会在使用OpenGL的核心模式时出现一些问题。
### 视口(Viewport)
在我们开始渲染之前还有一件重要的事情要做我们必须告诉OpenGL渲染窗口的尺寸大小这样OpenGL才只能知道怎样相对于窗口大小显示数据和坐标。我们可以通过调用<fun>glViewport</fun>函数来设置窗口的**维度**(Dimension)
```c++
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
```
<fun>glViewport</fun>函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度像素这里我们是直接从GLFW中获取的。我们从GLFW中获取视口的维度而不设置为800*600是为了让它在高DPI的屏幕上比如说Apple的视网膜显示屏也能[正常工作](http://www.glfw.org/docs/latest/window.html#window_size)。
我们实际上也可以将视口的维度设置为比GLFW的维度小这样子之后所有的OpenGL渲染将会在一个更小的窗口中显示这样子的话我们也可以将一些其它元素显示在OpenGL视口之外。
!!! Important
OpenGL幕后使用<fun>glViewport</fun>中定义的位置和宽高进行2D坐标的转换将OpenGL中的位置坐标转换为你的屏幕坐标。例如OpenGL中的坐标(-0.5, 0.5)有可能(最终)被映射为屏幕中的坐标(200,450)。注意处理过的OpenGL坐标范围只为-1到1因此我们事实上将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。
### 输入
我们同样也希望能够在GLFW中实现一些键盘控制这可以通过使用GLFW的回调函数(Callback Function)来完成。<def>回调函数</def>事实上是一个函数指针当我们设置好后GLFW会在合适的时候调用它。**按键回调**(KeyCallback)是众多回调函数中的一种。当我们设置了按键回调之后GLFW会在用户有键盘交互时调用它。该回调函数的原型如下所示
```c++
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
```
按键回调函数接受一个<fun>GLFWwindow</fun>指针作为它的第一个参数;第二个整形参数用来表示按下的按键;`action`参数表示这个按键是被按下还是释放最后一个整形参数表示是否有Ctrl、Shift、Alt、Super等按钮的操作。GLFW会在合适的时候调用它并为各个参数传入适当的值。
```c++
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
// 当用户按下ESC键,我们设置window窗口的WindowShouldClose属性为true
// 关闭应用程序
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
```
在我们(新创建的)<fun>key_callback</fun>函数中我们检测了键盘是否按下了Escape键。如果键的确按下了(不释放),我们使用<fun>glfwSetwindowShouldClose</fun>函数设定`WindowShouldClose`属性为`true`从而关闭GLFW。main函数的`while`循环下一次的检测将为失败,程序就关闭了。
最后一件事就是通过GLFW注册我们的函数至合适的回调代码是这样的:
```c++
glfwSetKeyCallback(window, key_callback);
```
除了按键回调函数之外,我们还能我们自己的函数注册其它的回调。例如,我们可以注册一个回调函数来处理窗口尺寸变化、处理一些错误信息等。我们可以在创建窗口之后,开始游戏循环之前注册各种回调函数。