如何通过C中的OpenGLES在android中显示位图?
作者:互联网
我的Java层中有一个实现Renderer的类.在此类中,我有一个位图,希望传递给JNI层. JNI层将负责使用OpenGL显示位图.谁能告诉我该怎么做?
更新:
我知道有一个开放的gl方法glTexImage2D可用于显示简单的2D图像.谁能告诉我如何使用它?在调用此方法之前和之后,我需要做哪些设置?我应该如何将位图传递给此方法(从Java到JNI)?
更新2
这是我当前的代码:
Java类
public class HelloRenderer implements Renderer
{
Context _context;
Bitmap wood;
public void SetContext(Context context)
{
_context = context;
wood = BitmapFactory.decodeResource( _context.getResources(), R.drawable.hello);
}
@Override
public void onDrawFrame(GL10 gl)
{
RenderGLStuff(wood.getWidth(), wood.getHeight(), wood);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
InitGLStuff(wood.getWidth(), wood.getHeight(), wood);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
}
private static native void InitGLStuff(int width, int height, Bitmap ptr);
private static native void RenderGLStuff(int width, int height, Bitmap ptr);
static
{
System.loadLibrary("myglstuff");
}
}
JNI方法
JNIEXPORT void JNICALL Java_mine_NativeGL_HelloRenderer_InitGLStuff(JNIEnv * env, jobject obj, int width, int height, void * ptr )
{
glViewport(0, 0, width, height);
glClearColorx((GLfixed)(0.1f * 65536), (GLfixed)(0.2f * 65536), (GLfixed)(0.3f * 65536), 0x10000);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
}
JNIEXPORT void JNICALL Java_mine_NativeGL_HelloRenderer_RenderGLStuff(JNIEnv * env, jobject obj, int width, int height, void * ptr)
{
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &ptr);
}
更新3
我已经更新了这样的本机代码,现在可以看到白框代替图像,但是没有图像内容.有任何想法吗?
JNIEXPORT void JNICALL Java_mine_NativeGL_HelloRenderer_RenderGLStuff(JNIEnv * env, jobject obj, int width, int height, void * ptr)
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLfloat vertices[] = { -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, };
GLfloat normals[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };
GLfloat textureCoords[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0 };
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &ptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, texture);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glNormalPointer(GL_FLOAT, 0, normals);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-5.0, 5.0, -7.5, 7.5, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
解决方法:
您不能直接传递Java Bitmap类指针,并且不能期望它与glTexImage2D一起使用.
glTexImage2D期望在指针中传递原始像素数据. (实际上,您的JNI本机C函数声明看起来不正确,最后一个参数应为jobject类型,而不是void *.请使用“ javah”生成正确的JNI函数签名)
您需要使用bitmap.getPixels(..)或bitmap.copyPixelsToBuffer(..)调用从位图中获取数据,具体取决于是否要转换像素格式.
要查看其在Java中的完成方式,请查看以下示例中的代码:
applying texture to Cube, different texture on each face of cube
ByteBuffer fcbuffer是保存原始像素数据的变量.您应该能够调用ByteBuffer.array()以获得实际的数据指针并将其传递给JNI.
编辑:要清楚,您的RenderGLStuff应该具有byte []类型的最后一个参数,并且从JNI / C端,您应该在传递的jbyteArray类型变量上调用GetByteArrayElements / ReleaseByteArrayElements.
EDIT2:非常清楚,我不确定您的约束是什么,但是还有其他解决纹理创建问题的方法
>您可以在Android端进行纹理生成调用(直接获取位图的GLUtils.texImage2D)
>您可以使用任何本机图像库从本机端的文件加载纹理
>如果必须从Java向下传递Bitmap对象,则必须按所述到达原始数据指针
有关不同方法的详细讨论,请参见线程http://groups.google.com/group/android-ndk/browse_thread/thread/eaf038cc50d5041e/c5874712be5382cf.
EDIT3:我刚刚了解到还有另一种方法
>像往下一样传递位图对象,并使用jnigraphics库获取对像素的原始访问,如此处所述What is JNI Graphics or how to use it?
标签:opengl-es,bitmap,c-4,android 来源: https://codeday.me/bug/20191208/2089096.html