OpenGL ES渲染流程总结

1. 大致流程

1.1 初始化上下文环境

在这里插入图片描述
代码实现:
EGLCore.h

#ifndef AVGRAPHICS_EGLCORE_H
#define AVGRAPHICS_EGLCORE_H

#include <EGL/egl.h>
#include <GLES3/gl3.h>

class EGLCore {
    
    
private:
    EGLDisplay mDisplay;
    EGLSurface mSurface;
    EGLContext mContext;

public:
    EGLCore();

    ~EGLCore();

    GLboolean buildContext(ANativeWindow *window, EGLContext sharedContext);

    void swapBuffer();

    void release();

    bool makeCurrent();

    EGLContext getCurrentContext();

    EGLSurface getCurrentSurface();
};

#endif //AVGRAPHICS_EGLCORE_H

EGLCore.cpp

#include "EGLCore.h"

#include <android/log.h>
#include <android/native_window.h>
#include <EGL/eglext.h>

#define LOG_TAG "EGLCore"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

EGLCore::EGLCore() : mDisplay(EGL_NO_DISPLAY), mSurface(EGL_NO_SURFACE),
                     mContext(EGL_NO_CONTEXT) {
    
    

}

EGLCore::~EGLCore() {
    
    
    mDisplay = EGL_NO_DISPLAY;
    mSurface = EGL_NO_SURFACE;
    mContext = EGL_NO_CONTEXT;
}

GLboolean EGLCore::buildContext(ANativeWindow *window, EGLContext sharedContext) {
    
    
    // 与本地窗口系统通信
    mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (mDisplay == EGL_NO_DISPLAY) {
    
    
        LOGE("eglGetDisplay failed: %d", eglGetError());
        return GL_FALSE;
    }

    if (sharedContext == NULL) {
    
    
        sharedContext = EGL_NO_CONTEXT;
    }

    GLint majorVersion;
    GLint minorVersion;
    if (!eglInitialize(mDisplay, &majorVersion, &minorVersion)) {
    
    
        LOGE("eglInitialize failed: %d", eglGetError());
        return GL_FALSE;
    }

    EGLConfig config;
    // 查找可用的 surface 配置
    EGLint numConfigs = 0;
    EGLint attribList[] = {
    
    
            EGL_RED_SIZE, 5,
            EGL_GREEN_SIZE, 6,
            EGL_BLUE_SIZE, 5,
            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_NONE
    };

    const EGLint surfaceAttr[] = {
    
    
            EGL_WIDTH, 1,
            EGL_HEIGHT,1,
            EGL_NONE
    };

    // 让 EGL 推荐匹配的 EGLConfig
    if (!eglChooseConfig(mDisplay, attribList, &config, 1, &numConfigs)) {
    
    
        LOGE("eglChooseConfig failed: %d", eglGetError());
        return GL_FALSE;
    }

    if (numConfigs < 1) {
    
    
        LOGE("eglChooseConfig get configs number less than one");
        return GL_FALSE;
    }

    // 创建渲染上下文(rendering context)
    GLint contextAttribs[] = {
    
    EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
    mContext = eglCreateContext(mDisplay, config, sharedContext, contextAttribs);
    if (mContext == EGL_NO_CONTEXT) {
    
    
        LOGE("eglCreateContext failed: %d", eglGetError());
        return GL_FALSE;
    }

    EGLint format = 0;
    if (!eglGetConfigAttrib(mDisplay, config, EGL_NATIVE_VISUAL_ID, &format)) {
    
    
        LOGE("eglGetConfigAttrib failed: %d", eglGetError());
        return GL_FALSE;
    }
    //离屏渲染
    if (window == NULL)
    {
    
    
        mSurface = eglCreatePbufferSurface(mDisplay, config, surfaceAttr);
    } else {
    
    
        ANativeWindow_setBuffersGeometry(window, 0, 0, format);

        // 创建 On-Screen 渲染区域
        mSurface = eglCreateWindowSurface(mDisplay, config, window, 0);
    }

    if (mSurface == EGL_NO_SURFACE) {
    
    
        LOGE("eglCreateWindowSurface failed: %d", eglGetError());
        return GL_FALSE;
    }

    // 把 EGLContext 和 EGLSurface 关联起来
    if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)) {
    
    
        LOGE("eglMakeCurrent failed: %d", eglGetError());
        return GL_FALSE;
    }

    LOGD("buildContext succeed");
    return GL_TRUE;
}

void EGLCore::swapBuffer() {
    
    
    eglSwapBuffers(mDisplay, mSurface);
}

void EGLCore::release() {
    
    
    eglDestroySurface(mDisplay, mSurface);
    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(mDisplay, mContext);
}

bool EGLCore::makeCurrent() {
    
    
    return eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
}

EGLContext EGLCore::getCurrentContext() {
    
    
    return mContext;
}

EGLSurface EGLCore::getCurrentSurface() {
    
    
    return mSurface;
}

1.2 初始化纹理对象

在这里插入图片描述

void createTexture(GLuint &texId)
{
    
    
    glGenTextures(1, &texId);
    glBindTexture(GL_TEXTURE_2D, texId);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glBindTexture(GL_TEXTURE_2D, GL_NONE);
}

