记录一下使用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;
}
}
继续阅读与本文标签相同的文章
-
猎户星空CEO傅盛:现在是AI发展最好时期,家庭服务机器人前景可期
2026-05-14栏目: 教程
-
5G远程驾驶和微公交首秀互联网大会
2026-05-14栏目: 教程
-
学宏程序编程,这些知识必不可少!
2026-05-14栏目: 教程
-
华为准备卖出“落后”的5G,多家美企极力竞争!任正非格局太大!
2026-05-14栏目: 教程
-
百度:飞桨深度学习平台已累计服务150多万开发者
2026-05-14栏目: 教程
