Как отобразить растровое изображение в Android через OpenGLES в C ++? - PullRequest
3 голосов
/ 27 июля 2011

В моем слое 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);
}

1 Ответ

3 голосов
/ 13 августа 2011

Вы не можете напрямую передать указатель класса растрового изображения Java и ожидать, что он будет работать с glTexImage2D.

glTexImage2D ожидает, что необработанные данные пикселей будут переданы в указатель.(на самом деле объявление вашей собственной функции C в JNI выглядит неправильно, последний параметр должен иметь тип jobject, а не void *. используйте «javah» для генерации правильных сигнатур функций JNI)

Вам необходимо получить эти данные изБитовое отображение с использованием вызова bitmap.getPixels (..) или bitmap.copyPixelsToBuffer (..), в зависимости от того, хотите ли вы преобразовать формат пикселя или нет.

Чтобы увидеть, как это делается в Java, посмотрите код здесьнапример: применение текстуры к кубу, различные текстуры на каждой грани куба

ByteBuffer fcbuffer - это переменная, которая содержит необработанные данные пикселей.Вы должны иметь возможность вызывать ByteBuffer.array () для получения фактического указателя данных и передачи его в JNI.

EDIT: чтобы очистить, ваш RenderGLStuff должен иметь последний параметр типа byte [], исо стороны JNI / C вы должны вызывать GetByteArrayElements / ReleaseByteArrayElements для переданной переменной типа jbyteArray.

EDIT2: чтобы быть совершенно ясным, я не уверен, каковы ваши ограничения, но есть другие решения вашей проблемы создания текстуры

  • вы можете сделать вызов генерации текстурына стороне Android (GLUtils.texImage2D, который принимает растровое изображение напрямую)

  • вы можете загружать текстуры из файлов на собственной стороне, используя любую собственную библиотеку изображений

  • если вы ДОЛЖНЫ передавать объекты Bitmap из Java, вы должны перейти к указателю необработанных данных, как описано

Подробное обсуждение различных подходов см. в этой теме http://groups.google.com/group/android-ndk/browse_thread/thread/eaf038cc50d5041e/c5874712be5382cf

EDIT3: я только что узнал, что есть еще один подход

...