Попытка рисовать текстурированные треугольники на устройстве не удалась, но эмулятор работает. Зачем?

У меня есть серия вызовов OpenGL-ES, которые правильно отображают треугольник и текстурируют его с альфа-смешиванием на эмуляторе (2.0.1). Когда я запускаю тот же код на самом устройстве (Droid 2.0.1), все, что я получаю, это белые квадраты.

Это говорит мне, что текстуры не загружаются, но я не могу понять, почему они не загружаются. Все мои текстуры представляют собой 32-битные PNG с альфа-каналами под res/raw, поэтому они не оптимизированы для sdk docs.

Вот как я загружаю свои текстуры:

private void loadGLTexture(GL10 gl, Context context, int reasource_id, int texture_id)
{
    //Get the texture from the Android resource directory
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), reasource_id, sBitmapOptions);

    //Generate one texture pointer...
    gl.glGenTextures(1, textures, texture_id);
    //...and bind it to our array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[texture_id]);

    //Create Nearest Filtered Texture
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

    //Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    //Clean up
    bitmap.recycle();
}

Вот как я рисую текстуру:

        //Clear
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    //Enable vertex buffer
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
        //Push transformation matrix
        gl.glPushMatrix();
        //Transformation matrices
        gl.glTranslatef(x, y, 0.0f);
        gl.glScalef(scalefactor, scalefactor, 0.0f);
        gl.glColor4f(1.0f,1.0f,1.0f,1.0f);
        //Bind the texture
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[textureid]);
        //Draw the vertices as triangles
        gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);
        //Pop the matrix back to where we left it
        gl.glPopMatrix();
            //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

И вот варианты, которые я включил:

        gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
        gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
        gl.glDepthFunc(GL10.GL_LEQUAL);             //The Type Of Depth Testing To Do
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);

Изменить: я просто попробовал передать BitmapOptions в вызов BitmapFactory.decodeResource(), но это, похоже, не устраняет проблему, несмотря на то, что вручную задан тот же предпочтительныйконфикс, плотность и целевая плотность.

Edit2: В соответствии с запросом, вот скриншот работы эмулятора. Подложные треугольники показаны с изображенной на нем текстурой окружности, прозрачность работает, потому что вы можете видеть черный фон.

удалена мертвая ссылка ImageShack

Вот, что делает дроид с тем же самым кодом на нем:

удалена мертвая ссылка ImageShack

Edit3: Вот мои BitmapOptions, обновленный вызов выше с тем, как я теперь вызываю BitmapFactory, все еще те же результаты, что и ниже: sBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;

sBitmapOptions.inDensity = 160;
sBitmapOptions.inTargetDensity = 160;
sBitmapOptions.inScreenDensity = 160;
sBitmapOptions.inDither = false;
sBitmapOptions.inSampleSize = 1;
sBitmapOptions.inScaled = false;

Вот мои вершины, текстурные коорды и индексы:

    /** The initial vertex definition */
    private static final float vertices[] = { 
                                        -1.0f, -1.0f, 0.0f, 
                                        1.0f, -1.0f, 0.0f,
                                        -1.0f, 1.0f, 0.0f,
                                        1.0f, 1.0f, 0.0f
                                                        };
    /** The initial texture coordinates (u, v) */   
private static final float texture[] = {            
                                    //Mapping coordinates for the vertices
                                    0.0f, 1.0f,
                                    1.0f, 1.0f,
                                    0.0f, 0.0f,
                                    1.0f, 0.0f
                                    };
/** The initial indices definition */   
private static final byte indices[] = {
                                        //Faces definition
                                        0,1,3, 0,3,2
                                        };

В любом случае, чтобы сбрасывать содержимое текстуры после загрузки в OpenGL ES? Может быть, я могу сравнить загруженную текстуру эмулятора с фактической загруженной текстурой устройства?

Я попробовал другую текстуру (значок по умолчанию для Android), и опять же, он отлично работает для эмулятора, но не отображается на самом телефоне.

Edit4: Попробовал переключиться, когда я загружаю текстуру. Не повезло. Пробовал использовать постоянное смещение от 0 до glGenTextures, без изменений.

Есть ли что-то, что я использую, что эмулятор поддерживает тот факт, что на самом деле нет телефона?

Edit5: Per Ryan ниже, я изменил размер моей текстуры с 200x200 до 256x256, и проблема не была решена.

Изменить: по запросу добавлены вызовы glVertexPointer и glTexCoordPointer выше. Кроме того, здесь инициализация vertexBuffer, textureBuffer и indexBuffer:

ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
loadGLTextures(gl, this.context);

Ответ 1

Im также новичок в Android OpenGL ES dev. У меня есть Milestone (евро версия для Droid).