1.3 初始化着色器

在这里插入图片描述

//
// Created by zzh on 2018/5/11 0011.
//

#include "glutil.h"

#include <android/log.h>
#include <malloc.h>
#include <cstring>
#include <math.h>

#define LOG_TAG "glutil"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

std::string *readShaderFromAsset(AAssetManager *manager, const char *fileName) {
    
    
    AAssetDir *dir = AAssetManager_openDir(manager, "");
    const char *file = nullptr;
    std::string *result = new std::string;
    while ((file = AAssetDir_getNextFileName(dir)) != nullptr) {
    
    
        if (strcmp(file, fileName) == 0) {
    
    
            AAsset *asset = AAssetManager_open(manager, file, AASSET_MODE_STREAMING);
            char buf[1024];
            int nb_read = 0;
            while ((nb_read = AAsset_read(asset, buf, 1024)) > 0) {
    
    
                result->append(buf, (unsigned long) nb_read);
            }
            AAsset_close(asset);
            break;
        }
    }
    AAssetDir_close(dir);
    return result;
}

GLuint loadProgram(const char *vertexShaderStr, const char *fragmentShaderStr) {
    
    
    GLuint program = glCreateProgram();
    if (program == 0) {
    
    
        LOGE("create program failed");
        checkGLError("glCreateProgram");
        return 0;
    }

    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderStr);
    GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderStr);
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);

    // 链接
    glLinkProgram(program);

    GLint linked;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    if (!linked) {
    
    
        GLint infoLen = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
    
    
            char *infoLog = (char *) malloc(sizeof(char) * infoLen);
            glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
            LOGE("loadProgram failed: %s", infoLog);
            free(infoLog);
        }

        glDeleteProgram(program);
        return 0;
    }

    return program;
}

GLuint loadShader(GLenum type, const char *shaderSrc) {
    
    
    GLuint shader = glCreateShader(type);
    if (shader == 0) {
    
    
        return 0;
    }

    // 加载 shader 源码
    glShaderSource(shader, 1, &shaderSrc, nullptr);

    // 编译
    glCompileShader(shader);

    // 检查编译状态
    GLint compiled;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if (!compiled) {
    
    
        GLint infoLen = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
    
    
            char *infoLog = (char *) malloc(sizeof(char) * infoLen);
            glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
            LOGE("load %s shader failed: \n%s", type == GL_VERTEX_SHADER ? "vertex" : "fragment",
                 infoLog);
            free(infoLog);
        }

        glDeleteShader(shader);
        return 0;
    }

    return shader;
}

void checkGLError(const char *pGLOperation) {
    
    
    for (GLint error = glGetError(); error; error = glGetError())
    {
    
    
        LOGE("GLUtils::CheckGLError GL Operation %s() glError (0x%x)\n", pGLOperation, error);
    }
}

1.4 初始化显卡执行程序

在这里插入图片描述

GLuint loadProgram(const char *vertexShaderStr, const char *fragmentShaderStr) {
    
    
    GLuint program = glCreateProgram();
    if (program == 0) {
    
    
        LOGE("create program failed");
        checkGLError("glCreateProgram");
        return 0;
    }

    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderStr);
    GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderStr);
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);

    // 链接
    glLinkProgram(program);

    GLint linked;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    if (!linked) {
    
    
        GLint infoLen = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
    
    
            char *infoLog = (char *) malloc(sizeof(char) * infoLen);
            glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
            LOGE("loadProgram failed: %s", infoLog);
            free(infoLog);
        }

        glDeleteProgram(program);
        return 0;
    }

    return program;
}

1.5 渲染

在这里插入图片描述

void drawToView(GLuint currentTexId, GLfloat *cameraMatrix) {
    
    
    // 启用透明
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
	glViewport(0, 0, mRecordWidth, mRecordHeight);
    glUseProgram(mProgram);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexOes);
    glUniform1i(mTexLoc, 0);
    glUniformMatrix4fv(mMatrixLoc, 1, GL_FALSE, cameraMatrix);

    glEnableVertexAttribArray(ATTRIB_POSITION);
    glVertexAttribPointer(ATTRIB_POSITION, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, 0, VERTICES);

    glEnableVertexAttribArray(ATTRIB_TEX_COORD);
    glVertexAttribPointer(ATTRIB_TEX_COORD, TEX_COORD_POS_SIZE, GL_FLOAT, GL_FALSE, 0,
                          TEX_COORDS);
                          
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableVertexAttribArray(ATTRIB_POSITION);
    glDisableVertexAttribArray(ATTRIB_TEX_COORD);
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);

1.7 释放资源

if (mProgram)
{
    
    
	glDeleteProgram(mProgram);
}

if (mTexOes)
{
    
    
    glDeleteTextures(1, &mTexOes);
}
if (mWindow) {
    
    
   ANativeWindow_release(mWindow);
    mWindow = nullptr;
}
eglDestroySurface(mDisplay, mSurface);
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);

猜你喜欢

转载自blog.csdn.net/wyw0000/article/details/129771523