OpenGL ES zero basic entry two drawing triangles

foreword

in the previous

1. Configure the context EAGLContext (context) for OpenGL ES rendering
Second, configure the rendering layer layer (rendering layer)
Third, configure the render buffer and frame buffer (renderBuffer and frameBuffer)
4. Shader Shader (user vertextShader and framentShader)

Coded on the basis of the " OpenGL ES Create Window " code. As mentioned above, the programmable pipeline is implemented by writing script files in shader language. These script files are equivalent to C source code. If there is source code, it needs to be compiled and linked. Therefore, the corresponding compiler and linker are required. The shader object and the program object are equivalent to Compiler and linker. The shader object is loaded into the source code, and then compiled into object form (just like C source code is compiled into an .obj file). The compiled shader can be assembled into the program object. Each program object must be equipped with two shader objects: a vertex shader, a fragment shader, and then the program object is linked into an "executable file", which can be used in the render. It's up to the "executable".
2

3

After completing the configuration of Figures 2 and 3, start to create vertex shaders and fragment shaders, and create shader programs to link vertex and fragment shaders

4

1. First, we add a new class OpenGLESUtils to the project and let it inherit from NSObject

The content of the OpenGLESUtils.h file is as shown below. The content of the
5
OpenGLESUtils.m file is:

//
//  OpenGLESUtils.m
//  OpenGL_ Triangle
//
//  Created by Mr_zhang on 17/4/7.
//  Copyright © 2017年 Mr_zhang. All rights reserved.
//

#import "OpenGLESUtils.h"

@implementation OpenGLESUtils
+ (GLuint)loadShaderProgram:(GLenum)type withFilepath:(NSString *)shaderFilepath
{
    NSError *error;
    NSString *shaderString = [NSString stringWithContentsOfFile:shaderFilepath encoding:NSUTF8StringEncoding error:&error];
    if (!shaderString)
    {
        NSLog(@"Error: loading shader file:%@  %@",shaderFilepath,error.localizedDescription);
        return 0;
    }
    return [self loadShader:type withString:shaderString];
}

+ (GLuint)loadShader:(GLenum)type withString:(NSString *)shaderString
{
    GLuint shader = glCreateShader(type);
    if (shader == 0)
    {
        NSLog(@"Error: failed to create shader.");
        return 0;
    }
    // Load the shader soure (加载着色器源码)
    const char *shaderStringUTF8 = [shaderString UTF8String];
    // 要编译的着色器对象作为第一个参数,第二个参数指定了传递的源码字符串数量,第三个着色器是顶点的真正的源码,第四个设置为NULL;
    glShaderSource(shader, 1, &shaderStringUTF8, NULL);
    // 编译着色器
    glCompileShader(shader);

    // 检查编译是否成功
    GLint success;
    GLchar infoLog[512];
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        GLint infolen;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infolen);

        if (infolen > 1)
        {
            char *infolog = malloc(sizeof(char) * infolen);
            glGetShaderInfoLog(shader, infolen, NULL, infoLog);
            NSLog(@"compile faile,error:%s",infoLog);
            free(infolog);
        }

        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

/**
 创建顶点着色器和片段着色器

 @param vertexShaderFilepath 顶点着色器路径
 @param fragmentShaderFilepath 片段着色器路径
 @return 链接成功后的着色器程序
 */
+ (GLuint)loadProgram:(NSString *)vertexShaderFilepath withFragmentShaderFilepath:(NSString *)fragmentShaderFilepath
{
    // Create vertexShader (创建顶点着色器)
    GLuint vertexShader = [self loadShaderProgram:GL_VERTEX_SHADER withFilepath:vertexShaderFilepath];
    if (vertexShader == 0)
        return 0;

    // Create fragmentShader (创建片段着色器)
    GLuint fragmentShader = [self loadShaderProgram:GL_FRAGMENT_SHADER withFilepath:fragmentShaderFilepath];
    if (fragmentShader == 0)
    {
        glDeleteShader(vertexShader);
        return 0;
    }

    // Create the program object (创建着色器程序)
    GLuint shaderProgram = glCreateProgram();
    if (shaderProgram == 0)
        return 0;
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    // Link the program (链接着色器程序)
    glLinkProgram(shaderProgram);

    // Check the link status (检查是否链接成功)
    GLint linked;
    GLchar infoLog[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linked);
    if (!linked)
    {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        glDeleteProgram(shaderProgram);
        NSLog(@"Link shaderProgram failed");
        return 0;
    }


    // Free up no longer needed shader resources (释放不再需要的着色器资源)
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return shaderProgram;
}
@end

