记录一下使用opengl es写的第一个立方体

 

glinit.cpp代码


#include \"GLInit.h\"
#include \"GLUtils.h\"
#include \"glm/glm.hpp\"
#include \"glm/ext.hpp\"
#include <GLES2/gl2.h>
#include <android/asset_manager_jni.h>
#include <android/asset_manager.h>

GLuint mProgramm;
GLuint vbo, ibo, textureId;
GLint positionLocation, textcoordLocation;
GLint modleLocation, viewLocation, projectLocation, U_MainTextureLocation;

glm::mat4 identifyMatric = glm::mat4(1.0f);//单位矩阵
glm::mat4 projecttionMatric;//投影矩阵
glm::mat4 viewMatric;//视图变换

float vertexs[] = {
        //face
        1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,
        1.0f, -1.0f, 1.0f, 1.0f, 0.0f,
        //right
        1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 1.0f, 0.0f, 0.0f,
        1.0f, -1.0f, -1.0f, 1.0f, 0.0f,
        //top
        1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
        1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
        //back
        -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, -1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
        -1.0f, -1.0f, -1.0f, 1.0f, 0.0f,
        //left
        -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
        -1.0f, -1.0f, 1.0f, 1.0f, 0.0f,
        //bottow
        1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
        -1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
        1.0f, -1.0f, -1.0f, 1.0f, 0.0f
};

unsigned int indexs[] = {
        0, 1, 2, 0, 2, 3,
        4, 5, 6, 4, 6, 7,
        8, 9, 10, 8, 10, 11,
        12, 13, 14, 12, 14, 15,
        16, 17, 18, 16, 18, 19,
        20, 21, 22, 20, 22, 23
};

void loadTexure();

GLuint creatTexture(unsigned char *bmp, long width, long height);

bool GLInit::registerNativeMethods(JNIEnv *pEnv) {
    jclass jclass1 = nullptr;
    jclass1 = pEnv->FindClass(GL_LOAD_CLASS);
    if (jclass1 == nullptr)
        return JNI_FALSE;
    jint registerNatives = pEnv->RegisterNatives(
            jclass1, jniNativeMethods, sizeof(jniNativeMethods) / sizeof(jniNativeMethods[0]));
    if (registerNatives < 0)
        return JNI_FALSE;
    return JNI_TRUE;
}

void init(JNIEnv *env, jclass type, j  assets) {
    JavaVM *javaVM;
    env->GetJavaVM(&javaVM);
    AAssetManager *assetManager = AAssetManager_fromJava(env, assets);
    GLUtils::setParameter(env, javaVM, assets, assetManager);
    //loadTexure();
}

void loadTexure() {
    if (!GL_TRUE) {
        textureId = GLUtils::loadTexture(\"cube.png\");
    } else {
        char *content = GLUtils::readFile(\"wood.bmp\");
//        char *content = GLUtils::readFile(\"earth.bmp\");
        long width = 0, height = 0;
        unsigned char *bmp = GLUtils::decodeBMP(content, width, height);
        textureId = creatTexture(bmp, width, height);
        delete content;
    }
}

GLuint creatTexture(unsigned char *bmp, long width, long height) {
    GLuint textureId;
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    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);
    //GLenum target,    GL_TEXURE_2D
    // GLint level,     bitmap level
    // GLint internalformat,    像素格式
    // GLsizei width,       宽度
    // GLsizei height,      高度
    // GLint border,
    // GLenum format,       数据源格式
    // GLenum type,         数据源每一个point类型unsined char 即byte
    // const void *pixels   文理数据
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp);
    glBindTexture(GL_TEXTURE_2D, 0);
    return textureId;
}

