OpenGLES之三角形(二)

2019/07/02 OpenGLES

在上一篇,其实我们什么都没做,就只是设置OpenGLES 的基本配置,这一篇我们回来绘制一个三角形,三角形是OpenGLES 中的基本图元。

前面说到,OpenGLES 是一个状态机器,这意味着在一个程序中设置了一个配置值后,这个值会一直保持,直到程序修改了这个值。上下文中的信息可能会被保存在CPU所控制的内存中,也可能会被保存在GPU所控制的内存中。OpenGLES会按需在两个内存区域之间复制信息,知道何时复制有助于程序的优化。

OpenGLEs 上下文会跟踪用于渲染的帧缓存。上下文还会跟踪用于集合数据、颜色等的缓存,上下文会决定是否使用某些功能,比如文理和灯光。

创建颜色缓存

- (void)setupRenderBuffer {
    glGenRenderbuffers(1, &_colorRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
    // 为 color renderbuffer 分配存储空间
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];
}

每个OpenGL 程序至少有一个缓冲区(color buffer,depth buffer,stencil buffer)

帧缓存

GPU需要知道应该在内存中的哪个位置存储渲染出来的2D图像像素数据。就像为GPU提供数据的缓存一样,接收渲染结果的缓冲区就叫做帧缓存(frame buffer)。程序会想任何其他种类的缓存一样生成、绑定、删除帧缓存。但是帧缓存不需要初始化,因为渲染指令会在适当的时候替换缓存的内容。帧缓存会在被绑定的时候隐式开启,同时OpenGLES会自动的根据特定平台的硬件配置和功能来设置数据的类型和偏移。

可以同时存在很多帧缓存,并且可以通过OpenGL ES 让GPU把渲染结果存储到任意数量的帧缓存中。但是屏幕显示像素要受到保存在前帧缓存(front frame buffer)的特定帧缓存中的像素颜色元素的控制。程序和操作系统很少会直接渲染到前帧缓存中。因为那样会让用户看到正在渲染的还没有渲染完成的图像。相反,程序和操作系统会把渲染结果保存到后帧缓存在内的其他帧缓存中。当渲染后的后帧缓存包含一个完成的图像时,前帧缓存与后帧缓存几乎会瞬间切换。后帧缓存会变成新的前帧缓存,同时旧的前帧缓存会变成新的后帧缓存。

创建帧缓存

- (void)setupFrameBuffer {
    glGenRenderbuffers(1, &_framebuffer);
    // 设置为当前 framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
    // 将 _colorRenderBuffer 装配到 GL_COLOR_ATTACHMENT0 这个装配点上
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
}

设置shader 程序

- (void)setupProgram {
    NSString *VertexFile = [[NSBundle mainBundle] pathForResource:@"VertexFile.glsl" ofType:nil];
    NSString *FragmentFile = [[NSBundle mainBundle] pathForResource:@"FragmentFile.glsl" ofType:nil];
    
    _programHandle0 = [OpenGLUtils programWithVertexFile:VertexFile fragmentFile:FragmentFile];
    glUseProgram(_programHandle0);//激活shader 程序
    
    _positionSlot = glGetAttribLocation(_programHandle0, "vPosition");//在ES3.0 中有另一种方式
    _vertexColorSlot = glGetAttribLocation(_programHandle0, "color");
    glEnableVertexAttribArray(_positionSlot);
    glEnableVertexAttribArray(_vertexColorSlot);
    
}

其中,这个program 可以理解为shader 程序的一个句柄,拿到这个句柄后,我们就可以获取program 中的一些变量值,就可以往shader程序中传输数据。

Vertex Shader

attribute vec3 vPosition;
attribute vec3 color;
varying vec3 outColor;

void main()
{
    gl_Position = vec4(vPosition,1.0);
    outColor = color;
}

在这里我们什么都没有做,仅仅只是把顶点坐标和顶点颜色值传输给OpenGL, 其中:Vertex shader在ES3.0 中

#version 300 es

layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec3 inColor;
out vec3 color;
void main()
{
    gl_Position = vec4(vPosition,1.0);
    color = inColor;
}

Fragment Shader

precision mediump float;
varying vec3 color;
void main()
{
    gl_FragColor = vec4(color, 1.0);
}

在ES3.0 中

//指定版本号和精度
#version 300 es
precision mediump float;
out vec4 fragColor;

//从顶点着色器传来的输入变量(名称相同、类型相同)
in vec3 color;
void main()
{
    //在通过out字段将颜色输出
    fragColor = vec4(color,1.0);
}

设置顶点数据

GLfloat vertices[] = {
        0.0f,  0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f,  -0.5f, 0.0f 
        };
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices );//填充数据
glEnableVertexAttribArray(_positionSlot);

设置顶点颜色

//颜色数据
    static GLfloat colors[] = {
        0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f
    };
 glVertexAttribPointer(_vertexColorSlot, 3, GL_FLOAT, GL_FALSE, 0, colors);
 glEnableVertexAttribArray(_vertexColorSlot);

而在OpenGLES3.0 中填充数据也就变成了:

GLfloat vertices[] = {
        0.0f,  0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f,  -0.5f, 0.0f 
        };
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices );//填充数据
glEnableVertexAttribArray(0);
static GLfloat colors[] = {
        0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f
    };
 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, colors);
 glEnableVertexAttribArray(1);

不再需要使用

glGetAttribLocation(_programHandle0, "vPosition");
_vertexColorSlot = glGetAttribLocation(_programHandle0, "color");

这里只是提一下,有空后面再讲。

看效果图:

也可以自己尝试着绘制其他图形,如果是立体图,就需要用到3D变换,平移、旋转,缩放。马上就会讲到。

最后,附上我自己在学习过程中的源码:

Tutorial02

参考:

[1]:OpenGL ES 应用开发实践指南iOS卷

[2]:https://blog.csdn.net/kesalin/article/details/8221393

[3]:https://www.jianshu.com/p/2c41ac4f4031

Search

    Post Directory