MAC OS下使用Xcode進行GLSL編程的配置過程

整理自以前使用的163博客原創文章。php

GLSL項目中須要使用GLEW庫,所以先要安裝GLEW庫和在Xcode中配置GLEW。要使GLEW在Xcode中被正確連接,又須要經過MacPorts來安裝GLEW。下文以MacPorts-->GLEW-->GLSL的順序來闡述。
環境:系統 OS X 10.9.2 (13C64),工具 Xcode 5.1,圖形卡 Intel Iris 1024 MB

1 MacPorts安裝

MacPorts是與apt-get和yum相似的軟件管理包,下載與系統對應的 安裝包後進行安裝(安裝過程當中會聯網進行更新,致使安裝過程好久,建議斷網安裝)。安裝以後打開終端運行
$ sudo port -v selfupdate
進行更新。若是更新時在以下狀態下卡的時間好久,
--->  Updating the ports tree
Synchronizing local ports tree from rsync://rsync.macports.org/release/tarballs/ports.tar
receiving file list ... done
ports.tar

使用control+z終止更新,終端輸入html

$ sudo vim /opt/local/etc/macports/sources.conf

打開配置文件,更改最後一行的默認下載地址(參考「解決安裝macports,不能更新的問題」,參考下載網址列表),如可修改成韓國鏡像:ios

#rsync://rsync.macports.org/release/tarballs/ports.tar [default]
#http://www.macports.org/files/ports.tar.gz [default]
rsync://cjj.kr.rsync.macports.org/macports/release/tarballs/ports.tar

改好後wq保存退出,再次運行macos

$ sudo port -v selfupdate

進行更新,更新成功後會顯示以下信息:vim

--->  MacPorts base is already the latest version
The ports tree has been updated. To upgrade your installed ports, you should run  port upgrade outdated

安裝過程當中遇到其它問題請戳:數組

Mac OS X Lion安裝MacPorts(讓你在Mac的Shell下更加遊刃有餘)xcode

Mac中MacPorts安裝和使用app

Mac OS X中MacPorts安裝和使用ide

2 GLEW庫安裝

glew庫主要有以下三種安裝方式:1)在Xcode中直接導入framework(下載地址);2)編譯glew源代碼進行安裝(參考「Installing GLEW in Mac OS X (Leopard));3)經過MacPorts進行安裝。函數

實測了三種方式,都可成功安裝glew庫,但前兩種方式在Xcode中連接不成功,本文經過MacPorts進行安裝(參考「GLEW: Apple Mach-O Linker (Id) Error」)。

終端輸入

$ sudo port install glew

進行安裝,安裝成功後顯示:

--->  Installing glew @1.10.0_0
--->  Activating glew @1.10.0_0
--->  Cleaning glew
--->  Updating database of binaries: 100.0%
--->  Scanning binaries for linking errors: 100.0%
--->  No broken files found.

安裝過程當中遇到其它問題請戳

cannot link glew under xcode4, macosx lion

3 Xcode中GLSL的配置

Mac系統中已內置openGL、GLUT和GLSL,無需安裝。

啓動Xcode,新建Cocoa Application工程,刪除「TriangleAppDelegate.*」文件、「*main.m」文件和「MainMenu.xib」文件。右鍵單擊"Supporting Files"添加新文件,選擇"C++ File"。添加後,刪除對應的頭文件。右鍵單擊"Frameworks",添加"OpenGL.framework"和"GLUT.framework"(參考「MAC OS X And Win7 vs2010 搭建OpenGL」,參考「在Xcode中使用GLUT開發OpenGL應用程序」)。

下面是添加對GLEW庫的連接,在build setting中添加以下參數便可:

other linker flags: -lGLEW
header search paths: /opt/local/include/
library search paths: /opt/local/lib/

4 Hello World

在supporting files下添加basic.vert:

1 void main(){
2     gl_Position = ftransform();
3 }

在supporting files下添加basic.frag:

1 void main() {
2     gl_FragColor = vec4(0.4,0.4,0.8,1.0);
3 }