There are two class methods in the utility class GLESUtils to follow the shader script string or shader script file to create a shader, then load it, and compile it. Each step is described in detail below.
1) Create/delete shader
The function glCreateShader is used to create a shader. The parameter GLenum type represents the shader type we want to deal with, which can be GL_VERTEX_SHADER or GL_FRAGMENT_SHADER, representing vertex shader or fragment shader respectively. It returns a handle to the created shader object.
The function glDeleteShader is used to destroy the shader, and the parameter is the shader object handle returned by glCreateShader.

2) Load the shader
function glShaderSource to provide shader source code to the specified shader. The first parameter is the handle of the shader object; the second parameter indicates the number of shader source strings; the third parameter is the shader source string array; the fourth parameter is an int array, indicating that each source string should be If the parameter is NULL, it means that the source string is assumed to be \0-terminated. Read the content of the string and specify \0 as the source code. If the parameter is not NULL, read each source string. The first length (length corresponding to each string) length characters are used as source code.

3) Compile shader
function glCompileShaderUsed to compile the specified shaderobject, which will compile the source code stored in the shader object. We can query the information of the object through functions glGetShaderiv, shadersuch as querying the compilation status in this example, and we can also query GL_DELETE_STATUS,GL_INFO_LOG_STATUS, GL_SHADER_SOURCE_LENGTHand GL_SHADER_TYPE. Here we query the compilation status. If it returns 0, it means that there is an error in the compilation, and the error information will be written into the info log. We can query the info log to get the error information.

2. Write the shader script

The interface provided by OpenGLESUtils allows us to use two methods: script string or script file to provide shader source code, usually using script file method has more flexibility. (The Cocos2D source code provides a lot of script strings to deal with some common situations, and interested students can check it out). Here, we use the script file method. Follow the following two steps to create, create vertex shader suffix using .vsh (ie vertexShader), fragment shader suffix using .fsh (ie fragmentShader).

6

7

1) Add vertex shader script vertexShader.vsh

vertextShader vertex shader script content:

attribute vec4 vPosition; 

void main(void)
{
    gl_Position = vPosition;
}

The source code of the vertex shader script is very simple, if you read the previous introduction carefully, it will be clear at a glance. The attribute vPosition represents the position information of type vec4 input from the application, and outputs the built-in vary variable vPosition. Note: The default precision is used here.

2) Add the fragment shader script fragmentShader.fsh

fragmentShader fragment shader script content:

precision mediump float;

void main()
{
    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}

The source code of the fragment coloring script is also very simple. As mentioned earlier, the fragment coloring can either define the default precision by itself, or add a precision descriptor before each variable. Here, the precision of the custom float is mediump. Then assign yellow to the built-in output variable gl_FragColor

3. Create shader program program, assemble shader, link program, use program

8

With the previous introduction, the above code is easy to understand. First, we create, load and compile vertex shaders and fragment shaders from the previously created script by the helper method provided by GLESUtils; then we create a program, assemble the vertex shader and fragment shader into the program object, and then use glLinkProgram to assemble the The shaders are linked, so that the two shaders can work together. Note: The linking process will check the linkability of the shader, that is to say, the variables with the same name must have the same name and the same type, and the number of variables cannot exceed the range. How we check the shader compilation is the same as the linking of the program. If everything is correct, then we can call glUseProgram to activate the program object and use it in render. By calling glGetAttribLocation we get the variable vPosition defined in the shader in the slot of the program, through which we can operate on vPosition.

5. Rendering

9

6. Compile and run

Compile and run, you will see a red triangle displayed in the center of the screen. Any idea why it's yellow? That's because the program also links the fragment shader, and in the fragment shader script file, we specify the value of gl_FragColor as yellow vec4(1.0, 1.0, 0.0, 1.0).

10

Summarize

After the two chapters of " OpenGL ES Creating Window " and " OpenGL ES Zero Basic Introduction--(2) Drawing Triangles ", we have a general understanding of the basic use of openGL, including setting CAEAGLLayer properties, creating EAGLContext, creating and using renderbuffer and framebuffer, Learn about the OpenGL ES rendering pipeline, create and use shaders, create and implement programs, and draw with vertex arrays. The process has gone through, let's enter the specific technical fields of OpenGL ES.
The source code of this article is available here: https://github.com/476455183/OpenGLES

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324965710&siteId=291194637