Из того, что я вижу до сих пор, выпустив несколько обучающих приложений из разных книг/веб-сайтов на моей вехе, кажется, что этот телефон обрабатывает OpenGL ES по-другому, чем все другие выпущенные на сегодняшний день телефоны Android.

Я думаю, что это связано с расширениями OpenGL, поддерживаемыми на устройстве.

проверьте эту ссылку для списка поддерживаемых расширений, я уверен, что гуру кода обнаружит, почему именно дроид обрабатывает opengl es таким странным способом.

http://www.rbgrn.net/content/345-hands-on-motorola-droid-opengl-es-specs

Надеюсь, это поможет.. немного


EDITED:

Я изменил manifest.xml и заметил при использовании

<uses-sdk android:minSdkVersion="6"/>

ресурсы не загружаются вообще.

При использовании

<uses-sdk android:minSdkVersion="3"/>
Ресурсы

загружаются нормально.

Итак, я переключился на

<uses-sdk android:minSdkVersion="6"/>

и изменил способ загрузки растрового изображения.

Попробуйте заменить:

  //Get the texture from the Android resource directory 
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), reasource_id, sBitmapOptions); 

с:

InputStream is = context.getResources().openRawResource(your.resource.there);
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(is);

    } finally {
        //Always clear and close
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }

Текстуры отлично переносятся на мою веху с помощью этого кода, надеюсь, что эта работа для вас!

Ответ 2

У меня была именно эта проблема, когда я перешел с SDK 3 на 4. Мои текстуры отображались на эмуляторе, но не на реальном устройстве (Motorola Milestone/Droid).

Все ваши текстуры должны быть двоичными. Шахта была 256х256. Однако причина, по которой текстуры не отображаются, заключается в том, что ОС масштабирует их из своих двоичных величин мощности для отображения на экране высокой плотности Milestone.

Решение легко - просто переместите текстуры в каталог drawable-nodpi, и ОС не будет масштабировать их при загрузке.

Ответ 3

Убедитесь, что вы загрузили свои растровые изображения с помощью соответствующего BitmapConfig, который не масштабирует ваше изображение за кулисами, потому что это происходит.

Кроме того, есть причина, по которой вы сохраняете свои png в/raw/вместо/drawable/?

Ответ 4

Редактированный ответ Dullahx решил мою проблему по той же проблеме. Большое спасибо, это прослушивало меня последние два дня!

Я пытался отобразить текстуру на вкладке galaxy galaxy, которая была успешно отображена на эмуляторе, но на дисплее отображалась только плоскость.

Я заменил свой код:

plane.loadBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.jay));

с этим:

InputStream is = context.getResources().openRawResource(R.drawable.jay);

// Load the texture.
plane.loadBitmap(BitmapFactory.decodeStream(is));

и он тоже работал на устройстве!

Но будьте осторожны с minSdkVersion, если вы также пытаетесь сопоставить текстуру в полноэкранном прямоугольнике размера, таком как я. Если я использую

 <uses-sdk android:minSdkVersion="3"/>

на вкладке galaxy galaxy, мой самолет не был показан в полноэкранном режиме. Он был отображен в соответствии с полноэкранным размером устройства с использованием SDK версии 3. Я изменил это на

<uses-sdk android:minSdkVersion="8"/>

и мой полноэкранный прямоугольник возвращается с текстурой.

Надеюсь, что это тоже поможет.

Ответ 5

Я не уверен в вашей проблеме, я довольно новичок в развитии в целом, но мои проблемы с OpenGL и различие между эмулятором и телефоном были:

-Emulator может поддерживать не 2 ^ x измерения для растровых изображений, телефон не может -Emulator перевернул экран в NDK для openGL, поэтому мне пришлось использовать отрицательные координаты для определения представления в эмуляторе, в то время как мой G1 использовал неотрицательные координаты.

Надеюсь, это поможет вам каким-то образом.

Ответ 6

Я думаю, что может возникнуть проблема с загрузкой текстуры из APK. Попробуйте скопировать текстуру на SDCard и посмотреть, можете ли вы ее загрузить.

Ответ 7

Вы используете интерфейс GL11 где-нибудь? GL11 не поддерживается всеми устройствами. а также удалить линию glColor, возможно, ваша текстура отображается, но окрашена цветом? здесь некоторый фрагмент кода, как я показываю свои текстурные сетки:

void draw(GL10 gl) {

    // Enabled the vertices buffer for writing and to be used during
    // rendering.
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    // Specifies the location and data format of an array of vertex
    // coordinates to use when rendering.
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

    gl.glEnable(GL10.GL_TEXTURE_2D);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
            GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
            GL10.GL_LINEAR);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, myTextureId);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    gl.glDrawArrays(drawMode, 0, verticesCount);

    gl.glDisable(GL10.GL_TEXTURE_2D);
    // Disable the vertices buffer.
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

}