在supporting files下添加textfile.h:

 1 #ifndef macGL_textfile_h
 2 #define macGL_textfile_h
 3 
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 #include <string.h>
 7 
 8 char *textFileRead(const char *fn);
 9 int textFileWrite(char *fn, char *s);
10 unsigned char *readDataFromFile(char *fn);
11 #endif

 在supporting files下添加textfile.cpp:

 1 #include "textfile.h"
 2 
 3 unsigned char * readDataFromFile(char *fn){
 4     FILE *fp;
 5     unsigned char *content = NULL;
 6     int count=0;
 7 
 8     if (fn != NULL) {
 9         fp = fopen(fn,"rb");
10         if (fp != NULL) {
11             fseek(fp, 0, SEEK_END);
12             count = ftell(fp);
13             rewind(fp);
14             if (count > 0) {
15                 content = (unsigned char *)malloc(sizeof(unsigned char) * (count+1));
16                 count = fread(content,sizeof(unsigned char),count,fp);
17                 content[count] = '\0';
18             }
19             fclose(fp);
20         }
21     }
22 
23     return content;
24 }
25 
26 
27 char *textFileRead(const char *fn) {
28     FILE *fp;
29     char *content = NULL;
30     int count=0;
31 
32     if (fn != NULL) {
33             fp = fopen(fn,"rt");
34             if (fp != NULL) {
35                 fseek(fp, 0, SEEK_END);
36                 count = ftell(fp);
37                 rewind(fp);
38                 if (count > 0) {
39                     content = (char *)malloc(sizeof(char) * (count+1));
40                     count = fread(content,sizeof(char),count,fp);
41                     content[count] = '\0';
42                 }
43                 fclose(fp);
44             }
45         }
46     return content;
47 }
48 
49 
50 int textFileWrite(char *fn, char *s) {
51     FILE *fp;
52     int status  = 0;
53     if (fn != NULL){
54         fp = fopen(fn,"w");
55         if (fp != NULL) {
56             if (fwrite(s,sizeof(char),strlen(s),fp) == strlen(s))
57                 status = 1;
58             fclose(fp);
59         }
60     }
61     return(status);
62 }
View Code

