栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【OpenGL ES】构建可移植、易扩展的代码书写结构

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【OpenGL ES】构建可移植、易扩展的代码书写结构

目录

【OpenGL ES】构建可移植、易扩展的代码书写结构

JAVA语言

分离GLSL语言创建工具类传入环境 C++语言

分离GLSL语言创建工具类传入环境 总结
不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵!

【OpenGL ES】构建可移植、易扩展的代码书写结构

MainActivity

package com.example.openglndk;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

//JNI类
public class MainActivity extends AppCompatActivity {
    private GLSurfaceView mGLSurfaceView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mGLSurfaceView = new GLSurfaceView(this);
        setContentView(mGLSurfaceView);
        //设置版本ES 3.0
        mGLSurfaceView.setEGLContextClientVersion(3);
        //设置渲染器  JAVA版本
        GLSurfaceView.Renderer renderer = new MyRenderer(this);
        //设置渲染器  C++版本
//        GLSurfaceView.Renderer renderer = new WaveRenderer(this);
        mGLSurfaceView.setRenderer(renderer);
    }
}
JAVA语言 分离GLSL语言

创建assets文件夹

在assets文件夹中创建glsl文件

创建工具类

工具类中有三个方法。

readFileFromAssets

    public static String readFileFromAssets(Context context, String fileName) {
        //初始化,关流判断
        InputStream inputStream = null;
        Reader reader = null;
        BufferedReader bufferedReader = null;
        //底层更快,性能更好
        StringBuilder shaderCode = new StringBuilder();
        try {
            //得到资源中的asset数据流
            inputStream = context.getResources().getAssets().open(fileName);  //字节输入流
            reader = new InputStreamReader(inputStream);// 字符流
            bufferedReader = new BufferedReader(reader); //缓冲流
            String temp;
            //从第一行数据读取到最后一行为止
            while ((temp = bufferedReader.readLine()) != null) {
                //连起来,成为字符串
                shaderCode.append(temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //先打开的后关闭,后打开的先关闭
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return shaderCode.toString();
    }

LoadShader

    public static int LoadShader(int type, String shaderCode) {
        //创建一个着色器
        final int shaderId = GLES30.glCreateShader(type);
        if (shaderId != 0) {
            //加载到着色器
            GLES30.glShaderSource(shaderId, shaderCode);
            //编译着色器
            GLES30.glCompileShader(shaderId);
            //检测状态
            final int[] compileStatus = new int[1];
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
            if (compileStatus[0] == 0) {
                String logInfo = GLES30.glGetShaderInfoLog(shaderId);
                System.err.println(logInfo);
                //创建失败
                GLES30.glDeleteShader(shaderId);
                return 0;
            }
            return shaderId;
        } else {
            //创建失败
            return 0;
        }
    }

linkProgram

    public static int linkProgram(int vertexShader, int fragmentShader) {
        final int program = GLES30.glCreateProgram();
        if (program != 0) {
            //将顶点着色器加入到程序
            GLES30.glAttachShader(program, vertexShader);
            //将片元着色器加入到程序中
            GLES30.glAttachShader(program, fragmentShader);
            //链接着色器程序
            GLES30.gllinkProgram(program);
            final int[] linkStatus = new int[1];
            GLES30.glGetProgramiv(program, GLES30.GL_link_STATUS, linkStatus, 0);
            if (linkStatus[0] == 0) {
                String logInfo = GLES30.glGetProgramInfoLog(program);
                System.err.println(logInfo);
                GLES30.glDeleteProgram(program);
                return 0;
            }
            return program;
        } else {
            //创建失败
            return 0;
        }
    }
传入环境


C++语言 分离GLSL语言

和JAVA版本的一样。

创建工具类

在工具类中需加入下列头文件。

#include 
#include 
#include 
#include 
#include 
#include 

工具类中还是三个方法。

readFileFromAssets

char *readFileFromAssets(JNIEnv *env, jobject assetManager, char *fileName) {
    //创建资源
    AAssetManager *mgr = AAssetManager_fromJava(env, assetManager);
    if (mgr == NULL) {
        return nullptr;
    }
    //根据文件名打开资源文件
    AAsset *asset = AAssetManager_open(mgr, fileName, AASSET_MODE_UNKNOWN);
    if (NULL == asset) {
        return nullptr;
    }
    //获取文件长度
    long size = AAsset_getLength(asset);
    //获取内存,存储数据
    char *shaderCode = (char *) malloc(sizeof(char) * size + 1);
    //结尾符号
    shaderCode[size] = '';
    //读取资源文件到buffer缓冲区中
    AAsset_read(asset, shaderCode, size);
    //不可释放内存,释放了数据就没了
//    free(shaderCode);
    //释放资源
    AAsset_close(asset);
    //返回数据
    return shaderCode;
}

LoadShader

GLuint LoadShader(int type, char *shaderCode) {
    //创建一个着色器
    GLuint shader = glCreateShader(type);
    if (shader != 0) {
        //加载到着色器
        glShaderSource(shader, 1, &shaderCode, NULL);
        //编译着色器
        glCompileShader(shader);
        //检测状态
        GLint compileStatus;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
        if (compileStatus == 0) {
            //声明log长度变量
            GLint infoLen = 0;
            //获取长度并赋值
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                //创建成功小于等于1
                char *infoLog = static_cast(malloc(sizeof(char) * infoLen));
                glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
                cout << "SHADER ERROR!" << endl;
                free(infoLog);
            }
            //创建失败
            glDeleteShader(shader);
            return 0;
        }
        return shader;
    } else {
        //创建失败
        return 0;
    }
}

linkProgram

GLuint linkProgram(GLuint vertexShader, GLuint fragmentShader) {
    GLuint program = glCreateProgram();
    if (program != 0) {
        //将顶点着色器加入到程序
        glAttachShader(program, vertexShader);
        //将片元着色器加入到程序中
        glAttachShader(program, fragmentShader);
        //链接着色器程序
        gllinkProgram(program);
        //检测状态
        GLint linkStatus;
        glGetProgramiv(program, GL_link_STATUS, &linkStatus);
        if (linkStatus == 0) {
            GLint infoLen = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                char *infoLog = static_cast(malloc(sizeof(char) * infoLen));
                glGetProgramInfoLog(program, infoLen, NULL, infoLog);
                cout << "PROGRAM ERROR!" << endl;
                free(infoLog);
            }
            glDeleteProgram(program);
            return 0;
        }
        return program;
    } else {
        //创建失败
        return 0;
    }
}
传入环境


总结

根据上述划分,可以分为五部分:

    GLSL语句文件。工具类来实现读取文件、创建和编译着色器、链接统一管理程序等功能。在构造方法中,利用上下文环境来使用这些方法。在surfaceChanged中确定图形尺寸。在drawframe中进行图形绘制。

如果是GLSL语句发生变化,改变其文件即可;绘制图形变化,改变drawframe方法即可。所以这样只要哪一个部分改变,修改那个部分即可,实现了分离,利于维护和扩展代码。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/763961.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号