# 第一課: 新建一個窗口
## 簡介
歡迎來到第一課!
在學習OpenGL之前,我們將先學習如何生成,運行,和玩轉(最重要的一點)課程中的代碼。
## 預備知識
不需要特別的預備知識。如果你有C、Java、Lisp、Javascript等編程語言的經驗,那么理解課程代碼會更快;但這不是必需的;如果沒有,那么也僅僅是同時學兩樣東西(編程語言+OpenGL)會稍微復雜點而已。
課程全部用“傻瓜式C++”編寫:我費了很大勁盡量讓代碼簡單些。代碼里沒有模板(template)、類或指針。就是說,即使只懂Java,也能理解所有內容。
## 忘記一切
如前面所說,我們不需要預備知識;但請暫時把『老式OpenGL』先忘了吧(例如glBegin()這類東西)。在這里,你將學習新式OpenGL(OpenGL 3和4),而多數網上教程還在講『老式OpenGL』(OpenGL 1和2)。所以,在你的腦袋亂成一鍋粥之前,把它們都擱在一邊吧。
## 生成課程中的代碼
所有課程代碼都能在Windows、Linux、和Mac上生成,而且過程大體相同:
- 更新驅動 !!趕快更新吧。我可是提醒過你喲。
- 下載C++編譯器。
- 安裝CMake
- 下載全部課程代碼
- 用CMake創建工程
- 編譯工程
- 試試這些例子!
各平臺的詳細代碼生成過程將會在后面一一給出,不過具體每個平臺可能會有差異。如果你不確定,可以去看看Windows平臺的生成說明,然后按照需改動一下來適應你自己的平臺。
### 在Windows平臺上生成課程代碼
1.
更新驅動應該很輕松。直接去NVIDIA或者AMD的官網下載。若不清楚GPU的型號:控制面板->系統和安全->系統->設備管理器->顯示適配器。如果是Intel集成顯卡,一般由電腦廠商(Dell、HP等)提供驅動。
1.
建議用Visual Studio 2010 Express來編譯。 這里可以免費下載。 若喜歡用MinGW,推薦[Qt Creator](http://qt-project.org/)。安裝哪個都行。下列步驟是用Visual Studio講解的,其他IDE也差不多。
1.
從這里下載安裝 [CMake](http://www.cmake.org/cmake/resources/software.html) 。
1.
[下載課程源碼](http://www.opengl-tutorial.org/?page_id=200) ,解壓到例如C:/Users/XYZ/Projects/OpenGLTutorials .
1.
啟動CMake。讓第一欄路徑指向剛才解壓縮的文件夾;若不確定,就選包含CMakeLists.txt的文件夾。第二欄,填CMake輸出路徑 (譯者注:這里CMake輸出一個可以在Visual Studio中打開和編譯的工程)。例如C:/Users/XYZ/Projects/OpenGLTutorials-build-Visual2010-32bits,或者C:/Users/XYZ/Projects/OpenGLTutorials/build/Visual2010-32bits。注意,此處可隨便填,不一定要和源碼在同一文件夾。

1.
點擊Configure。由于是首次configure工程,CMake會讓你選擇編譯器。根據步驟1選擇。如果你的Windows是64位的,選64位。不清楚就選32位。\
1.
再點Configure直至紅色行全部消失。點Generate。Visual Studio工程創建完畢。Visual Studio工程創建完畢。不再需要CMake了,可以卸載掉。
1.
打開 C:/Users/XYZ/Projects/OpenGL/Tutorials-build-Visual2010-32bits會看到Tutorials.sln文件(譯者注:這就是CMake生成的VS項目文件),用Visual Studio打開它。

在 Build 菜單中,點Build All。每個課程代碼和依賴項都會被編譯。生成的可執行文件會出現在 C:/Users/XYZ/Projects/OpenGLTutorials。但愿不會報錯。

1. 打開C:/Users/XYZ/Projects/OpenGLTutorials/playground,運行playground.exe,會彈出一個黑色窗口。

也可以在Visual Studio中運行任意一課的代碼,但得先設置工作目錄:右鍵點擊Playground,選擇Debugging、Working Directory、Browse,設置路徑為C:/Users/XYZ/Projects/OpenGLTutorials/playground。驗證一下。再次右鍵點擊Playground,“Choose as startup project”。按F5就可以調試了。


## 在Linux上生成
Linux版本眾多,這里不可能列出所有的平臺。按需變通一下吧,也不妨看一下發行版文檔。
1.
安裝最新驅動。強烈推薦閉源的二進制驅動;它們不開源,但好用。如果發行版不提供自動安裝,試試[Ubuntu指南](http://help.ubuntu.com/community/BinaryDriverHowto).
1.
安裝全部需要的編譯器、工具和庫。完整清單如下:cmake make g++ libx11-dev libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxext-dev 。 用 sudo apt-get install ***** 或者 su && yum install ******。
1.
[下載課程源碼](http://www.opengl-tutorial.org/?page_id=200) 并解壓到如 ~/Projects/OpenGLTutorials/
1.
接著輸入如下命令 :
~~~
cd ~/Projects/OpenGLTutorials/
mkdir build
cd build
cmake ..
~~~
1.
build/目錄會創建一個makefile文件。
1.
鍵入“make all”。每個課程代碼和依賴項都會被編譯。生成的可執行文件在~/Projects/OpenGLTutorials/。但愿不會報錯。
1.
打開~/Projects/OpenGLTutorials/playground,運行./playground會彈出一個黑色窗口。
提示:推薦使用[Qt Creator](http://qt-project.org/)作為IDE。值得一提的是,Qt Creator內置支持CMake,調試起來也順手。如下是QtCreator使用說明:
1.在QtCreator中打開Tools->Options->Compile-&Execute->CMake
2.設置CMake路徑。很可能像這樣/usr/bin/cmake
3.File->Open Project;選擇 tutorials/CMakeLists.txt
4.選擇生成目錄,最好選擇tutorials文件夾外面
5.還可以在參數欄中設置-DCMAKE_BUILD_TYPE=Debug。驗證一下。
6.點擊下面的錘子圖標。現在教程可以從tutorials/文件夾啟動了。
7.要想在QtCreator中運行教程源碼,點擊Projects->Execution parameters->Working Directory,選擇著色器、紋理和模型所在目錄。以第二課為例:~/opengl-tutorial/tutorial02_red_triangle/
## 在Mac上生成
Mac OS不支持OpenGL 3.3。最近,搭載MacOS 10.7 Lion和兼容型GPU的Mac電腦可以跑OpenGL 3.2了,但3.3還不行;所以我們用2.1移植版的課程代碼。除此外,其他步驟和Windows類似(也支持Makefiles,此處不贅述):
1.從Mac App Store安裝XCode
2.下載[CMake](http://www.cmake.org/cmake/resources/software.html),安裝.dmg。無需安裝命令行工具。
3.下載[課程源碼](http://www.opengl-tutorial.org/?page_id=200) (2.1版!!)解壓到如~/Projects/OpenGLTutorials/ .
4.啟動CMake (Applications->CMake)。讓第一欄路徑指向剛才解壓縮的文件夾,不確定就選包含CMakeLists.txt的文件夾。第二欄,填CMake輸出路徑。例如~/Projects/OpenGLTutorials_bin_XCode/。注意,這里可以隨便填,不一定要和源碼在同一文件夾。
5.點擊Configure。由于是首次configure工程,CMake會讓你選擇編譯器。選擇Xcode。
6.再點Configure直至紅色行全部消失。點Generate。Xcode項目創建完畢。不再需要CMake了,可以卸載掉。
7.打開~/Projects/OpenGLTutorials_bin_XCode/會看到Tutorials.xcodeproj文件:打開它。
8.選擇一個教程,在Xcode的Scheme面板上運行,點擊Run按鈕編譯和運行:

**在第二課及后續課程中,Run按鈕就失效了。下一版本會解決這個bug。目前,請用Cmd-B鍵運行(雙擊源碼文件夾/tutorialX/tutorialX,或者通過終端)。**
## 關于Code::Blocks的說明
由于C::B和CMake中各有一個bug,你得在Project->Build->Options->Make commands中手動設置編譯命令,如下圖所示:

同時你還得手動設置工作目錄:Project->Properties->Build targets->tutorial N->execution working dir(即src_dir/tutorial_N/)。
## 運行課程例子
一定要在正確的目錄下運行課程例子:你可以雙擊可執行文件;如果愛用命令行,請用cd命令切換到正確的目錄。
若想從IDE中運行程序,別忘了看看上面的說明——先正確設置工作目錄。
## 如何學習本課程
每課都附有源碼和數據,可在tutorialXX/找到。不過,建議您不改動這些工程,將它們作為參考;推薦在playground/playground.cpp中做試驗,怎么折騰都行。要是弄亂了,就去粘一段課程代碼,一切就會恢復正常。
我們會在整個教程中提供代碼片段。不妨在看教程時,直接把它們復制到playground里跑跑看。動手實驗才是王道。單純看別人寫好的代碼學不了多少。即使僅僅粘貼一下代碼,也會碰到不少問題。
## 新建一個窗口
終于!寫OpenGL代碼的時刻來了!
呃,其實還早著呢。有的教程都會教你以“底層”的方式做事,好讓你清楚每一步的原理。但這往往很無聊也無用。所以,我們用一個外部的庫——GLFW來幫我們處理窗口、鍵盤消息等細節。你也可以使用Windows的Win32 API、Linux的X11 API,或Mac的Cocoa API;或者用別的庫,比如SFML、FreeGLUT、SDL等,請參見鏈接頁。
我們開始吧。從處理依賴庫開始:我們要用一些基本庫,在控制臺顯示消息:
~~~
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
~~~
然后是GLEW庫。這東西的原理,我們以后再說。
~~~
// Include GLEW. Always include it before gl.h and glfw.h, since it's a bit magic.
#include <GL/glew.h>
~~~
我們使用GLFW庫處理窗口和鍵盤消息,把它也包含進來:
~~~
// Include GLFW
#include <GL/glfw.h>
~~~
下面的GLM是個很有用的三維數學庫,我們暫時沒用到,但很快就會用上。GLM庫很好用,但沒有什么神奇的,你自己也可以寫一個。添加“using namespace”是為了不用寫“glm::vec3”,直接寫“vec3”。
~~~
// Include GLM
#include <glm/glm.hpp>
using namespace glm;
~~~
如果把這些#include都粘貼到playground.cpp,編譯器會報錯,說缺少main函數。所以我們創建一個 :
~~~
int main(){
~~~
首先初始化GLFW :
~~~
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
return -1;
}
~~~
可以創建我們的第一個OpenGL窗口啦!
~~~
glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4); // 4x antialiasing
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); // We want OpenGL 3.3
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
// Open a window and create its OpenGL context
if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ) )
{
fprintf( stderr, "Failed to open GLFW window\n" );
glfwTerminate();
return -1;
}
// Initialize GLEW
glewExperimental=true; // Needed in core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
glfwSetWindowTitle( "Tutorial 01" );
~~~
編譯并運行。一個窗口彈出后立即關閉了。可不是嘛!還沒設置等待用戶Esc按鍵再關閉呢:
~~~
// Ensure we can capture the escape key being pressed below
glfwEnable( GLFW_STICKY_KEYS );
do{
// Draw nothing, see you in tutorial 2 !
// Swap buffers
glfwSwapBuffers();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
glfwGetWindowParam( GLFW_OPENED ) );
~~~
第一課就到這啦!第二課會教大家畫三角形。