JCV AR SDK(Effects)Windows開発マニュアル
  • 1.環境準備
  • 2.開発の事前準備
  • 3.OpenCLの利用
  • 4.SDK API の使用
  • 5.ファイルの説明
  • 6.画像の回転とミラーリング
Powered by GitBook
On this page
  • 3.1 OpenGLの初期化
  • 3.2 OpenGLレンダリング効果の利用
  • 3.3 OpenGLのクローズ
Export as PDF

3.OpenCLの利用

美顔、ステッカー、フィルターおよびメークアップ効果の実現にOpenGLの利用が必要です。

3.1 OpenGLの初期化

  1. opengl_check.exeを実行し,システムおよびGPUドライバーのopengl32.dllバージョンを確認する

  2. opengl_checkが失敗の場合は、Mesa版のopengl32.dllを用いてOpenGLの初期化を行う

  3. opengl_checkが成功の場合は、glfwライブラリを初期化し、glfwウィンドウを作成する。glfwウィンドウ作成が失敗の場合は、Mesa版のopengl32.dllを用いてOpenGLの初期化を行う

  4. glfwウィンドウの作成が成功したら,gl3wの初期化を行う。gl3wの初期化が失敗シた場合は,

    1. Mesa版のopengl32.dllを用いてOpenGLの初期化を行う

  5. OpenGLのバージョンを確認し,2.1以下またはOpenGLSLバージョンは1.2以下の場合は,エラーで返す

OpenGL初期化の詳細はhelper_opengl.hに参照してください。

inline bool InitGL() {
    glfwSetErrorCallback(PrintglfwError);
    bool bGLInited = false;
    if (!window) {
        try {
            int err = 0;
#ifdef WIN32 
if (opengl_check()) {
#endif 
    err = glfwInit();
    if (!err) {
        throw "OpenGL: fail to create window context!";
    }
    // Create a offscream mode window and its OpenGL context
    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
    window = glfwCreateWindow(10, 10, "hello", NULL, NULL);
#ifdef WIN32 
} 
#endif 
            if (!window) {
#ifdef WIN32 
                MesaOpenGL();
#else 
                throw "OpenGL: fail to init glfw";
#endif 
}
else { 
                // Make the window's context current
                glfwMakeContextCurrent(window);
#ifdef WIN32 
                err = gl3wInit();
                if (err != GL3W_OK) {
                    MesaOpenGL();
                }
#else 
                glewExperimental = GL_TRUE;
                err = glewInit();
                if (err != GLEW_OK) {
                    throw "OpenGL: fail to init glew\n";
                }
#endif 
} 
            const unsigned char* glVer = glGetString(GL_VERSION);
            const unsigned char* glslVer = glGetString(GL_SHADING_LANGUAGE_VERSION);
            float OpenglVersion = 0.f, GLSLVersion = 0.f;
            StringTo((char*)glVer, OpenglVersion);
            StringTo((char*)glslVer, GLSLVersion);
            fprintf(stdout, "Renderer: %s\n", glGetString(GL_RENDERER));
            fprintf(stdout, "OpenGL version supported %s\n", glGetString(GL_VERSION));
            fprintf(stdout, "OpenGLSL version supported %s\n",
            glGetString(GL_SHADING_LANGUAGE_VERSION));
            if (OpenglVersion <2.1f || GLSLVersion < 1.2f) {
                throw "OpenGL version is too old, we only support above opengl2.1 and glsl1.2.0";
            }
            bGLInited = true;
        }
        catch (std::exception &e){
            fprintf(stderr, "%s\n", e.what());
        }
        catch (const char* e){
            fprintf(stderr, "%s\n", e);
        }
        catch (...) {
            return false;
} } 
 else {
        GLFWwindow* curCtx = glfwGetCurrentContext();
        if (!curCtx)
            glfwMakeContextCurrent(window);
        bGLInited = true;
} 
    return bGLInited;
}

Mesa版opengl32.dllによるOpenGLの初期化は以下の通り。

  1. Mesa版opengl32.dllをロードする

  2. glfwライブラリの初期化を行い,glfwウィンドウを作成し,gl3wの初期化を行う

opengl32.dllと区別するため、Mesa版opengl32.dllはMesaOpengl32.dllに命名されています。MesaOpenGLが利用されると、自動的にopengl32.dllに名前が変更されます。

