iOS开发-OpenGLES 入门踩坑

OpenGL的变换

OpenGL ES 中有两套矩阵,都是4×4的GLfloat矩阵。一个叫 modelview matrix ,你大部分时间都会与之打交道。它是你用来对虚拟世界进行变换的矩阵。要对虚拟世界中的物体进行旋转,转移或尺寸变化,你都需要对此矩阵进行修改。

另一个矩阵用来创建根据设定的视口对世界坐标进行描述的二维表示。此矩阵称为 projection matrix 。在绝大部分时间内,你都不需要接触该矩阵。

从三维空间到二维平面,就如同用相机拍照一样,通常都要经历以下几个步骤 (括号内表示的是相应的图形学概念):
  第一步,将相机置于三角架上,让它对准三维景物(视点变换,Viewing Transformation)。
  第二步,将三维物体放在适当的位置(模型变换,Modeling Transformation)。
  第三步,选择相机镜头并调焦,使三维物体投影在二维胶片上(投影变换,Projection Transformation)。
  第四步,决定二维像片的大小(视口变换,Viewport Transformation)。
  这样,一个三维空间里的物体就可以用相应的二维平面物体表示了,也就能在二维的电脑屏幕上正确显示了。
 
 
变换后的x坐标范围是[-1, 1],y坐标范围是[-1, 1],z坐标范围是[0, 1](OpenGL略有不同,z值范围是[-1, 1])。
 

因为在光栅化之前,我们需要对z坐标的倒数进行插值(原因请参见Mathematics for 3D Game Programming and Computer Grahpics 3rd section 5.4),所以可以将z''写成z的一次表达式形式,如下

 
这个导致如果z坐标不在视锥体内的点,最后的z坐标范围会大于[-1, 1],导致不显示。
 

着色

Flat coloring(单色)

是通知OpenGL使用单一的颜色来渲染,OpenGL将一直使用指定的颜色来渲染直到你指定其它的颜色。

指定颜色的方法为

public abstract void glColor4f(float red, float green, float blue, float alpha)。

缺省的red,green,blue为1,代表白色。

Smooth coloring (平滑颜色过渡)

当给每个顶点定义一个颜色时,OpenGL自动为不同顶点颜色之间生成中间过渡颜色(渐变色)。
 
 
OpenGL 支持两种着色模式:单调着色(Flat)与平滑着色(smooth,也称Gouraud着色)。单调着色就是整个图元的颜色就是它的任何一个顶点的颜色,比如教程02中的红色三角形效果;平滑着色下每个顶点都是单独进行的,顶点之间的点是所有顶点颜色的均匀插值计算而得。
 
在 OpenGL 中,全局环境光的强度为 (0.2, 0.2, 0.2, 1.0),这弱弱的白色全局环境光确保即使没有额外的光源,场景中的物体依然是可见的。
 
 
 

gl_FragCoord(点我)

gl_FragCoord根据glsl language spec的解释为:
它是fragment shaders的输入变量,并持有该framgent的屏幕相对坐标(x, y, z, 1/w)
 
 

深度测试 

GL_POLYGON_OFFSET_FILL
The value of the offset is factor * DZ + bias, where DZ is a measurement of the change in z relative to the screen area of the polygon. The offset is added before the Depth Test is performed and before the value is written into the Depth Buffer.
在进行深度测试和写入深度缓冲区之前,会把深度值加上一个offset。offset的计算公式是factor * DZ + bias,其中factor和bias是由glPolygonOffset指定
深度缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 

CAEAGLLayer 

显示比例不对,屏幕大小只有320*480.
contentsScale属性定义了寄宿图的像素尺寸和视图大小的比例
 
 

GLSL限定符

限定符赋给变量特殊的含义:
const--     用于声明非可写的编译时常量变量
attribute-- 用于经常更改的信息,只可以在顶点着色器中使用
uniform--  用于不经常更改的信息,用于顶点着色器和片元着色器
varying--   用于从顶点着色器传递到片元着色器的插值信息
 
 

GLSL内建变量

Vertex Shader的输出数据时使用的内置变量:
vec4 gl_posotion;                用来设置顶点转换到屏幕坐标的位置,Vertex Shader一定要去更新这个数值
float gl_pointSize;                是启动PointSprite功能时,用来设置矩形大小的数值
vec4 gl_ClipVertex;              如果启用了Clip Plane功能,gl_ClipVertex可以放入用来与Clip Plane平面做测试用的位置
 
Fragment Shader的内置输出变量:
vec4 gl_FragColor;                               代表画面所要填入的颜色
vec4 gl_FragData[gl_MaxDrawBuffers];  用来填入画面的颜色,用在启用多个FrameBuffer时,调用gl_FragData填入画面颜色
vec4 gl_FrData填入画面颜色
vec4 gl_FragDepth;                             用来指定Z Buffer测试时所使用的Z值,这样就可以不通过顶点内插得到的Z值
 
 
GLSL
GLSL是严格的类型匹配,int和float不会默认互转;
着色语言定了三种级别的精度:lowp, mediump, highp。我们可以在 glsl 脚本文件的开头定义默认的精度。

precision mediump float;

注意,在片着色器,不会有默认的精度,所以如果没有上面这一句,会有编译错误哦;

 

 

OpenGL

写 OpenGL 代码时从前到后的顺序依次是:设定 viewport(视口变换),设定投影变换,设定视图变换,设定模型变换,在本地坐标空间描绘物体。而在前面为了便于理解做介绍时,说的顺序是OpenGL 中物体最初是在本地坐标空间中,然后转换到世界坐标空间,再到 camera 视图空间,再到投影空间。由于模型变换包括了本地空间变换到世界坐标空间,所以我们理解3D 变换是一个顺序,而真正写代码时则是以相反的顺序进行的,如果从左乘矩阵这点上去理解就很容易明白为什么会是反序的。
 
用数组表示 Matrix 又分为两种形式:行主序和列主序,它们在本质上是等价的,只不过是一个是右乘(行主序,矩阵放右边)和一个是左乘(列主序,矩阵放左边)。OpenGL 使用列主序矩阵,即列矩阵因此我们总是倒过来算的(左乘矩阵,变换效果是按从右向左的顺序进行): 投影矩阵 × 视图矩阵 × 模型矩阵 × 3D位置。
 
 
glUniform2fv 参数的count 是glsl里面vec2 vecArr[3]的vecArr数组个数,不是vec2的数组个数。
 

常犯错误

1,glUniform4fv和glUniform4f的区别?

带v表示是vec,赋值的是基础是向量;

2,glUniform 无效?

先调用glUseProgram(myprogram),再调用glUniform;

对于没有调用过的变量,glGetUniformLocation返回值-1;(编译器优化)

3, mediump 在片着色器必须带有这类修饰符

 片元语言没有默认的浮点数精度修饰符。因此,对于浮点数,浮点数向量和矩阵变量声明,要么声明必须包含一个精度修饰符,要不默认的精度修饰符在之前已经被声明过了。

学习的博客

 
原文地址:https://www.cnblogs.com/loying/p/5315733.html