OpenGL Shading Language 入门之 Hello World
2015-03-31 14:31
267 查看
帛裂七弦原创作品,转载请注明 http://blog.sina.com.cn/blqx
不管什么语言第一步都是 Hello World
![](http://blogimg.sinajs.cn/images/control/face/004.gif)
OpenGL Shading Language 的 “Hello World”一个旋转的茶壶:
这个例子在 windows下 采用 VC6.0 开发
首先确定你已经安装并可以正常使用 glew 和 glut 扩展库
下一步,新建一个控制台程序,项目加载库文件 glew32.lib
本项目一共5个文件
创建程序文件3个 “ogl3.cpp” “textfile.h” “textfile.cpp”
创建顶点着色器和片元着色器文件 “minimal.vert” 和 “minimal.frag” 并导入到项目中
顶点着色器 “minimal.vert” 程序代码:
这个顶点着色器非常简单,就是将顶点坐标做模型视点变换和投影变化,得到裁剪坐标。
片元着色器 “minimal.frag” 程序代码:
这个片元着色器更加简单,输出一个固定的颜色
我们知道着色器的源代码是由OpenGl驱动程序进行编译和链接的,OpenGl驱动程序大部分是由显卡厂商提供的并作为显卡驱动的一部分,因此VC并不能编译和链接GLSL的源代码。VC要做的事是读取这个以文本形式存在的源代码,并将这些代码以字符形式存下来,提交给OpenGl驱动程序。所以我们的例子中需要文件操作方面的代码。“textfile.h” “textfile.cpp”就是进行这方面的工作。
![](http://s2.sinaimg.cn/bmiddle/41630e7e449ca237effa1)
文本操作 “textfile.h” 程序代码:
文本操作 “textfile.cpp” 程序代码:
下面就是最关键的部分 整个设置着色器的步骤是:
创造空白顶点着色器
读取着色器源代码文件
将着色器源代码字符串数组提交给空白的着色器
编译源代码
创造空白程序对象
将着色器对象附加到程序对象
链接程序对象
安装程序
主要操作 “ogl3.cpp” 程序代码:
注:新浪什么垃圾博客把注释全部都忽略了发不上去 注释只有写成**了。。
不管什么语言第一步都是 Hello World
![](http://blogimg.sinajs.cn/images/control/face/004.gif)
OpenGL Shading Language 的 “Hello World”一个旋转的茶壶:
这个例子在 windows下 采用 VC6.0 开发
首先确定你已经安装并可以正常使用 glew 和 glut 扩展库
下一步,新建一个控制台程序,项目加载库文件 glew32.lib
本项目一共5个文件
创建程序文件3个 “ogl3.cpp” “textfile.h” “textfile.cpp”
创建顶点着色器和片元着色器文件 “minimal.vert” 和 “minimal.frag” 并导入到项目中
顶点着色器 “minimal.vert” 程序代码:
// 顶点着色器 void main() { // 下列三行运行结果一样 gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; // gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; // gl_Position = ftransform(); } |
片元着色器 “minimal.frag” 程序代码:
// 片元着色器 void main() { gl_FragColor = vec4(0.4,0.4,0.8,1.0); } |
我们知道着色器的源代码是由OpenGl驱动程序进行编译和链接的,OpenGl驱动程序大部分是由显卡厂商提供的并作为显卡驱动的一部分,因此VC并不能编译和链接GLSL的源代码。VC要做的事是读取这个以文本形式存在的源代码,并将这些代码以字符形式存下来,提交给OpenGl驱动程序。所以我们的例子中需要文件操作方面的代码。“textfile.h” “textfile.cpp”就是进行这方面的工作。
文本操作 “textfile.h” 程序代码:
/////////////////////////////////////////////////////////////// // // FileName : textfile.h // Creator : 帛裂七弦 // Date : 2008-04-01 14:20:07 // Comment : 读写文本文件(用于读取着色器的源代码.vert和.frag文件) // /////////////////////////////////////////////////////////////// char *textFileRead(char *fn);///读取文件 int textFileWrite(char *fn, char *s);///写入文件 |
/////////////////////////////////////////////////////////////// // // FileName : textfile.cpp // Creator : 帛裂七弦 // Date : 2008-04-01 14:20:07 // Comment : 读写文本文件(用于读取着色器的源代码.vert和.frag文件) // /////////////////////////////////////////////////////////////// #include #include #include char *textFileRead(char *fn) { FILE *fp; char *content = NULL; int count=0; if (fn != NULL) { ///打开文件 fp = fopen(fn,"rt"); if (fp != NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); if (count > 0) { content = (char *)malloc(sizeof(char) * (count+1)); count = fread(content,sizeof(char),count,fp); content[count] = '\0'; } fclose(fp); } } return content; } int textFileWrite(char *fn, char *s) { FILE *fp; int status = 0; if (fn != NULL) { ///打开文件 fp = fopen(fn,"w"); if (fp != NULL) { if (fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) status = 1; fclose(fp); } } return(status); } |
创造空白顶点着色器
读取着色器源代码文件
将着色器源代码字符串数组提交给空白的着色器
编译源代码
创造空白程序对象
将着色器对象附加到程序对象
链接程序对象
安装程序
主要操作 “ogl3.cpp” 程序代码:
注:新浪什么垃圾博客把注释全部都忽略了发不上去 注释只有写成**了。。
/////////////////////////////////////////////////////////////// // // FileName : ogl3.cpp // Creator : 帛裂七弦 // Date : 2008-04-01 15:11:33 // Comment : GLSL入门 // /////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> #include <GL/glew.h> #include <GL/glut.h> #include "textfile.h" #define printOpenGLError() printOglError(__FILE__, __LINE__) static float degree = 0;///茶壶旋转的度数 ** * @brief 处理窗口大小改变 * @param w 窗口的宽 * @param h 窗口的高 ** void changeSize(int w, int h) { ///重新定义视口 glViewport(0, 0, w, h); ///重新设置投影变换 if(h == 0) h = 1;/// 防止高为0产生除0错误 float ratio = 1.0 * w / h;///宽高比 glMatrixMode(GL_PROJECTION);///当前矩阵设为投影矩阵 glLoadIdentity();///清空投影矩阵 gluPerspective(45,ratio,1,1000);//重设投影矩阵 ///模型视点变换 glMatrixMode(GL_MODELVIEW);///当前矩阵设为模型视点矩阵 } ** * @brief 显示函数 ** void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);///清空颜色缓存和深度缓存 glLoadIdentity();///清空模型视点矩阵 ///视点变换 gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0, 0.0f,1.0f,0.0f); ///模型变换 旋转茶壶 glRotatef(degree,0,1,1); ///绘制茶壶 glutSolidTeapot(1); degree += 0.1;///旋转度数增加 glutSwapBuffers();///交换缓存(双缓存模式) } ** * @brief 处理键盘事件 按下 Esc 退出程序 ** void processNormalKeys(unsigned char key, int x, int y) { if(key == 27) exit(0); } ** * @brief 打印OpenGL错误信息 * @param file 错误所在的文件 * @param line 错误所在的行 * @return 1 OpenGL error * @return 0 other error ** int printOglError(char *file, int line) { GLenum glErr; int retCode = 0; glErr = glGetError();///获取错误 while (glErr != GL_NO_ERROR) { printf("glError in file %s @ line %d: %s\n", file, line, gluErrorString(glErr)); retCode = 1; glErr = glGetError();///获取下一个错误 } return retCode; } ** * @brief 打印日志 ** void printInfoLog(GLhandleARB obj) { int infologLength = 0; int charsWritten = 0; char *infoLog; glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength); if (infologLength > 0) { infoLog = (char *)malloc(infologLength); glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog); printf("%s\n",infoLog); free(infoLog); } } ** * @brief 设置着色器 ** void setShaders() { GLhandleARB v,f,p; char *vs = NULL,*fs = NULL; ///创造空白顶点着色器对象并返回其句柄 v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); ///顶点着色器 v f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); ///片元着色器 f ///读取着色器源代码文件 vs = textFileRead("minimal.vert");///顶点着色器源代码字符串 fs = textFileRead("minimal.frag");///片元着色器源代码字符串 ///加入到字符串数组 const char * vv = vs; const char * ff = fs; /// 将着色器源代码字符串数组提交给空白的着色器 /// glShaderSourceARB() 参数表: /// GLhandleARB shader --- 着色器 /// GLuint nstrings --- 字符串数组中多少个元素 本例子就只有1个字符串 /// const GLcharARB **strings --- 字符串数组 /// GLint *lengths --- 对应字符串数组的长度数组 NULL表示所有字符串以null结束 glShaderSourceARB(v, 1, &vv,NULL); glShaderSourceARB(f, 1, &ff,NULL); ///释放字符串所占用的内存空间 free(vs); free(fs); ///编译源代码 glCompileShaderARB(v); glCompileShaderARB(f); ///打印日志 printInfoLog(v); printInfoLog(f); ///创造空白程序对象并返回其句柄 p = glCreateProgramObjectARB(); ///将着色器对象附加到程序对象 glAttachObjectARB(p,v); glAttachObjectARB(p,f); ///链接程序对象 打印日志 glLinkProgramARB(p); printInfoLog(p); ///安装程序对象 glUseProgramObjectARB(p); } ** * @brief 主函数 程序入口 ** int main(int argc, char **argv) { ///创建窗口相关函数 glutInit(&argc, argv);///初始化GLUT并处理命令行参数 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);///深度缓存 双缓存 RGBA颜色模式 glutInitWindowPosition(100,100);///窗口左上角位置 glutInitWindowSize(320,320);///窗口大小 glutCreateWindow("GLSL的第一步");///创建窗口 ///注册各种回调函数 glutDisplayFunc(renderScene);///注册显示回调函数 renderScene glutIdleFunc(renderScene);///注册后台管理函数(事件循环空闲时运行) renderScene glutReshapeFunc(changeSize);///注册窗口大小改变时的回调函数 changeSize glutKeyboardFunc(processNormalKeys);///注册键盘输入回调函数 processNormalKeys ///启动必须的功能 glEnable(GL_DEPTH_TEST);///开启深度缓存测试 glEnable(GL_CULL_FACE);///启动多边形剔除功能 glClearColor(1.0,1.0,1.0,1.0);///指定清除颜色 glewInit();///glew初始化 ///检测是否支持基本的顶点着色器和片元着色器 if(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader) { printf("Ready for GLSL\n"); } else { printf("No GLSL support\n"); exit(1); } setShaders();///设置着色器 glutMainLoop();///进入主循环 return 0; } |
相关文章推荐
- OPENGL的入门第一个程序——Hello World
- OpenGL 纹理的使用入门
- 入门程序,hello world
- OpenGL编程轻松入门之使用颜色
- 黄聪:OpenGl 初级入门学习视频教程, 绘制一个立方体
- 【计算机图形学】OpenGL入门1——第一个OpenGL程序
- OpenGL入门学习(一)
- OpenGL入门
- [转载收藏] Hello World - WDM驱动程序入门 安装步骤
- cocos2dx opengl入门系列三-画一个四边形
- Selenium入门记录_001_环境配置和Hello World!
- AngularJS入门——hello world!
- opengl 入门学习
- OBJECTIVE-C入门(1) HELLO WORLD
- shell入门之hello world!
- OpenGL入门学习
- Linux设备驱动程序学习(一)入门必须的hello world
- Dojo入门Hello World!
- OpenGL入门学习(十四) 【转】
- Node.js入门,第一个APP,Hello World