inline void MesaOpenGL() {
    unInitGL();
    char work_path[_MAX_PATH] = { 0 };
    GetModuleFileName(NULL, work_path, _MAX_PATH);
    std::string str_work_path(work_path);
    str_work_path = str_work_path.substr(0, str_work_path.find_last_of('\\') + 1);
#ifdef _WIN64
    str_work_path = str_work_path + "..\\external\\libs\\windows-x86_64";
#else
    str_work_path = str_work_path + "..\\external\\libs\\windows-x86";
#endif
    SetDllDirectory(str_work_path.data());
    std::string rename_path = str_work_path + "\\MesaOpengl32.dll";
    str_work_path = str_work_path + "\\opengl32.dll";
    // judge opengl32.dll exist or not
    if (access(str_work_path.data(), 0) == -1) {
        // rename and SetDllDirectory are must, because glfw loadlibrary("opengl32.dll")
        if (rename(rename_path.data(), str_work_path.data()) != 0)
            throw "MESA OpenGL: fail to rename opengl32.dll!";
} 
    GLenum err = false;
    err = glfwInit();
    if (!err) {
        throw "MESA OpenGL: fail to init glfw";
    }
    // Create a offscream mode window and its OpenGL context
    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
    window = glfwCreateWindow(10, 10, "hello", NULL, NULL);
    if (!window) {
unInitGL(); 
        throw "MESA OpenGL: fail to create window context!";
    }
    // Make the window's context current
    glfwMakeContextCurrent(window);
    //str_work_path = str_work_path + "\\opengl32.dll";
    err = gl3wInitWithPath(str_work_path.data());
    if (err != GL3W_OK) {
        fprintf(stderr, "gl3wInit error: %d\n", err);
        throw "MESA OpenGL: fail to init gl3w\n";
    }
} 

3.2 OpenGLレンダリング効果の利用

3.2.1 テクスチャバンディング

画像を処理する前に、テクスチャにバインドする必要があります。 テクスチャのバインド処理は、次のように行います。

  1. テクスチャのインデックスを生成する。

  2. テクスチャインデックスがテクスチャオブジェクトにバインドされていない場合、テクスチャインデックスをテクスチャユニットにバインドし、glTexImage2Dを使用して2Dテクスチャを生成してバインドを完了させます。

  3. 後続のビデオフレームでは、glTexSubImage2Dを使用して既存のテクスチャを変更します。

  4. ビデオ解像度が変更された場合は、手順2へ戻ります。

static GLboolean BindTexture(uchar *buffer, int width, int height, GLuint& texId) {
    if (!glIsTexture(texId) || (gTextures.find(texId) == gTextures.end())) {
        glGenTextures(1, &texId);
        std::vector<int> tmp(2);
        tmp[0] = width;
        tmp[1] = height;
        gTextures[texId] = tmp;
    }
    int &OldW = gTextures[texId][0];
    int &OldH = gTextures[texId][1];
    if (!glIsTexture(texId) || (OldW != width) || (OldH != height)) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texId);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
            GL_UNSIGNED_BYTE, buffer);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        OldW = width;
        OldH = height;
    }
    else if(buffer) {
        glBindTexture(GL_TEXTURE_2D, texId);
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA,
         GL_UNSIGNED_BYTE, buffer);
    }
    bool tmp = glIsTexture(texId);
    GLenum error = glGetError();
    if (error != GL_NO_ERROR) {
        printf("error : %d\n", error);
        //  result = RESULT_TEXTURE_ERR;
        error = GL_NO_ERROR;
        return false;
    } 
    return true;
}

process textureインターフェースを使用して、効果をレンダリングする前に入力と出力のテクスチャーをバインドします。

BindTexture(rgba_frame.data, rgba_frame.cols, rgba_frame.rows, texture_src);
BindTexture(NULL, rgba_frame.cols, rgba_frame.rows, texture_dst);

process bufferを使用したエフェクトのレンダリングでは、テクスチャのバインディングは不要で、関数内部で行われます。

3.2.2 エフェクトレンダリング

この効果はOpenGLでprocess textureインターフェイスまたはprocess bufferインターフェイスを使って、次のように描画されます。他の効果については4.4を参照してください:

//process_texture
ret = st_mobile_beautify_process_and_output_texture(handle_beautify, texture_src,
                                                    read_frame.cols, read_frame.rows,
                                                    ST_CLOCKWISE_ROTATE_0,
                                                    &human_action,texture_dst,
                                                    temp_frame.data,ST_PIX_FMT_BGR888,
                                                    NULL);
//process_buffer
ret = st_mobile_beautify_process_buffer(handle_beautify, temp_frame.data,
                                        ST_PIX_FMT_BGR888, temp_frame.cols,
                                        temp_frame.rows, temp_frame.step,
                                        ST_CLOCKWISE_ROTATE_0, &human_action,
                                        temp_frame.data, ST_PIX_FMT_BGR888, NULL);

3.3 OpenGLのクローズ

プログラムの終了時には、glfw が作成したウィンドウを閉じて、glfwを終了させる必要があります。

inline void unInitGL() {
    if (window)
        glfwDestroyWindow(window);
    window = nullptr;
    glfwTerminate();
}
Previous2.開発の事前準備Next4.SDK API の使用

Last updated 2 years ago