Opengl红皮书有选择的看了一些,最后的讲着色语言GLSL的部分看的甚为不理解,然后找到Opengl橙皮书,然后就容易理解多了。 

  在前面,我们或多或少接触到Opengl的处理过程,只说前面一些处理,简单来说:顶点操作-组装图形-栅栏化-片断处理-帧缓冲。其中顶点操作相当于我们在程序里设定顶点,法向量等,组装图形就是opengl以我们设定的格式连接顶点,如组装成三角形,四边形等。栅栏化就是把上部操作的图元分解成更小的单元,如一个三角形里有100个像素,在这个过程会转换成100个片断,这个片断包含了窗口坐标,深度,颜色,纹理坐标等组成。片断处理就是把上面生成的片断进行一些如组合纹理,雾效果等。

  在最开始,Opengl在上面的各个处理被设置好,如前面,我们按照给定的API来打开光照,设定纹理,设定材质等,这个在大部分情况下已经能得到比较好的效果,但是通过Opengl API,我们不能更改Opengl图形管道的一些基本操作,也不能改变相应的顺序,如果想要实现一些特殊的效果,可能就实现不了了。GLSL就是在这种情况下出现的,主要是允许应用程序对在Opengl处理流程进行自己的实现。

  GLSL让我现在的理解,就是语法简单,用起来就需要经验了,为什么这么说,因为GLSL的语法是在C和C++的基础了简化了一些元素与特性,如GLSL里没有指针,字符串以及相应操作,不支持double,byte,short,long以及相应的符号形式。以及联合,枚举。大家可以想象一下,还有什么在里面,但是用起来一点都不简单,就我现在的感觉,里面内置的函数,相关变量,常量不少,灵活运用肯定需要一定的GLSL代码量。最后GLSL为了突出图形计算这块,内置了一些图形计算所需要的结构vec3,vec4,mat4等,最后GLSL和F#一样,不支持数据类型自动提升,如float f = 1这个是错的,应该是 f = 1.0.

  GLSL通常会包含二种着色器,顶点着色器和片断着色器,最常见用法是在顶点着色器里生成所需要的值,然后传给片断着色器用。着色器中常用限定符有attribute,unifrom,varying,const.其中attribute是应用程序传给顶点着色器用的,着色器不能修改。unifrom一般是应用程序用于设定顶点着色器和片断着色器相关初始化值。varying用于传递顶点着色器的值给片断着色器。const和C++里差不多,定义不可变常量。

  GLSL内置的相关变量,常量,结构大家在OpenGL橙皮书里找。下面我们来完整的实现OpenGL的第一个例子,砖墙。顶点着色器如下:

 1 //一致变量 设置灯光位置(提供眼睛坐标位置)
 2 uniform vec3 LightPosition;
 3 //常量 镜面反射强度
 4 const float SpecularContribution = 0.3;
 5 //常量 漫反射强度
 6 const float DiffuseContribution = 1.0 - SpecularContribution;
 7 //物体顶点上的光强度 易变变量 传给片断着色器
 8 varying float LightIntensity;
 9 //物体顶点位置
10 varying vec2 MCposition;
11 //顶点着色器入口
12 void main(void)
13 {
14     //顶点在视图坐标中的位置
15     vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex);
16     //顶点在视图坐标中的法向量,gl_NormalMatrix为gl_ModelViewMatrix逆矩阵的倒置矩阵
17     vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);
18     //视图坐标中灯光的位置 取顶点到灯光的单位向量
19     //LightPosition如果是全局坐标里的值,应该进行gl_ModelViewMatrix转换
20     vec3 lightVec = normalize(LightPosition - ecPosition);
21     //灯光到顶点经过tnorm的表面反射光向量 reflect i n = i - 2.0*dot(N,I)*N
22     vec3 reflectVec = reflect(-lightVec,tnorm);
23     //查看位置向量单位向量 就是在视图坐标中,眼睛到顶点的向量.eye(0,0,0)
24     vec3 viewVec = normalize(-ecPosition);
25 
26     //一是用来计算lightVec的tnorm角度,二是计算lightVec在顶点上的漫反射强度
27     float diffuse = max(dot(lightVec,tnorm),0.0);
28     float spec = 0.0;
29     //只有lightVec与tnorm的角度在90度之间,才可能反射光照
30     if(diffuse > 0.0)
31     {        
32         //计算反射光在人看的方向上的分量。角度越少,分量越多。
33         spec = max(dot(reflectVec,viewVec),0.0);
34         spec = pow(spec,16.0);
35     }
36     //计算光照,主要成分为漫反射与镜面反射
37     LightIntensity = DiffuseContribution * diffuse + SpecularContribution * spec;
38     //传个片断着色器的x,y位置
39     MCposition = gl_Vertex.xy;
40     //定点坐标位置不变性
41     gl_Position = ftransform();
42 }
View Code

相关文章:

  • 2021-08-15
  • 2021-08-05
  • 2022-12-23
  • 2022-12-23
  • 2021-09-18
  • 2021-12-05
  • 2021-06-09
  • 2021-08-04
猜你喜欢
  • 2021-11-27
  • 2021-04-13
  • 2021-04-28
  • 2021-05-29
  • 2022-12-23
相关资源
相似解决方案