uniform和attribute区别

简单对比一下

attribute,可以理解为顶点的属性,表示顶点的输入数据,只在顶点着色器中使用

uniform,可以简单理解为向着色器中传递matrix等数据,这个是在着色器中是只读的,并且在两个着色器中都可以使用

使用上的区别:

1 获取指针,分别使用glGetAttribLocation和glGetUniformLocation方法

2 设置值时,分别使用glVertexAttribPointer和glUniformMatrix4fv,注意使用glVertexAttribPointer和glEnableVertexAttribArray需要配合使用,而glUniformMatrix4fv无此限制

3 使用矩阵时,一般先LoadIdentity,然后进行平移,旋转和缩放,glDrawElements与顶点着色器可以理解为一一对应,也就是说,可以设置matrix1,传入shader的modelView中,然后glDrawElements,接下来可以再设置matrix2,再传入modelView中,再进行glDrawElements

opengl iOS创建OpenGL环境绘制一个简单三角形

EAGLView创建要点

1 EAGLView的layer为CAEAGLLayer,设置kEAGLDrawablePropertyRetainedBacking和kEAGLDrawablePropertyColorFormat属性

1
2
3
4
5
6
7
8
9
- (void)setupLayer{

CAEAGLLayer* layer = (CAEAGLLayer*)self.layer;

layer.opaque = YES;

layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:@(NO), kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
}

2 创建EAGLContext

1
_context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];

3 加载着着色器程序,获取到着色器变量的索引,此过程,大致可分为:

a获取着色器源文件,创建shader,编译

b创建program,attachShader,link,useProgram

c从program,通过名字获取着色器中变量的索引(后续可以向着色器中传递参数)

这里有一点需要注意,此过程的前提,一定是已经设置了EAGLContext的currentContext

4 每一帧绘制流程

在外面使用CADisplayLink来控制播放帧率,每一帧的绘制流程就是

1
2
3
4
5
6
7
8
- (void)drawFrame{

[_eaglView setFramebuffer];

[_eaglView draw];

[_eaglView presentFramebuffer];
}

5 关于frameBuffetObject的创建和释放

前提:context确保设置

流程大致是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
- (void)createBuffer{

[self checkContext];

glGenRenderbuffers(1, &_colorRenderBuffer);

glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);

[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

glGenFramebuffers(1, &_frameBuffer);

glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, _colorRenderBuffer);
}

- (void)deleteBuffer{

[self checkContext];

glDeleteRenderbuffers(1, &_colorRenderBuffer);

_colorRenderBuffer = 0;

glDeleteFramebuffers(1, &_frameBuffer);

_frameBuffer = 0;
}

- (void)setFramebuffer
{
if ([self checkContext])
{
if (!_frameBuffer){
[self createBuffer];
}
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
}
}

- (BOOL)presentFramebuffer
{
BOOL success = FALSE;

if ([self checkContext])
{
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);

success = [_context presentRenderbuffer:GL_RENDERBUFFER];
}
return success;
}

6 关于绘制三角形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)draw{
//设置背景颜色为绿色
glClearColor(0, 1.0, 0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
//设置管区域大小
glViewport(0, 0, self.frame.size.width, self.frame.size.height);

GLfloat vertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f };
//设置着色器中的vPositon
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
//使上一步的设置生效
glEnableVertexAttribArray(_positionSlot);
//绘制三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
}

CALayer opaque

颜色合成公式

R = S + D * ( 1 – Sa )

20130819170332968

其中,R表示混合结果的颜色,S是源颜色(位于上层的红色图层一),D是目标颜色(位于下层的绿色图层二),Sa是源颜色的alpha值,即透明度。公式中所有的S和D颜色都假定已经预先乘以了他们的透明度。

设置opaque相当于是设置了Sa=1,此时R = S,省去了GPU的计算

注意:设置opaque为YES时,要确保alpha为1.0f,否则结果不可预期

CALayer属性positon和anchor

CALayer 的frame,bounds, position和anchor

frame描述的是在父layer上的坐标和尺寸

bounds是类似于View的bounds

anchor描述的是做动画时,比如旋转时的中心点,以某个点旋转,默认时(0.5,0.5)左上点是(0,0),右下点是(1,1)

position描述的是anchor的在父layer的坐标

举例来说,一个View的Frame是(40,40,100,100)

那么layer的frame是(40,40,100,100)

bound是(0,0,100,100)

position是:(140,140)

position计算:

pos.x = origin.x + anchor.x*size.with

pos.y = origin.y + anchor.y*size.height

如果想修改anchor,一定要同时修改position,才能保证位置不变,否则,单独修改position或者anchor,根据上面公式会导致layer位置发生变化

如果想修改anchor,而不影响layer移动,只需修改完成后,再设置一次layer的frame即可

CGRect oldFrame = _redView.frame;
_redView.layer.anchorPoint = CGPointMake(0.5, 1);
_redView.frame = oldFrame;

注意,position并不适用这一点