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 [default]
#http://www.macports.org/files/ports.tar.gz [default]
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 run  port 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[count] = '';
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] = '';
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[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     //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[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

原文地址:https://www.cnblogs.com/openxxs/p/4055916.html