承接上文鳖孤,以下就讓我們來測試下配置的開發(fā)環(huán)境能否正常工作。
編寫代碼蜘渣,讓我們簡單的創(chuàng)建一個窗口先淌铐。
導(dǎo)入頭文件,注意 #pragma comment(lib,"glew32.lib")(經(jīng)測試蔫缸,這個glew庫文件在2015中必須顯式包含——代碼包含或者在附加依賴項中添加)
另外需要注意的是:glew.h需要先包含在前面腿准,然后才是freeglut.h
// stdafx.h : 標準系統(tǒng)包含文件的包含文件,
// 或是經(jīng)常使用但不常更改的
// 特定于項目的包含文件
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: 在此處引用程序需要的其他頭文件
#include <glew.h> // 注意glew.h在前面拾碌,然后才是freeglut.h
#include <freeglut.h>
#pragma comment(lib,"glew32.lib") // 你也可以在項目->屬性->鏈接器->輸入->附加依賴項中添加這個庫文件
#include <iostream>
using namespace std;
main函數(shù)代碼吐葱,創(chuàng)建一個窗口(注意未調(diào)用OpenGL的代碼,只是調(diào)用freeglut校翔、glew的代碼)弟跑。
// 第一個OpenGL程序.cpp : 定義控制臺應(yīng)用程序的入口點。
//
#include "stdafx.h"
void displayFunc();
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutCreateWindow("第一個OpenGL程序");
if (glewInit())
{
cerr << "Unable to initialize GLEW ... exiting" << endl;
exit(EXIT_FAILURE);
}
glutDisplayFunc(displayFunc);
glutMainLoop();
return 0;
}
void displayFunc()
{
}
運行結(jié)果:
使用《OpenGL開發(fā)指南 原書第8版》的第一章例子測試開發(fā)環(huán)境
讓我們重新創(chuàng)建一個工程,重新配置OpenGL開發(fā)環(huán)境之后蔫敲,再編寫一個較為復(fù)雜的程序——這個程序是OpenGL紅寶書的第一章的例子
不過這個例子還需要另外一些文件才行饲嗽,你需要在這里下載必需文件。
解壓下載的文件之后奈嘿,工程中和原先一樣配置glew貌虾、freeglut的包含目錄、庫目錄裙犹、顯式包含glew32.lib庫文件尽狠、exe同目錄下需要復(fù)制 .dl文件之外衔憨,還需要在包含目錄加入 ...\oglpg-8th-edition\include路徑,在庫目錄加入 ...\oglpg-8th-edition\bin路徑袄膏,工程中添加LoadShaders.cpp文件:
然后在工程中的解決方案上右鍵践图,添加現(xiàn)有項:
把 triangles.vert, triangles.frag文件復(fù)制到工程目錄下:
另外需要注意的是,如果運行窗口上的三角形是白色哩陕,并且控制臺輸出錯誤提示: 類似version: 450 字樣平项,這說明當前電腦的顯卡不支持這個版本的OpenGL;
這個只需查看你的電腦的顯卡支持的OpenGL版本悍及,然后把triangles.frag、triangles.vert文件中的版本修改為我們當前電腦的OpenGL版本即可(version: 450 是OpenGL最新版本4.5接癌,但當前大多數(shù)顯卡只支持到4.4心赶,即version 440):
假設(shè)你的顯卡支持的OpenGL版本是4.4缺猛,那么缨叫,修改值為440,如果顯卡支持的OpenGL版本是4.3荔燎,則修改為430耻姥,依次類推:
查看本機顯卡支持的OpenGL版本蘑秽,可以自行百度如何查看OpenGL版本,這個OpenGLExtension Viewer可以為你幫助箫攀。
輸入代碼
// stdafx.h : 標準系統(tǒng)包含文件的包含文件肠牲,
// 或是經(jīng)常使用但不常更改的
// 特定于項目的包含文件
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: 在此處引用程序需要的其他頭文件
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <vgl.h>
#include <LoadShaders.h>
#pragma comment(lib,"glew32.lib")
#include <iostream>
using namespace std;
```
```
// 1.2 初識OpenGL程序.cpp : 定義控制臺應(yīng)用程序的入口點。
//
#include "stdafx.h"
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, Numbuffer };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[Numbuffer];
const GLuint NumVertives = 6;
void init()
{
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertives[NumVertives][2] = {
{-0.90,-0.90},
{ 0.85,-0.90},
{-0.90, 0.85},
{ 0.90,-0.85},
{ 0.90, 0.90},
{-0.85, 0.90}
};
glGenBuffers(Numbuffer, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertives), vertives, GL_STATIC_DRAW);
ShaderInfo shaders[] = {
{GL_VERTEX_SHADER, "triangles.vert"},
{GL_FRAGMENT_SHADER, "triangles.frag"},
{GL_NONE, NULL}
};
GLuint program = LoadShaders(shaders);
glUseProgram(program);
glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vPosition);
}
void displayFunc();
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(512, 512);
glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow(argv[0]);
if (glewInit())
{
cerr << "Unable to initialize GLEW ... exiting" << endl;
exit(EXIT_FAILURE);
}
init();
glutDisplayFunc(displayFunc);
glutMainLoop();
return 0;
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertives);
glFlush();
}
```
**注意: 如果提示“無法打開freeglutd.lib”匠童,則在VC++目錄中的庫目錄需要包含freeglut的Debug下的lib文件斩跌;如果提示“無法打開freeglut.lib”朴摊,則在VC++目錄中的庫目錄需要包含Release下的lib.文件**
####運行結(jié)果
![測試結(jié)果:glew、freeglut吠式、OpenGL都可以正常使用](http://upload-images.jianshu.io/upload_images/1490569-a66c20502c0b68f3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#永久配置OpenGL開發(fā)環(huán)境
折騰了半天,我們知道了一個OpenGL程序的運行奴曙,需要使用到glew、freeglut的所有.h、對應(yīng)版本的 .lib裤唠、.dll文件,只要把這些文件一次性配置好莹痢,一個OpenGL程序需要的環(huán)境就基本配置完畢种蘸。
隨便打開一個VS工程,點擊項目->屬性->VC++目錄竞膳,查看包含目錄或庫目錄發(fā)現(xiàn)航瞭,VS本身配置有默認值:
![VS包含目錄中設(shè)置的默認值](http://upload-images.jianshu.io/upload_images/1490569-8e468d81e0f917cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
這些默認值在不同電腦、不同版本的系統(tǒng)中對應(yīng)的路徑是不同的坦辟,找到這些路徑就成了我們永久配置OpenGL環(huán)境的關(guān)鍵——**只要把glew刊侯、freeglut必需的 .h文件、.lib文件復(fù)制到VS默認的包含目錄和庫目錄中即可**锉走。
這樣復(fù)制之后滨彻,**以后再創(chuàng)建任何OpenGL程序時,就不需要在配置包含目錄和庫目錄了挪蹭,只需要在exe同目錄下復(fù)制相應(yīng)的 .dll 文件**即可亭饵。
這種辦法不止適用與OpenGL的配置,任何庫的配置都可以這樣配置梁厉,就算是其他編譯器辜羊,如XCode,也可以這樣配置懂算,參照的原理是一樣只冻。
**但有一點要格外注意,在操作VS默認的目錄時计技,要格外小心喜德,不然麻煩只會更多;一旦操作不當垮媒,很可能就是給自己挖一個隱藏的大坑舍悯。**
####好了,那么以下睡雇,我們就小心翼翼的在VS默認目錄中嘗試配置下glew萌衬、freeglut
之前我們已經(jīng)知道我們需要的文件其實只有兩類:.h文件、.lib文件 —— 顯然它抱,.h文件要拷貝到VS的包含目錄中秕豫、.lib文件則要拷貝到庫目錄中。
剩下的問題就是找到VS默認目錄,那么我們現(xiàn)在再次新建一個C++控制臺工程混移。
找VS默認目錄的方法上面也介紹了祠墅,我們先來看看包含目錄(**注意你此時的電腦很大很大的可能和下圖顯示內(nèi)容不同,這是正常的歌径,不必驚慌毁嗦。繼續(xù)向下閱讀...**):
![計算的值和繼承的值](http://upload-images.jianshu.io/upload_images/1490569-1a22ec28677f66bf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
即使我們不知道微軟把計算的值和繼承的值定義為何種含義,我們也能猜出來:計算的值表示這臺電腦的VS將默認目錄的實際文件路徑——可以復(fù)制這個路徑回铛,直接可以直達它指示的位置狗准;而繼承的值,從名稱上看茵肃,顯然意思是表示兩類路徑:VC的路徑腔长、windowSDK的路徑。
好了验残,還記得OpenGL的頭文件所在位置嘛饼酿? 好吧,我也忘記了胚膊,我們重新找出來。
輸入#include <gl\GL.h>想鹰、右鍵打開文檔紊婉、再右鍵打開所在的文件夾:
```
#include <gl\GL.h>
```
... 具體步驟常見[上文開頭部分](http://www.reibang.com/p/68c314fa9fea)...
![操作結(jié)果](http://upload-images.jianshu.io/upload_images/1490569-ee2c532a024a4d7f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![對比結(jié)果](http://upload-images.jianshu.io/upload_images/1490569-cf612fd8aeb45f60.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
顯而易見,我們找到我們想要的東西了辑舷,我覺得OpenGL相關(guān)的內(nèi)容喻犁,就讓我們永久配置在上圖那個默認的文件夾中吧,這樣好找也容易歸類何缓。
####OpenGL的 .h文件 永久配置
筆者在這個gl文件夾下創(chuàng)建了 glew 2.0.0肢础、freeglut 3.0.0文件夾,并拷貝相關(guān).h文件到里面碌廓,讀者可以隨意命名传轰,位置隨意(如果你真的明白這么做的意義):
![gl文件夾下創(chuàng)建glew 2.0.0文件夾,并拷貝相應(yīng).h文件進來谷婆。](http://upload-images.jianshu.io/upload_images/1490569-8b96c2a2be70575b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![gl文件夾下創(chuàng)建freeglut 3.0.0文件夾慨蛙,并拷貝相應(yīng).h文件進來。](http://upload-images.jianshu.io/upload_images/1490569-7f76d297237ce01c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**好了纪挎,OpenGL的包含目錄永久配置完成期贫。**
####OpenGL的 lib 文件永久配置
庫目錄也類似,找到VS默認庫目錄异袄,選擇一個合適的位置通砍,然后拷貝文件進入。但是VS的默認庫目錄路徑卻只有32位的烤蜕,沒有表示64位的默認庫目錄封孙,
![VS默認庫目錄樣式](http://upload-images.jianshu.io/upload_images/1490569-7fd5168da5db70d9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
我們該如何抉擇迹冤?是在這個目錄下拷貝64位的進去還是32位的呢?看起來貌似哪個都行的通敛瓷。
其實主要看你創(chuàng)建的應(yīng)用程序是32位還是64位叁巨,進一步理解[可以在這里可以獲得幫助](http://blog.csdn.net/github_27886083/article/details/45456809):
簡單而言,此時:
![創(chuàng)建的是32位應(yīng)用程序還是64位應(yīng)用程序](http://upload-images.jianshu.io/upload_images/1490569-a68aff50f5acdd2d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
若你創(chuàng)建的是32位應(yīng)用程序則拷貝32位 .lib文件即可呐籽;反之锋勺,創(chuàng)建的是64位應(yīng)用程序,則拷貝64位 .lib文件即可狡蝶。
那么我們的現(xiàn)在創(chuàng)建的是32位應(yīng)用程序庶橱,則選擇32的.lib文件拷貝進去:
![打開VS的一個默認庫目錄文件夾,拷貝glew的32位 .lib 文件進入即可](http://upload-images.jianshu.io/upload_images/1490569-98941b3633931610.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
至于拷貝freeglut的 .lib 文件之前贪惹,你確認用CMake編譯好了的VS2015工程環(huán)境是否是32位的苏章,確認后那么干脆再F6編譯下,然后再拷貝文件到上圖路徑中:
![筆者在32位&Release下奏瞬,再次編譯工程枫绅。](http://upload-images.jianshu.io/upload_images/1490569-a5cfa12a649d518b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如圖拷貝freeglut的.lib文件到VS默認的32位庫目錄中,**建議讀者在Release和Debug模式下分別編譯依次硼端,然后拷貝里面的 .lib文件并淋。**
![拷貝了6個.lib文件](http://upload-images.jianshu.io/upload_images/1490569-6aa5657be284897d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**OpenGL的庫目錄永久配置完畢**
好,此時珍昨,就可以拷貝 動態(tài)鏈接庫到exe同目錄下县耽,然后編寫OpenGL代碼了,
下面就是簡單的復(fù)制镣典、粘貼兔毙,只有在引入頭文件時有一些變化:
```
// stdafx.h : 標準系統(tǒng)包含文件的包含文件,
// 或是經(jīng)常使用但不常更改的
// 特定于項目的包含文件
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: 在此處引用程序需要的其他頭文件
#include <gl\glew 2.0.0\glew.h>
#pragma comment(lib,"glew32.lib")
#include <gl\freeglut 3.0.0\freeglut.h>
#include <iostream>
using namespace std;
```
```
// ConsoleApplication1.cpp : 定義控制臺應(yīng)用程序的入口點兄春。
//
#include "stdafx.h"
void displayFunc();
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutCreateWindow("第一個OpenGL程序");
if (glewInit())
{
cerr << "Unable to initialize GLEW ... exiting" << endl;
exit(EXIT_FAILURE);
}
glutDisplayFunc(displayFunc);
glutMainLoop();
return 0;
}
void displayFunc()
{
}
```
![運行結(jié)果:正常](http://upload-images.jianshu.io/upload_images/1490569-101db2ef80a77b8d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
####OpenGL dll文件永久配置
如果這些dll文件你也不想每次都拷貝澎剥,想要像OpenGL相關(guān)頭文件、庫文件一樣永久配置它們神郊,那么你可以依照以下的操作肴裙,把dll文件永久配置到系統(tǒng)中。
關(guān)于dll 拷貝到系統(tǒng)目錄時需要考慮的細節(jié)涌乳,[在這里可以給你更詳細的幫助](http://tieba.baidu.com/p/3337331207)蜻懦,簡單而言,就是要注意你本機系統(tǒng)是那種類型的(32位夕晓?64位宛乃?):
![將dll文件拷貝到系統(tǒng)目錄中](http://upload-images.jianshu.io/upload_images/1490569-931f8dd7dfda3843.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
glew、freeglut都有32位和64位的dll文件,我們依次拷貝即可(**freeglut需要分別在Win32征炼、Win64的工程中析既,才能編譯生成期望的文件**):
筆者是64位系統(tǒng),所以稍微復(fù)雜點谆奥,如下圖(freeglut需要Win64環(huán)境眼坏,進行編譯后,才能生成64位的dll酸些,[請閱讀上文介紹CMake Configure 選擇VS編譯器時選擇Win64...](http://www.reibang.com/p/68c314fa9fea)):
![拷貝32位dll到SysWOW64文件夾中](http://upload-images.jianshu.io/upload_images/1490569-a8dcb3b988d75742.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![拷貝64位dll到System32文件夾中](http://upload-images.jianshu.io/upload_images/1490569-862c89ee3161d953.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**OpenGL 所需的dll文件永久配置完畢**
刪除原來在工程exe同目錄下的所有dll文件宰译,運行工程:
![刪除原來在工程exe同目錄下的所有dll文件](http://upload-images.jianshu.io/upload_images/1490569-9d4557a27bd05cd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![運行正常](http://upload-images.jianshu.io/upload_images/1490569-5db3e05d999f49e2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**在處理系統(tǒng)目錄時,請務(wù)必不要亂動文件魄懂,當遇到不知道有什么作用的文件時沿侈,就什么也不要做**
#解決常見錯誤
> - **無法打開文件“xxx.lib”**
**如:無法打開文件“freeglutd.lib” —— 這種錯誤原因是編譯器需要使用 該lib文件時,卻在相應(yīng)的目錄(VC++目錄中庫目錄的添加的所有路徑)中找不到市栗;此時缀拭,可以添加手動缺少庫文件(添加庫文件路徑或拷貝庫文件到VS一個默認庫目錄中);如果依然提示該錯誤填帽,可是再添加代碼(如 `#pragma comment(lib,"glew32.lib")`)加載該lib蛛淋;當提示無法打開“freeglutd.lib”時,[除了手動添加相應(yīng)庫文件(添加庫文件路徑或拷貝庫文件到VS一個默認庫目錄中)之外篡腌,你也可以在 項目->屬性->C/C++ ->預(yù)處理器->預(yù)處理器定義->編輯中輸入NDEBUG即可](http://blog.csdn.net/yapingxin/article/details/46440307)铣鹏。**
![無法打開文件“freeglut.lib” 或者 無法打開文件“freeglutd.lib“ 或者 無法打開文件“glew32.lib”](http://upload-images.jianshu.io/upload_images/1490569-b33aebadd57e117f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- **無法解析外部符號_imp_glewInit@0
該錯誤的原因是,程序要中使用了一個名稱哀蘑,但沒有鏈接到該名稱的實現(xiàn)部分,就好像是你聲明了一個函數(shù)葵第,卻忘記實現(xiàn)這個函數(shù)了绘迁,這時就會出現(xiàn)這種錯誤;而如果無法解析的外部符號中有g(shù)l卒密、glew缀台、glut字樣時,表示相應(yīng)的OpenGL實現(xiàn)哮奇、glew實現(xiàn)膛腐、glut實現(xiàn)不存在,其中一個可能原因是相應(yīng)的 .lib 文件沒有加載到鼎俘,例如沒有加載到glew32.lib文件哲身,而程序中又調(diào)用了某glew系列函數(shù),這時贸伐,系統(tǒng)就會報無法解析外部符號的錯誤勘天。
![無法解析外部符號: glew字樣的符號 或者 無法解析外部符號: glut字樣的符號、無法解析外部符號: gl字樣的符號](http://upload-images.jianshu.io/upload_images/1490569-474f70f8a0338789.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
解決辦法同上(和無法打開文件“xxx.lib”解決方法一樣,把相應(yīng)庫配置好脯丝,VS能找到相應(yīng)函數(shù)實現(xiàn)就行了商膊。)。**
- **無法啟動應(yīng)用程序**
這種錯誤原因是應(yīng)用程序運行需要 某某某.dll 動態(tài)鏈接庫宠进,而系統(tǒng)沒有找到該 dll文件晕拆。
![無法啟動此程序,因為計算機丟失 freeglut.dll (或者丟失freeglutd.dll 或者 丟失 glew32.dll)材蹬,建議重新安裝該程序...](http://upload-images.jianshu.io/upload_images/1490569-c68b6a85ba8f1401.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
解決辦法是拷貝該dll文件到exe同目錄下即可实幕,[或者將dll拷貝到系統(tǒng)相應(yīng)的文件夾內(nèi)](http://tieba.baidu.com/p/3337331207)。