void onSurfaceCreated() {
    mProgramm = GLUtils::CreatProgramm();
    if (mProgramm == 0) {
        LOGD(\"creat programm failed\");
        return;
    }
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);//指定剔出操作的多边形面 本函数可以禁用多边形正面或背面上的光照、阴影和颜色计算及操作,消除不必要的渲染计算是因为无论对象如何进行旋转或变换
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    positionLocation = glGetAttribLocation(mProgramm, \"position\");
    textcoordLocation = glGetAttribLocation(mProgramm, \"textcoord\");
    modleLocation = glGetUniformLocation(mProgramm, \"M\");
    viewLocation = glGetUniformLocation(mProgramm, \"V\");
    projectLocation = glGetUniformLocation(mProgramm, \"P\");
    U_MainTextureLocation = glGetUniformLocation(mProgramm, \"U_MainTexture\");

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    size_t verlength = sizeof(vertexs) / sizeof(vertexs[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * verlength, vertexs, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    size_t fralength = sizeof(indexs) / sizeof(indexs[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * fralength, indexs, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    loadTexure();
}

void onSurfaceChanged(JNIEnv *env, jclass type, jfloat width, jfloat height) {
    LOGD(\"onSurfaceChanged\");
    glViewport(0, 0, width, height);
    projecttionMatric = glm::perspective(90.0f, width / height, 0.1f, 10.0f);

    glm::vec3 vec(0.0f, 0.0f, -3.0f);
    glm::vec3 vec2(1.0f, 1.0f, 0.0f);
    viewMatric = glm::translate(identifyMatric, vec) * glm::rotate(identifyMatric, 45.0f, vec2);
    identifyMatric = glm::mat4(1.0f);
}

void onDraw () {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glUseProgram(mProgramm);

    glUniformMatrix4fv(modleLocation, 1, GL_FALSE, glm::value_ptr(identifyMatric));
    glUniformMatrix4fv(viewLocation, 1, GL_FALSE, glm::value_ptr(viewMatric));
    glUniformMatrix4fv(projectLocation, 1, GL_FALSE, glm::value_ptr(projecttionMatric));
    //纹理
    glBindTexture(GL_TEXTURE_2D, textureId);
    glUniform1i(U_MainTextureLocation, 0);
    //顶点坐标
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glEnableVertexAttribArray(positionLocation);
    //  哪个      第一个参数指定顶点属性位置,与顶点着色器中layout(location=0)对应。
    //  坐标由xyz组成        第二个参数指定顶点属性大小。
    //  浮点数             第三个参数指定数据类型。
    // 是否归一化            第四个参数定义是否希望数据被标准化。
    // 数据间隔     (stride 步幅;大步,阔步;进展;一跨) 每个点的数据间隔        第五个参数是步长(Stride),指定在连续的顶点属性之间的间隔。
    //从哪个位置开始           第六个参数表示我们的位置数据在缓冲区起始位置的偏移量。
    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
    //纹理坐标
    glEnableVertexAttribArray(textcoordLocation);
    glVertexAttribPointer(textcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5,
                          (void *) (sizeof(float) * 3));
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //第一个参数表示绘制的类型,有三种取值:
    //GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接;
    //GL_TRIANGLE_FAN:以V0V1V2,V0V2V3,V0V3V4,……的形式绘制三角形;
    //GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。这个方法可以保证从相同的方向上所有三角形均被绘制。以V0V1V2,V1V2V3,V2V3V4……的形式绘制三角形;
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    //第二个参数是我们打算绘制顶点的个数
    size_t length = sizeof(indexs) / sizeof(indexs[0]);
    glDrawElements(GL_TRIANGLES, length, GL_UNSIGNED_INT, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glUseProgram(0);

}

glinit.h 头文件


#include <jni.h>
#include <android/log.h>

#define TAG \"TAG\" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型

#ifndef SECONDTRIANGLE_GLINIT_H
#define SECONDTRIANGLE_GLINIT_H
#define GL_LOAD_CLASS \"com/vivo/secondtriangle/GLNativeUtils\"

 void init(JNIEnv *env, jclass type, j  assets);

 void onSurfaceCreated();

 void onSurfaceChanged(JNIEnv *env, jclass type, jfloat width, jfloat height);

 void onDraw ();

static JNINativeMethod jniNativeMethods[] = {
        {\"init\",             \"(Landroid/content/res/AssetManager;)V\", (void *) init},
        {\"onSurfaceCreated\", \"()V\",                                    (void *) onSurfaceCreated},
        {\"onSurfaceChanged\", \"(FF)V\",                                  (void *) onSurfaceChanged},
        {\"onDraw \",      \"()V\",                                    (void *) onDraw }
};

class GLInit {

public:

    static bool registerNativeMethods(JNIEnv *pEnv);

};


#endif //SECONDTRIANGLE_GLINIT_H

glutils 创建programming所用


#include <android/asset_manager_jni.h>
#include \"GLUtils.h\"

_JNIEnv *env = nullptr;
AAssetManager *assetManager = nullptr;
JavaVM *javaVM = nullptr;
static j  assets = nullptr;

/**
 * 设置全局参数
 * @param pEnv
 * @param pManager
 */
void GLUtils::setParameter(JNIEnv *pEnv, JavaVM *pVM, j  asset, AAssetManager *pManager) {
    env = pEnv;
    assets = asset;
    assetManager = pManager;
    javaVM = pVM;
}

/**
 * creat gles programm
 * @return
 */
GLuint GLUtils::CreatProgramm() {
    if (assetManager == nullptr) {
        return GL_FALSE;
    }
    GLuint vertexShader = creatShader(GL_VERTEX_SHADER, cubeVertexShader);
    if (vertexShader == GL_FALSE) {
        return 0;
    }
    GLuint fragmentShader = creatShader(GL_FRAGMENT_SHADER, cubeFragmentShader);
    if (fragmentShader == GL_FALSE) {
        return 0;
    }

    GLuint program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    gl Program(program);

    glDetachShader(program, vertexShader);
    glDetachShader(program, fragmentShader);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    GLint  edStatus;
    glGetProgramiv(program, GL_ _STATUS, & edStatus);
    if ( edStatus == GL_FALSE) {
        char chars[1024];
        int lenght;
        glGetProgramInfoLog(program, 1024, &lenght, chars);
        LOGD(\"error create programm:%s\", chars);
        glDeleteProgram(program);
        return 0;
    }
    return program;
}


/**
 * 读取assert文件
 * @param pManager
 * @param shaderPath
 * @return
 */
char *GLUtils::readFile(const char *shaderPath) {
    AAsset *aAsset = AAssetManager_open(assetManager, shaderPath, AASSET_MODE_UNKNOWN);
    if (aAsset == nullptr) {
        LOGD(\"aAsset == nullptr\");
        return nullptr;
    }
    off_t length = AAsset_getLength(aAsset);
    char *chars = new char[length + 1];
    AAsset_read(aAsset, chars, length);
    chars[length] = \'\\0\';
    AAsset_close(aAsset);
//    LOGD(\"%s\", chars);
    return chars;
}

/**
 * 创建shader
 * @param shadeType
 * @param shaderPath
 * @param pManager
 * @return
 */
GLuint GLUtils::creatShader(int shadeType, const char *shaderPath) {
    const char *vertexShaderChars = readFile(shaderPath);
    if (vertexShaderChars == nullptr) {
        LOGD(\"vertexShaderChars == nullptr\");
        return GL_FALSE;
    }
    GLuint shader = glCreateShader(shadeType);
    glShaderSource(shader, 1, &vertexShaderChars, nullptr);
    glCompileShader(shader);
    delete vertexShaderChars;

    GLint complite = -1;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &complite);
    if (complite == GL_FALSE) {
        char chars[1024];
        GLint length;
        //shader
        //緩衝區
        //讀到的長度 真實的日志大小
        //日志放哪
        glGetShaderInfoLog(shader, 1024, &length, chars);
        //打印
        LOGD(\"error creat shader:%s\", chars);
        glDeleteShader(shader);
        return 0;
    }
    LOGD(\"creat shader success:%d\", shader);
    return shader;
}

/**
 * java 层获取textureID 并返回  不用解码图片,java用bitmap
 * @param filePath
 * @return
 */
GLuint GLUtils::loadTexture(const char *filePath) {
    if (javaVM->AttachCurrentThread(&env, NULL) != JNI_OK) {
        return GL_FALSE;
    }
    jclass pJclass = env->FindClass(java_utils_path);
    if (pJclass == NULL) {
        LOGD(\"can\'t find class\");
        return GL_FALSE;
    }
    //第三个参数为  方法参数类型以及返回值
    jmethodID pJmethodID = env->GetStaticMethodID(pJclass, \"loadTexture\",
                                                  \"(Landroid/content/res/AssetManager;Ljava/lang/String;)I\");
    if (pJmethodID == NULL) {
        LOGD(\"can\'t find methodId\");
        return GL_FALSE;
    }
    jstring pJstring = env->NewStringUTF(filePath);
    LOGD(\"env:%p,assets:%p\", env, assets);
    GLuint textureId = env->CallStaticIntMethod(pJclass, pJmethodID,
                                                assets, pJstring);
    env->DeleteLocalRef(pJstring);
    LOGD(\"loadTexture finish\");
    return textureId;
}

/**
 * 解码bmp
 * @param bmpData
 * @param width
 * @param height
 * @return
 */
unsigned char *GLUtils::decodeBMP(char *bmpData, long &width, long &height) {
    //要读四个字节  如果是八个字节要转为int
    LOGD(\"long size:%ld,unsigned long size:%ld\", sizeof(long), sizeof(unsigned long));
    //0x4D42 bmp标准   offset 0 :bmptype :unsigned short
    if (0x4D42 == (*(unsigned short *) bmpData)) {
        //offset 10:bmptype:unsined long    ->imagedate offset
        unsigned long imageStartLengh = *(unsigned long *) (bmpData + 10);
        //offset 18 :width long -> image width
        width = *(long *) (bmpData + 18);
        //offset 22 :height long -> image width
        height = *(long *) (bmpData + 22);
        LOGD(\"decodeBMP size:%ld,width:%ld,height:%ld\", imageStartLengh, width, height);
        unsigned char *imageData = (unsigned char *) (bmpData + imageStartLengh);
        for (int i = 0; i < width * height * 3; i += 3) {
            //BRG 转为 RGB
            unsigned char temp = imageData[i];
            imageData[i] = imageData[i + 2];
            imageData[i + 2] = temp;
        }
        return imageData;
    } else {
        LOGD(\"不是bmp格式\");
        return nullptr;
    }
}

在里面还是用到了jni条用java方法 创建纹理并返回纹理坐标。这样就不用解码图片,java直接用的bitmap

package com.vivo.secondtriangle;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;

/**
 * date:2018/12/20:11:25
 * describe:
 */
public class GLESUtils {

    public static int loadTexture(AssetManager manager, String path) {
        InputStream in = null;
        try {
            in = manager.open(path);
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
        BitmapFactory.Options op = new BitmapFactory.Options();
        op.inPreferredConfig = Bitmap.Config.ARGB_8888;
        Bitmap bmp = BitmapFactory.decodeStream(in, null, op);

        // generate textureID
        int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);
        int textureID = textures[0];

        // create texture
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
        GLES20.glTexParameteri(
                GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(
                GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
                GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                GLES20.GL_CLAMP_TO_EDGE);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        // clean up
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            bmp.recycle();
        }
        return textureID;
    }

}

 

收藏 打印