【问题标题】:How to display a bitmap in android through OpenGLES in C++?如何通过 C++ 中的 OpenGLES 在 android 中显示位图?
【发布时间】:2011-07-27 10:06:10
【问题描述】:

我的 Java 层中有一个实现Renderer 的类。在这个类中,我有一个想要传递给 JNI 层的位图。 JNI 层将负责使用 OpenGL 显示位图。谁能告诉我这是怎么做到的?

更新: 我知道有一个 open 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);
}

【问题讨论】:

  • 你为什么要做所有这些而不是坚持使用常规的Android GL interface
  • 我知道这很奇怪,但这是要求。事实上,这是我无法实现的整个事情的第一步

标签: android c++ opengl-es bitmap


【解决方案1】:

您不能直接传递 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 向下传递位图对象,则必须按照所述获取原始数据指针

有关不同方法的详细讨论,请参阅此线程 http://groups.google.com/group/android-ndk/browse_thread/thread/eaf038cc50d5041e/c5874712be5382cf

EDIT3:我刚刚了解到还有另一种方法

【讨论】:

    猜你喜欢
    • 2011-06-23
    • 2012-06-06
    • 2016-12-12
    • 2014-07-22
    • 2018-03-12
    • 2015-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多