GLSL教程1
- 格式:doc
- 大小:240.50 KB
- 文档页数:30
OpenGl中使⽤着⾊器的基本步骤及GLSL渲染简单⽰例OpenGL着⾊语⾔(OpenGL Shading Language,GLSL)是⽤来在OpenGL中着⾊编程的语⾔,是⼀种具有C/C++风格的⾼级过程语⾔,同样也以main函数开始,只不过执⾏过程是在GPU上。
GLSL使⽤类型限定符⽽不是通过读取和写⼊操作来管理输⼊和输出。
着⾊器主要分为顶点着⾊器(Vertex Shader)和⽚段着⾊器(Fragment Shader)两部分。
顶点着⾊器的主要功能是:顶点法线变换及单位化纹理坐标变换光照参数⽣成顶点着⾊器的输⼊内容包括:着⾊器源代码attribute变量uniform变量顶点着⾊器的输出内容包括:varying变量内置的特殊变量,如gl_Position、gl_FrontFacing、gl_PointSize⽚元着⾊器的主要功能:在差值得到的值上进⾏操作访问纹理应⽤纹理雾化颜⾊融合⽚元着⾊器的输⼊内容包括:着⾊器源代码⽤户⾃定义的varying变量uniform变量采样器(Sampler)⼀些内置的特殊变量(gl_PointCoord、gl_FragCoord、gl_FrontFacing等)⽚元着⾊器的输出:内置的特殊变量gl_FragColor在OpenGL程序中使⽤着⾊器的初始化⼀般需要依次执⾏以下步骤:1、顶点着⾊程序的源代码和⽚段着⾊程序的源代码分别写⼊到⼀个⽂件⾥(或字符数组)⾥⾯,⼀般顶点着⾊器源码⽂件后缀为.vert,⽚段着⾊器源码⽂件后缀为.frag;2、使⽤glCreateshader()分别创建⼀个顶点着⾊器对象和⼀个⽚段着⾊器对象;3、使⽤glShaderSource()分别将顶点/⽚段着⾊程序的源代码字符数组绑定到顶点/⽚段着⾊器对象上;4、使⽤glCompileShader()分别编译顶点着⾊器和⽚段着⾊器对象(最好检查⼀下编译的成功与否);5、使⽤glCreaterProgram()创建⼀个着⾊程序对象;6、使⽤glAttachShader()将顶点和⽚段着⾊器对象附件到需要着⾊的程序对象上;7、使⽤glLinkProgram()分别将顶点和⽚段着⾊器和着⾊程序执⾏链接⽣成⼀个可执⾏程序(最好检查⼀下链接的成功与否);8、使⽤glUseProgram()将OpenGL渲染管道切换到着⾊器模式,并使⽤当前的着⾊器进⾏渲染;以下是⼀个功能简单但流程完整的使⽤顶点着⾊器和⽚段着⾊器渲染的矩形图形。
glsl 语法GLSL是一种高级编程语言,用于编写着色器程序并在OpenGL ES或OpenGL上运行。
GLSL是OpenGL着色器语言的缩写。
这种语言的主要目的是描述如何把GPU中的顶点和像素转化成最终图像。
GLSL本质上是一种类C语言,因此将其用于实现着色器程序的过程是相当容易和自然的。
着色器是在GPU上运行的小程序,它们能够根据输入的数据生成颜色、纹理、阴影等效果。
其中,顶点着色器(vertex shader)负责处理顶点数据,将其变换到适合绘制的视图坐标系中;而片段着色器(fragment shader)则负责处理像素数据,根据交互效应来生成最终颜色。
GLSL 编译器能够将这些着色器代码编译成机器语言,从而为GPU 提供可执行的着色器程序。
GLSL的语法包括以下几个方面。
1. 数据类型:GLSL支持vec2、vec3、vec4、mat2、mat3、mat4、int、float、bool、sampler2D等数据类型。
不同的数据类型具有不同的作用和属性。
其中,vec2、vec3、vec4表示二维矢量、三维矢量和四维矢量,mat2、mat3、mat4表示矩阵,int和float代表整数和实数,bool代表布尔型。
2. 函数:GLSL支持一些内置函数,例如normalize()、length()、dot()、cross()、mix()等。
这些函数能够处理向量、矩阵等数据类型,以及生成颜色、纹理等效果。
3. 运算符:GLSL支持常见的运算符,包括加、减、乘、除、赋值、比较等运算符。
此外,GLSL还支持复合运算符,例如+=,*=,-=等。
4. 控制语句:GLSL支持if/else、while、for等控制语句,还支持break、continue、return等流程控制语句。
5. 变量定义:GLSL中的变量定义方式与C语言类似。
可以使用类型名称和变量名定义变量,例如:vec4 position = vec4(0.0, 0.0, 0.0, 1.0);。
GLSL Shader特效(一)遮罩特效在游戏中很多特效可以通过美工等工具来实现。
在此教大家如何通过GPU的shader 来实现,让CPU打盹。
作为该系列的第一个教程,教大家如何让写一个遮罩特效。
这样比较容易上手。
在高级阶段教大家如何在shader中实现复杂的3D特效,包括光线追踪和体积渲染。
如果你对opengl、es没有基础,可以先放开不理会。
你只需要了解C语言。
GLSL和C语音很相似,语法也比较简单。
GPU的shader编程对数学和物理的要求比较高,特别是立体几何和线性代数。
如果你已经把立体几何忘光了,后面可以补,现在要熟悉平面几何里的向量和矩阵、坐标系的变换。
作为第一个教程,还没涉及矩阵和坐标系变换。
但如何你真的忘记了,要花点时间来复习下了,时间挤挤都会有的。
在开始之前先普及下GPU和CPU的区别:两者的主要区别在于GPU是完全并行的,具有多个(例如512)逻辑运算单元,但计算能力不如CPU的逻辑运算单元;CPU虽然有多核的,但一般不多于10 。
一般都是2、4、8核,多于16核的一般人都用不到。
在CPU的编程中你可以假设“邻居”数据而完成一些复杂的算法运算。
但在GPU中数据是完全并行的,你不能假设其他数据,这也是为什么在GPU 中你永远看不到“求和”函数的存在,例如在GLSL中,你找不到类似sum的求和函数。
在CPU的多核和多线程、多进程的并行编程中,不是真正严格意义上的并行。
因为只要涉及到数据的共享就会导致资源的竞争,为了数据的一致性和安全,就必须采取加锁(读写锁、自旋锁、RCU等)或者线程等待,这些机制都将会导致某些进程、线程被迫等待而被内核调度器挂起(或者主动放弃CPU),放在运行等待队列中,等待其他线程的唤起或者再次被内核调度器调度。
好比,茅坑被占了,即使后面有再多的人(线程或者进程)都必须要排队。
因此,这就不是真正的并行了。
可以说这是真正并行和串行产生的一个折中的处理机制。
GPU的设计是真正的并行设计。
GLSL基础语法介绍
GLSL(OpenGL Shading Language)是一种用于编写着色器的编程语言。
以下是GLSL的一些基础语法:
1.变量类型:GLSL支持多种变量类型,包括float、int、bool、vec2、vec3、
vec4等。
其中,vec2、vec3和vec4分别表示2维、3维和4维向量。
2.变量声明:在GLSL中,变量可以在声明时初始化。
例如,以下代码声明了
一个名为“a”的浮点型变量,并将其初始化为1.0:
float a = 1.0;
3.运算符:GLSL支持基本的算术运算符(如+、-、*、/)和比较运算符(如
==、!=、<、>、<=、>=)。
4.控制结构:GLSL支持if-else语句、for循环和while循环等控制结构。
例
如,以下代码使用for循环打印出0到9的数字:
for (int i = 0; i < 10; i++) {
gl_FragColor = vec4(i, 0, 0, 1);
}
5.函数:GLSL支持内建函数和自定义函数。
例如,以下代码使用内建的sin
函数计算正弦值:
float a = sin(1.0);
以上是GLSL的一些基础语法,如果你需要更深入的学习,可以参考相关的学习资料或在线教程。
glslcookbook 代码编译(原创实用版)目录1.GLSL 概述2.代码编译过程3.编译器选项和参数4.代码优化和调试5.结论正文1.GLSL 概述GLSL(OpenGL Shading Language)是一种基于 C 语言的编程语言,用于编写 OpenGL 着色器程序。
着色器程序在计算机图形学中扮演着至关重要的角色,它们负责计算渲染到屏幕上的 3D 模型的颜色和纹理。
GLSL 具有较高的性能,因为它是专为图形处理器(GPU)优化的。
2.代码编译过程在编写 GLSL 代码时,我们需要将其编译为可在 GPU 上执行的着色器程序。
编译过程主要包括以下步骤:- 预处理:预处理器负责处理 GLSL 代码中的宏、条件编译和文件包含等预处理指令。
- 词法分析:词法分析器将预处理后的代码转换为单词(tokens),例如变量名、关键字和运算符等。
- 语法分析:语法分析器将单词转换为抽象语法树(AST),它是一种层次结构,表示代码的语法结构。
- 语义分析:语义分析器检查 AST 中的语法错误和语义错误,例如类型不匹配等。
- 中间代码生成:中间代码生成器将经过语义分析的 AST 转换为可在 GPU 上执行的低级代码。
- 优化和调试:编译器可以应用各种优化技术,以提高代码的性能。
此外,我们还可以使用调试器查找和修复代码中的错误。
- 代码生成:最后,编译器将中间代码转换为可在 GPU 上执行的二进制代码。
3.编译器选项和参数在编译 GLSL 代码时,我们可以使用各种编译器选项和参数来影响编译过程。
例如:- -o:指定输出文件。
- -I:指定包含目录。
- -D:指定宏定义。
- -p:指定调试选项。
- -O:指定优化选项。
4.代码优化和调试为了提高 GLSL 代码的性能,我们可以采用以下优化技术:- 使用着色器语言规范中的内置函数,而不是自定义函数。
- 避免在顶点着色器中使用复杂的计算。
- 使用纹理压缩格式以减少内存占用。
glsl内联函数GLSL(OpenGL着色语言)是一种用于编写OpenGL程序的编程语言。
在GLSL中,内联函数是一种特殊的函数,可以直接在着色器代码中定义和使用。
本文将介绍GLSL内联函数的概念、定义与使用,以及其在实际编程中的应用实例。
1.GLSL内联函数概述GLSL内联函数是一种特殊的函数,与普通函数相比,它在编译时会被直接替换为函数体,而不是作为一个独立的函数调用。
这使得内联函数具有更高的执行效率,因为避免了函数调用的开销。
同时,内联函数也可以实现一些简单的功能,例如数学运算、类型转换等。
2.GLSL内联函数的定义与使用在GLSL中,内联函数的定义与普通函数相似,但需要使用`inline`关键字声明。
例如,以下是一个简单的内联函数,用于计算两个向量的和:```glslinline vec2 add(vec2 a, vec2 b) {return a + b;}```使用内联函数时,只需在需要调用函数的地方直接写上函数名,并传入所需的参数。
例如,要使用上述内联函数计算两个向量的和,可以这样写:```glslvec2 sum = add(vec2(1, 2), vec2(3, 4));```3.GLSL内联函数的优缺点优点:- 内联函数具有较高的执行效率,因为避免了函数调用的开销。
- 内联函数可以实现一些简单的功能,方便开发者进行编程。
缺点:- 内联函数可能导致代码可读性降低,尤其是当函数体较长时。
- 内联函数过多可能会导致着色器代码体积膨胀,增加编译时间。
4.内联函数在GLSL编程中的应用实例以下是一个使用内联函数实现在顶点着色器中计算两点之间距离的例子:```glslinline float distance(vec2 a, vec2 b) {return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));}void main() {vec2 posA = vec2(10, 20);vec2 posB = vec2(30, 40);float dist = distance(posA, posB);// 后续代码}```5.总结GLSL内联函数是一种在编译时直接替换为函数体的特殊函数,具有较高的执行效率。
着⾊器语⾔GLSL(opengl-shader-language)⼊门⼤全基本类型:类型说明void空类型,即不返回任何值bool布尔类型 true,falseint带符号的整数 signed integerfloat带符号的浮点数 floating scalarvec2, vec3, vec4n维浮点数向量 n-component floating point vectorbvec2, bvec3, bvec4n维布尔向量 Boolean vectorivec2, ivec3, ivec4n维整数向量 signed integer vectormat2, mat3, mat42x2, 3x3, 4x4 浮点数矩阵 float matrixsampler2D2D纹理 a 2D texturesamplerCube盒纹理 cube mapped texture基本结构和数组:类型说明结构struct type-name{} 类似c语⾔中的结构体数组float foo[3] glsl只⽀持1维数组,数组可以是结构体的成员向量的分量访问:glsl中的向量(vec2,vec3,vec4)往往有特殊的含义,⽐如可能代表了⼀个空间坐标(x,y,z,w),或者代表了⼀个颜⾊(r,g,b,a),再或者代表⼀个纹理坐标(s,t,p,q) 所以glsl提供了⼀些更⼈性化的分量访问⽅式.vector.xyzw其中xyzw 可以任意组合vector.rgba其中rgba 可以任意组合vector.stpq其中rgba 可以任意组合vec4 v=vec4(1.0,2.0,3.0,1.0);float x = v.x; //1.0float x1 = v.r; //1.0float x2 = v[0]; //1.0vec3 xyz = v.xyz; //vec3(1.0,2.0,3.0)vec3 xyz1 = vec(v[0],v[1],v[2]); //vec3(1.0,2.0,3.0)vec3 rgb = v.rgb; //vec3(1.0,2.0,3.0)vec2 xyzw = v.xyzw; //vec4(1.0,2.0,3.0,1.0);vec2 rgba = v.rgba; //vec4(1.0,2.0,3.0,1.0);运算符:优先级(越⼩越⾼)运算符说明结合性1()聚组:a*(b+c)N/A2[] () . ++ --数组下标__[],⽅法参数__fun(arg1,arg2,arg3),属性访问__a.b__,⾃增/减后缀__a++ a--__L - R3++ -- + - !⾃增/减前缀__++a --a__,正负号(⼀般正号不写)a ,-a,取反__!false__R - L4* /乘除数学运算L - R5+ -加减数学运算L - R7< > <= >=关系运算符L - R8== !=相等性运算符L - R12&&逻辑与L - R13^^逻辑排他或(⽤处基本等于!=)L - R14||逻辑或L - R15__? :__三⽬运算符L - R16= += -= *= /=赋值与复合赋值L - R17,顺序分配运算L - Rps 左值与右值:左值:表⽰⼀个储存位置,可以是变量,也可以是表达式,但表达式最后的结果必须是⼀个储存位置.右值:表⽰⼀个值, 可以是⼀个变量或者表达式再或者纯粹的值.操作符的优先级:决定含有多个操作符的表达式的求值顺序,每个操作的优先级不同.操作符的结合性:决定相同优先级的操作符是从左到右计算,还是从右到左计算。
现代OpenGL教程 01——入门指南欢迎大家,这是现代OpenGL教程系列的第一篇。
所有代码都是开源的,你可以在GitHub上下载:https:///tomdalling/opengl-series 通过这篇教程,你将会学到如何在Windows下用Visual Studio 2013或Mac下用Xcode搭建OpenGL 3.2工程。
该应用包含一个顶点着色器(vertex shader),一个片段着色器(fragment shader)和使用VAO和VBO来绘制的三角形。
该工程使用GLEW来访问OpenGL API,用GLFW来处理窗口创建和输入,还有使用GLM进行矩阵/矢量相关的数学运算。
这听上去有点无聊,但搭建这样的工程确实挺麻烦的,尤其对于初学者。
只要解决完这问题,我们就可以开始玩些有趣的东西了。
[TOC]获取代码所有例子代码的zip打包可以从这里获取:https:///tomdalling/opengl-series/archive/master.zip。
这一系列文章中所使用的代码都存放在:https:///tomdalling/opengl-series。
你可以在页面中下载zip,加入你会git的话,也可以复制该仓库。
本文代码你可以在source/01_project_skeleton目录里找到。
使用OS X系统的,可以打开根目录里的opengl-series.xcodeproj,选择本文工程。
使用Windows系统的,可以在Visual Studio 2013里打开opengl-series.sln,选择相应工程。
工程里已包含所有依赖,所以你不需要再安装或者配置额外的东西。
如果有任何编译或运行上的问题,请联系我。
关于兼容性的提醒本文使用OpenGL 3.2,但我会尝试保持如下兼容:向后兼容OpenGL 2.1向前兼容OpenGL 3.X和4.X兼容Android和iOS的OpenGL ES 2.0因为OpenGL和GLSL存在许多不同版本,本文代码不一定能做到100%上述兼容。
GLSL学习__中文版2.1 OpenGL Shading语言介绍这本书的目的是帮助读者学习和使用高级图形编程语言――OPENGL SHADING 语言。
对于这种语言提供支持的相关OpenGL扩展在2003年6说被ARB组织批准,并且将被加入到新的OpenGL2.0的核心中去。
当前图形硬件的变得越来越复杂,那些传统的固定功能逐渐将被可编程的功能取代。
顶点处理和面片处理就是两个这样的例子。
顶点处理包括那些对于每一个顶点进行分别运算的步骤,比如坐标转换和光照。
面片指的那些在图形数据光栅化时象素对应的数据结构。
一个面片包含更新帧缓存中某个位置数据的所有必要信息。
面片处理包括所有发生在面片级别上的操作,比较典型的例子就是从包含纹理的存储器中获得数据,以及将纹理值赋予每一个面片。
通过使用OpenGL Shading语言,用户不仅仅可以实现所有显卡的固定管线功能,而且可以做的更多.OpenGL Shading的设计使程序员能够在OpenGL渲染管线中每一个可编程的地方实现他们的想法。
通过OpenGL Shading语言的代码编写的能够在OpenGL可编程处理器上运行的程序代码叫做SHADER。
OpenGL Shader这个词有时候也用来特指那些用OpenGL Shading语言开发的shader,以和那些使用其他shading语言(比如RenderMan)开发的shader相区分。
因为在OpenGL中定义了两种可编程的处理单元,所以也对应有两种类型的shader:顶点shader和面片shader。
OpenGL可以将shader 进行编译链接,使其成为可执行程序一部分。
OpenGL Shading语言是基于C语言发展起来的,它和RenderMan以及其他的shading语言拥有相同的特征。
这种语言有丰富的数据类型定义,其中包括向量和矩阵这些与三维操作息息相关的类型定义。
一些类型qualifiers对输入和输出进行处理,使其适合shader使用。
GLSL教程(1)1 管线(pipeline)简介上图中一个顶点(V ertex )是一组属性,包括位置,颜色,纹理坐标等。
1.1顶点转换模块(V ertex Transformation)在此模块实现功能:顶点位置转换为每个顶点计算光照纹理坐标的生成与转换1.2图元安装和光栅化处理模块(Primitive Assembly and Rasterization)此阶段的输入是转换后的数据和连接信息。
连接信息告诉管线顶点是如何连接为图元的。
光栅化决定了片断和像素位置。
片断是一组用于更新桢缓存中像素的数据。
片断包括颜色,纹理坐标等。
在此模块输出包括:桢缓存中片断的位置在顶点阶段计算的属性的每一片断的插值1.3 片断纹理和颜色模块(Fragment Texturing and Coloring)此模块的输入是插值处理后的片断。
在这个阶段一个颜色元素可以绑定到一个纹理元素,雾化处理也在这个阶段。
通常这个阶段的输出值是一个颜色值和一个片断的深度。
1.4光栅操作模块(Raster Operations)此阶段的输入:像素位置片断深度和颜色值在这个阶段对片断进行一系列的测试,包括:剪取测试Alpha测试模版测试深度测试如果测试成功,则根据当前的混合模式用片断信息来更新像素值。
1.5总结:上面的过程可以用下面的图形象进行概括:2 顶点处理器顶点处理器用来运行顶点着色程序。
顶点着色程序的输入是顶点数据,即颜色,位置等。
下面这段代码为每个顶点发送给顶点处理器一个颜色和一个顶点的位置。
glBegin(...); glColor3f(0.2,0.4,0.6); glV ertex3f(-1.0,1.0,2.0); glColor3f(0.2,0.4,0.8); glV ertex3f(1.0,-1.0,2.0); glEnd();在一个顶点着色程序中,你可以写代码实现功能如:顶点位置转换规范化处理纹理坐标的生成和转化为顶点计算光照颜色计算顶点着色程序至少要写入一个变量,如gl_Position,用于矩阵转换。
3 片断处理器片断处理器负责下面的操作:为每个像素计算颜色,纹理坐标纹理应用雾化计算若想为每个像素进行光照则进行规范化此阶段的输入是先前阶段进行的差值,包括顶点的颜色,位置等。
像顶点处理器一样,我们写得片断着色程序将代替所有固定的函数。
所以我们必须对实际应用的所有要求全部在着色程序中编码实现。
片断处理器只能对一个片断进行处理,没有此片断相邻片断的信息。
重要的一点是一个片断着色器不能改变像素坐标。
这与顶点着色器是不同的,在顶点着色器中,模型和映射矩阵用于顶点变换。
片断着色程序可以访问屏幕上像素的位置,但不能改变它。
片断着色器有两个输出:丢弃片断,什么也不输出要么计算最终的片断颜色gl_FragColor 要么计算多重目标着色的gl_FragData注意片断着色程序不能访问桢缓存。
这意味着混合操作只能发生在片断着色器运行后。
4 GLSL安装在这部分,假设你已经有了一对着色程序,顶点着色程序和片段着色程序,你想把他们应用到OPENGL程序中。
每个着色程序就像C模块一样,它必须被单独编译,然后链接到一个程序中。
在这里我们使用两种方法来进行说明:ARB扩展和opengl2.0程序。
GLEW使得扩展使用起来非常方便。
如果要使用扩展部分,而你不支持opengl2.0,那么下面两个扩展要用到:GL_ARB_fragment_shaderGL_ARB_vertex_shader下面代码是一个简单的例子检查扩展是否可用:#include <GL/glew.h>#include <GL/glut.h>void main(int argc, char **argv){glutInit(&argc, argv);...glewInit();if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)printf("Ready for GLSL\n");else {printf("Not totally ready :( \n");exit(1);}setShaders();glutMainLoop();}下面代码是一个简单的例子检查opengl2.0是否可用:#include <GL/glew.h>#include <GL/glut.h>void main(int argc, char **argv){glutInit(&argc, argv);...glewInit();if (glewIsSupported("GL_VERSION_2_0"))printf("Ready for OpenGL 2.0\n");else{printf("OpenGL 2.0 not supported\n");exit(1);}setShaders();glutMainLoop();}下面图片是opengl程序和着色程序的关系:5 建立一个着色程序(Creating a shader)建立着色程序共需要三步:第一种方法:opengl2.0GLuint glCreateShader(GLenum shaderType);shaderType - GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings);shader - the handler to the shader.numOfStrings - the number of strings in the array.strings - the array of strings.lenOfStrings - an array with the length of each string, or NULL, meaning that the strings are NULL terminatedvoid glCompileShader(GLuint shader);Parameters:shader - the handler to the shader.第二种方法:ARB扩展GLhandleARB glCreateShaderObjectARB(GLenum shaderType);Parameter:shaderType - GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB.void glShaderSourceARB(GLhandleARB shader, int numOfStrings, const char **strings, int *lenOfStrings);Parameters:shader - the handler to the shader.numOfStrings - the number of strings in the array.strings - the array of strings.lenOfStrings - an array with the length of each string, or NULL, meaning that the strings are NULL terminated.void glCompileShaderARB(GLhandleARB shader);Parameters:shader - the handler to the shader.6 编写一个程序下图是编写一个程序的步骤:第一种方法:opengl2.0GLuint glCreateProgram(void);void glAttachShader(GLuint program, GLuint shader);Parameters:program - the handler to the program.shader - the handler to the shader you want to attach.void glLinkProgram(GLuint program);Parameters:program - the handler to the program.void glUseProgram(GLuint prog);Parameters:prog - the handler to the program you want to use, or zero to return to fixed functionality示例:void setShaders() {char *vs,*fs;v = glCreateShader(GL_VERTEX_SHADER);f = glCreateShader(GL_FRAGMENT_SHADER);vs = textFileRead("toon.vert");fs = textFileRead("toon.frag");const char * vv = vs;const char * ff = fs;glShaderSource(v, 1, &vv,NULL);glShaderSource(f, 1, &ff,NULL);free(vs);free(fs);glCompileShader(v);glCompileShader(f);p = glCreateProgram();glAttachShader(p,v);glAttachShader(p,f);glLinkProgram(p);glUseProgram(p);}第二种方法:ARB扩展GLhandleARB glCreateProgramObjectARB(void);void glAttachObjectARB(GLhandleARB program, GLhandleARB shader); Parameters:program - the handler to the program.shader - the handler to the shader you want to attach.void glLinkProgramARB(GLhandleARB program);Parameters:program - the handler to the program.void glUseProgramObjectARB(GLhandleARB prog);Parameters:prog - the handler to the program you want to use, or zero to return to fixed functionalityvoid setShaders(){char *vs,*fs;v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);vs = textFileRead("toon.vert");fs = textFileRead("toon.frag");const char * vv = vs;const char * ff = fs;glShaderSourceARB(v, 1, &vv,NULL);glShaderSourceARB(f, 1, &ff,NULL);free(vs);free(fs);glCompileShaderARB(v);glCompileShaderARB(f);p = glCreateProgramObjectARB();glAttachObjectARB(p,v);glAttachObjectARB(p,f);glLinkProgramARB(p);glUseProgramObjectARB(p);}///////////////////////////////////////////////////////////////////////////** my first glsl program, hello - glsl* now, go!**/#define GLUT_DISABLE_A TEXIT_HACK#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <gl/glew.h>#include <gl/glut.h>// grid resolution#define N 64// vision regionconst GLdouble nearV al = 1.0;const GLdouble farV al = 20.0;// program object IDGLuint program = 0;GLint timeParam;// error buffer and error message lengthGLchar *ebuffer;GLsizei elength;// high field dataGLfloat data[N][N];// shader read entry functionstatic char* readShaderSource(const char * shaderFile) {char *buf = NULL;int size(0);FILE *file = fopen(shaderFile, "r");if (!file) return NULL;fseek(file, 0, SEEK_END);size = ftell(file);rewind(file);if (size > 0){buf = (char*)malloc(sizeof(char)*(size+1));size = fread(buf, sizeof(char), size, file);buf[size] = '\0';}fclose(file);return buf;}// init OpenGLstatic void initGL(){glClearColor(1.0f, 1.0f, 1.0f, 1.0f);glColor3f(0.0, 0.0, 0.0);glMatrixMode( GL_PROJECTION );glLoadIdentity();glOrtho(-0.75, 0.75, -0.75, 0.75, -5.5, 5.5);}// init GLSLstatic void initShader(const GLchar * vShaderFile, const GLchar * fShaderFile)GLint status;GLchar *vSource, *fSource;GLuint vShader, fShader;// read shader filevSource = readShaderSource(vShaderFile);if ( vSource == NULL ){printf("Failed to read vertex shader\n");exit( EXIT_FAILURE );}fSource = readShaderSource(fShaderFile);if ( fSource == NULL ){printf("Failed to read fragment shader\n");exit( EXIT_FAILURE );}//create program and shader objectvShader = glCreateShader( GL_VERTEX_SHADER );fShader = glCreateShader( GL_FRAGMENT_SHADER ); program = glCreateProgram();// bind shader to program objectglAttachShader( program, vShader );glAttachShader( program, fShader );// read shaderglShaderSource( vShader, 1, (const GLchar**)&vSource, NULL ); glShaderSource( fShader, 1, (const GLchar**)&fSource, NULL );// compile vertex shaderglCompileShader( vShader );// error detectionglGetShaderiv( vShader, GL_COMPILE_STA TUS, &status );if ( status == GL_FALSE ){printf("Failed to compile vertex shader\n");glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &elength); ebuffer = (char*)malloc(elength*sizeof(char)); glGetShaderInfoLog(vShader, elength, NULL, ebuffer);printf("%s\n", ebuffer);exit( EXIT_FAILURE );}// compile fragment shaderglCompileShader( fShader );// error detectionglGetShaderiv( fShader, GL_COMPILE_STA TUS, &status );if ( status == GL_FALSE ){printf("Failed to compile fragment shader\n"); glGetShaderiv(fShader, GL_INFO_LOG_LENGTH, &elength); ebuffer = (char*)malloc(elength*sizeof(char)); glGetShaderInfoLog(fShader, elength, NULL, ebuffer);printf("%s\n");exit( EXIT_FAILURE );// link and error detectionglLinkProgram( program );glGetProgramiv( program, GL_LINK_STA TUS, &status );if ( status == GL_FALSE ){printf("Failed to link program object\n");glGetProgramiv( program, GL_INFO_LOG_LENGTH, &elength ); ebuffer = (char*)malloc(elength*sizeof(char)); glGetProgramInfoLog(program, elength, &elength, ebuffer);printf("%s\n");exit( EXIT_FAILURE );}// use program objectglUseProgram( program );// set uniform parametertimeParam = glGetUniformLocation( program, "time" );}// meshvoid mesh(){int i(0), j(0);glMatrixMode( GL_MODELVIEW );glLoadIdentity();gluLookAt(2.0, 2.0, 2.0, 0.5, 0.0, 0.5, 0.0, 1.0, 0.0);for (i = 0; i < N; i++){for (j = 0; j < N; j++){glBegin( GL_LINE_LOOP );glV ertex3f((float)i/N, data[i][j], (float)j/N);glV ertex3f((float)i/N, data[i][j], (float)(j+1)/N);glV ertex3f((float)(i+1)/N, data[i][j], (float)(j+1)/N);glV ertex3f((float)(i+1)/N, data[i][j], (float)j/N);glEnd();}}}static void display(){// transfer run-time to shaderglUniform1f( timeParam, glutGet(GLUT_ELAPSED_TIME) ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); mesh();glutSwapBuffers();}// reshape callback functionstatic void reshape(int w, int h){glMatrixMode( GL_PROJECTION );glLoadIdentity();glOrtho(-0.75, 0.75, -0.75, 0.75, -5.5, 5.5);glViewport(0, 0, w, h);glutPostRedisplay();}// keyboard callback functionstatic void keyboard(unsigned char key, int x, int y){switch(key){case 27:case 'Q':case 'q':exit( EXIT_FAILURE );break;default:break;}}// idle callback functionstatic void idle(){glUniform1f( timeParam, (GLfloat)glutGet(GLUT_ELAPSED_TIME) ); glutPostRedisplay();}// check whether GLEW and GLSL are supportedbool check(){const char * version = (const char*)glGetString( GL_VERSION ); printf("OpenGL version : %s\n", version);// check OpenGLif ( glewIsSupported("GL_VERSION_2_0") )printf("Ready for OpenGL 2.0\n");}else{printf("OpenGL 2.0 not supported\n");return false;}// check extensionsif ( GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader ) {printf("Ready for GLSL\n");}else{printf("Not totally ready\n");return false;}return true;}// mainint main(int argc, char ** argv){int i(0), j(0);for (i = 0; i < N; i++){for (j = 0; j < N; j++){data[i][j] = 0;}}glutInit(&argc, argv);glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );glutInitWindowSize(512, 512);glutCreateWindow("Simple GLSL example");glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutIdleFunc(idle);// init GLEW, this is very importantglewInit();// check whether GLEW and GLSL are supportedif ( !check() ){return 0;}initGL();initShader("vmesh.vert", "fPassThrough.frag");glutMainLoop();return 0;}两个shader文件,分别存为vmesn.vert和fPassThrough.frag,代码如下:vmesh.vert文件//// vertex shader//uniform float time;void main(){float s;vec4 t = gl_V ertex;t.y = 0.1*sin(0.001*time + 5.0*gl_V ertex.x) * sin(0.001*time + 5.0*gl_V ertex.z);gl_Position = gl_ModelViewProjectionMatrix * t;gl_FrontColor = gl_Color;}fPassThrough.frag文件//// mesh shader//void main(){gl_FragColor = gl_Color;}本文来自CSDN博客,转载请标明出处:/mike_zw/archive/2010/10/19/5951677.aspx7 变量类型着色程序中常用的变量是uniform,attribute变量。