websyhg 发表于 2015-12-30 07:45:46

MAC OS下使用Xcode进行GLSL编程的配置过程

  整理自之前使用的163博客原创文章。


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终止更新,终端输入



$ sudo vim /opt/local/etc/macports/sources.conf
  打开配置文件,更改最后一行的默认下载地址(参考“解决安装macports,不能更新的问题”,参考下载网址列表),如可修改为韩国镜像:



#rsync://rsync.macports.org/release/tarballs/ports.tar
#http://www.macports.org/files/ports.tar.gz
rsync://cjj.kr.rsync.macports.org/macports/release/tarballs/ports.tar
  改好后wq保存退出,再次运行



$ sudo port -v selfupdate
  进行更新,更新成功后会显示如下信息:



--->MacPorts base is already the latest version
The ports tree has been updated. To upgrade your installed ports, you should runport upgrade outdated
  安装过程中遇到其它问题请戳:
  Mac OS X Lion安装MacPorts(让你在Mac的Shell下更加游刃有余)
  Mac中MacPorts安装和使用
  Mac OS X中MacPorts安装和使用

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 = '\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 = '\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   //1、查看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   //2、编译着色器
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 = {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 = {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   //3、链接着色器对象
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;
160   glGenBuffers(2, vboHandles);
161   GLuint positionBufferHandle = vboHandles;
162   GLuint colorBufferHandle = vboHandles;
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
  
页: [1]
查看完整版本: MAC OS下使用Xcode进行GLSL编程的配置过程