在supporting files下添加GLSLTest.cpp。其中display函數中的glutWireTeapot()是glut內置的畫茶壺的函數。注意MAC下特有的glBindVertexArrayAPPLE,glBindVertexArrayAPPLE,glGenVertexArraysAPPLE:

  1 //#pragma comment(lib,"libGLEW.a")
  2 
  3 #include <GL/glew.h>
  4 
  5 #include "textfile.h"
  6 
  7 #include <glut/glut.h>
  8 #include <iostream>
  9 using namespace std;
 10 
 11 GLuint vShader,fShader;//頂點着色器對象
 12 
 13 //頂點位置數組
 14 float positionData[] = {
 15     -0.8f, -0.8f, 0.0f,
 16     0.8f, -0.8f, 0.0f,
 17     0.0f,  0.8f, 0.0f };
 18 //顏色數組
 19 float colorData[] = {
 20     1.0f, 0.0f, 0.0f,
 21     0.0f, 1.0f, 0.0f,
 22     0.0f, 0.0f, 1.0f };
 23 
 24 GLuint vaoHandle;//vertex array object
 25 
 26 void initShader(const char *VShaderFile,const char *FShaderFile)
 27 {
 28     //一、查看GLSL和OpenGL的版本
 29     const GLubyte *renderer = glGetString( GL_RENDERER );
 30     const GLubyte *vendor = glGetString( GL_VENDOR );
 31     const GLubyte *version = glGetString( GL_VERSION );
 32     const GLubyte *glslVersion =
 33     glGetString( GL_SHADING_LANGUAGE_VERSION );
 34     GLint major, minor;
 35     glGetIntegerv(GL_MAJOR_VERSION, &major);
 36     glGetIntegerv(GL_MINOR_VERSION, &minor);
 37     cout << "GL Vendor    :" << vendor << endl;
 38     cout << "GL Renderer  : " << renderer << endl;
 39     cout << "GL Version (string)  : " << version << endl;
 40     cout << "GL Version (integer) : " << major << "." << minor << endl;
 41     cout << "GLSL Version : " << glslVersion << endl;
 42     
 43     //二、編譯着色器
 44     //建立着色器對象:頂點着色器
 45     vShader = glCreateShader(GL_VERTEX_SHADER);
 46     //錯誤檢測
 47     if (0 == vShader)
 48     {
 49         cerr << "ERROR : Create vertex shader failed" << endl;
 50         exit(1);
 51     }
 52     
 53     //把着色器源代碼和着色器對象相關聯
 54     const GLchar *vShaderCode = textFileRead(VShaderFile);
 55     const GLchar *vCodeArray[1] = {vShaderCode};
 56     glShaderSource(vShader,1,vCodeArray,NULL);
 57     
 58     //編譯着色器對象
 59     glCompileShader(vShader);
 60     
 61     
 62     //檢查編譯是否成功
 63     GLint compileResult;
 64     glGetShaderiv(vShader,GL_COMPILE_STATUS,&compileResult);
 65     if (GL_FALSE == compileResult)
 66     {
 67         GLint logLen;
 68         //獲得編譯日誌長度
 69         glGetShaderiv(vShader,GL_INFO_LOG_LENGTH,&logLen);
 70         if (logLen > 0)
 71         {
 72             char *log = (char *)malloc(logLen);
 73             GLsizei written;
 74             //獲得日誌信息並輸出
 75             glGetShaderInfoLog(vShader,logLen,&written,log);
 76             cerr << "vertex shader compile log : " << endl;
 77             cerr << log << endl;
 78             free(log);//釋放空間
 79         }
 80     }
 81     
 82     //建立着色器對象:片段着色器
 83     fShader = glCreateShader(GL_FRAGMENT_SHADER);
 84     //錯誤檢測
 85     if (0 == fShader)
 86     {
 87         cerr << "ERROR : Create fragment shader failed" << endl;
 88         exit(1);
 89     }
 90     
 91     //把着色器源代碼和着色器對象相關聯
 92     const GLchar *fShaderCode = textFileRead(FShaderFile);
 93     const GLchar *fCodeArray[1] = {fShaderCode};
 94     glShaderSource(fShader,1,fCodeArray,NULL);
 95     
 96     //編譯着色器對象
 97     glCompileShader(fShader);
 98     
 99     //檢查編譯是否成功
100     glGetShaderiv(fShader,GL_COMPILE_STATUS,&compileResult);
101     if (GL_FALSE == compileResult)
102     {
103         GLint logLen;
104         //獲得編譯日誌長度
105         glGetShaderiv(fShader,GL_INFO_LOG_LENGTH,&logLen);
106         if (logLen > 0)
107         {
108             char *log = (char *)malloc(logLen);
109             GLsizei written;
110             //獲得日誌信息並輸出
111             glGetShaderInfoLog(fShader,logLen,&written,log);
112             cerr << "fragment shader compile log : " << endl;
113             cerr << log << endl;
114             free(log);//釋放空間
115         }
116     }
117     
118     //三、連接着色器對象
119     //建立着色器程序
120     GLuint programHandle = glCreateProgram();
121     if (!programHandle)
122     {
123         cerr << "ERROR : create program failed" << endl;
124         exit(1);
125     }
126     //將着色器程序連接到所建立的程序中
127     glAttachShader(programHandle,vShader);
128     glAttachShader(programHandle,fShader);
129     //將這些對象連接成一個可執行程序
130     glLinkProgram(programHandle);
131     //查詢連接的結果
132     GLint linkStatus;
133     glGetProgramiv(programHandle,GL_LINK_STATUS,&linkStatus);
134     if (GL_FALSE == linkStatus)
135     {
136         cerr << "ERROR : link shader program failed" << endl;
137         GLint logLen;
138         glGetProgramiv(programHandle,GL_INFO_LOG_LENGTH,
139                        &logLen);
140         if (logLen > 0)
141         {
142             char *log = (char *)malloc(logLen);
143             GLsizei written;
144             glGetProgramInfoLog(programHandle,logLen,
145                                 &written,log);
146             cerr << "Program log : " << endl;
147             cerr << log << endl;
148         }
149     }
150     else//連接成功,在OpenGL管線中使用渲染程序
151     {
152         glUseProgram(programHandle);
153     }
154 }
155 
156 void initVBO()
157 {
158     // Create and populate the buffer objects
159     GLuint vboHandles[2];
160     glGenBuffers(2, vboHandles);
161     GLuint positionBufferHandle = vboHandles[0];
162     GLuint colorBufferHandle = vboHandles[1];
163     
164     //綁定VBO以供使用
165     glBindBuffer(GL_ARRAY_BUFFER,positionBufferHandle);
166     //加載數據到VBO
167     glBufferData(GL_ARRAY_BUFFER,9 * sizeof(float),
168                  positionData,GL_STATIC_DRAW);
169     
170     //綁定VBO以供使用
171     glBindBuffer(GL_ARRAY_BUFFER,colorBufferHandle);
172     //加載數據到VBO
173     glBufferData(GL_ARRAY_BUFFER,9 * sizeof(float),
174                  colorData,GL_STATIC_DRAW);
175     
176     glGenVertexArraysAPPLE(1,&vaoHandle);
177     glBindVertexArrayAPPLE(vaoHandle);
178     
179     glEnableVertexAttribArray(0);//頂點座標
180     glEnableVertexAttribArray(1);//頂點顏色
181     
182     //調用glVertexAttribPointer以前須要進行綁定操做
183     glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
184     glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
185     
186     glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
187     glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
188 }
189 
190 void init()
191 {
192     //初始化glew擴展庫
193     GLenum err = glewInit();
194     if( GLEW_OK != err )
195     {
196         cout <<"Error initializing GLEW: " << glewGetErrorString(err) << endl;
197     }
198     
199     initShader("basic.vert","basic.frag");
200     
201     initVBO();
202     
203     glClearColor(0.0,0.0,0.0,0.0);
204     //glShadeModel(GL_SMOOTH);
205     
206 }
207 
208 void display()
209 {
210     glClear(GL_COLOR_BUFFER_BIT);
211     
212     ////繪製一個三角形(使用普通方法)
213     //glBegin(GL_TRIANGLES);
214     //glColor3f(0.0f,1.0f,0.0f);
215     //glVertex3f(0.0f,1.0f,0.0f);
216     
217     //glColor3f(0.0f,1.0f,0.0f);
218     //glVertex3f(-1.0f,-1.0f,0.0f);
219     
220     //glColor3f(0.0f,0.0f,1.0f);
221     //glVertex3f(1.0f,-1.0f,0.0f);
222     //glEnd();
223     
224     //使用VAO、VBO繪製
225     glBindVertexArrayAPPLE(vaoHandle);
226     //glDrawArrays(GL_TRIANGLES,0,3);
227     glutWireTeapot(0.5);
228     GLint tiz = glGetUniformLocation(vaoHandle, "iz");
229     glUniform1iARB(tiz, 20);
230     glBindVertexArrayAPPLE(0);
231     glutWireTeapot(1.0);
232     
233     glutSwapBuffers();
234 }
235 
236 void keyboard(unsigned char key,int x,int y)
237 {
238     switch(key)
239     {
240         case 27:
241             glDeleteShader(vShader);
242             glUseProgram(0);
243             break;
244     }
245 }
246 
247 int main(int argc,char** argv)
248 {
249     glutInit(&argc,argv);
250     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
251     glutInitWindowSize(600,600);
252     glutInitWindowPosition(100,100);
253     glutCreateWindow("GLSL Test : Draw a triangle");
254     init();
255     glutDisplayFunc(display);
256     glutKeyboardFunc(keyboard);
257     
258     glutMainLoop();
259     return 0;
260 }
View Code

運行成功後的效果圖:

其它參考網址:

【GLSL教程】(四)shder的簡單示例

GLSL Tutorial

How to link glew in xcode

【GLSL教程】(二)在OpenGL中使用GLSL

GLSL.Refract & Reflect & Diffraction

相關文章
相關標籤/搜索