Не могу сопоставить текстуры с OpenGL ES на реальных устройствах - PullRequest
0 голосов
/ 21 декабря 2011

Я пробовал простую программу, которая динамически генерирует текстуру и отображает ее на четырехугольник, используя NDK. На эмуляторе все нормально, но на реальных устройствах не получилось. Вот мой код:

private static class Renderer implements GLSurfaceView.Renderer
{
    @Override
    public void onDrawFrame(GL10 gl)
    {
        nativeDrawFrame();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height)
    {
        nativeInit(width, height);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config)
    {
        // do nothing...
    }
}

и собственный код:

const static GLfloat vertices_f[4][2] = 
{
    { 0.0f,    0.0f },
    { 100.0f,    0.0f },
    { 100.0f,    100.0f },
    { 0.0f,    100.0f }
};

const static GLfloat texCoords_f[4][2] = 
{
    { 0.0f,    0.0f },
    { 1.0f,    0.0f },
    { 1.0f,    1.0f },
    { 0.0f,    1.0f }
};

JNIEXPORT void JNICALL Java_com_sangfor_gltest_GLView_nativeInit(JNIEnv * env, jobject obj, jint width, jint height)
{
    if (!bitmap)
    {
        // allocate dynamic texture memory
        bitmap = memalign(16, 1024*1024);
        if (!bitmap)
        {
            __android_log_print(ANDROID_LOG_ERROR, "native-render", "failed allocation.");
            return;
        }
    }

    glViewport(0, 0, width, height);
    //glMatrixMode(GL_PROJECTION);
    //glLoadIdentity();
    //glOrthox(0, 0x10000, 0, 0x10000, 0x10000, -0x10000);
    //glClearColorx(0, 0, 0, 0);
    glGenTextures(1, &texture);
    __android_log_print(ANDROID_LOG_INFO, "native-render", "texture = %d", texture);
    // glVertexPointer(2, GL_FIXED, 0, vertices);
    // glTexCoordPointer(2, GL_FIXED, 0, texCoords);
    //glEnableClientState(GL_COLOR_ARRAY);
    glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
    glEnable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    glDisable(GL_ALPHA_TEST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}

JNIEXPORT void JNICALL Java_com_sangfor_gltest_GLView_nativeDrawFrame(JNIEnv * env, jobject obj)
{
    struct timeval tv;
    unsigned char color_value;

    glClear(GL_COLOR_BUFFER_BIT);

    // fill texture according to current timestamp
    gettimeofday(&tv, NULL);
    color_value = (unsigned char)(tv.tv_usec * 0.000255f);
    memset(bitmap, color_value, 1024*1024);
    __android_log_print(ANDROID_LOG_INFO, "native-render", "color_value = %d", color_value);

    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, bitmap);

    glBindTexture(GL_TEXTURE_2D, texture);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glTexCoordPointer(2, GL_FLOAT, 0, texCoords_f);
    glVertexPointer(2, GL_FLOAT, 0, vertices_f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    glFlush();
}

В эмуляторе все работает так, как я ожидал: область на экране постоянно меняет свой цвет. Тем не менее, когда я запускаю его на реальных устройствах (Samsung Galaxy S 2.3.3 и Asus Transformer TF101 3.2.1), он просто показывает белый блок и отображение текстуры кажется не работающим.

Я попытался добавить и закомментировать проекционное преобразование, включить отображение текстур, вызвав glEnable(GL_TEXTURE_2D), отключить альфа-смешивание и тестирование, вызвав glDisable(...), переместить glBindTexture и glTexImage2D в функцию инициализации, изменить размер текстуры на 32 x 32 но ничего из этого не работает.

Может кто-нибудь помочь мне понять, почему наложение текстур не работает только на реальных устройствах? Есть ограничение GPU или что-то?

РЕДАКТИРОВАТЬ: Я попробовал предложение Ложка и нашел реальную проблему. Независимо от того, какую текстуру я привязываю, устройство использует текстуру с именем 0 для рендеринга четырехугольников, поэтому glBindTexture(GL_TEXTURE_2D, 0) работает нормально, но glBindTexture(GL_TEXTURE_2D, 1) и все, что возвращается glGenTextures(...), не выполняется. Это означает, что я могу сохранить только одну текстуру, но мне нужно использовать 2 или более.

Ответы [ 2 ]

0 голосов
/ 29 декабря 2011

Я переместил свои нативные методы JNI в отдельный класс-оболочку, аналогично примеру gl2-jni в Android NDK, и проблема была решена.Я не знаю, почему реализация статического нативного кода в классе-оболочке имеет значение, но в любом случае это работает.

GLJNILib.java

// Wrapper for native library
public class GLJNILib {

     static {
         System.loadLibrary("gljni");
     }

    /**
     * @param width the current view width
     * @param height the current view height
     */
     public static native void init(int width, int height);
     public static native void step();
}

GLJNIView.java

// some other stuff

private class Renderer implements GLSurfaceView.Renderer {
    private static final String TAG = "Renderer";
    public void onDrawFrame(GL10 gl) {
        GLJNILib.step();
    }

    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLJNILib.init(width, height);
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // Do nothing.
    }
}

// some other stuff
0 голосов
/ 22 декабря 2011

Белый блок означает, что текстурирование работает, но текстуры загружены неправильно.

Если бы фактическое отображение было проблемой, вы бы увидели текстуры, но все цвета были искажены или перепутаны.

Проверьте фактические значения, заданные glGenTextures(). Я обнаружил, что при использовании openGL-es 1.x в более поздних версиях android (2.2+) glGenTextures() выбрасывает некоторые действительно случайные числа вместо того, чтобы давать идентификаторы 0,1,2,3 и т. Д. Возможно, вам придется введите свои идентификаторы вручную и не используйте glGenTextures()

Либо проверьте, правильно ли загружаются данные пикселей из файла. Пустые белые текстуры могут появиться, если у вас неправильное имя файла или файл отсутствует, но вы добавили некоторую обработку ошибок, которая позволяет приложению продолжать работу. И / или не забудьте обновить папки res или даже очистить проект при добавлении новых текстур

UPDATE:

Вот как я это сделал:

public class Texture{

private int textureId = -1;
// initialise to -1

public int getTextureId(){
    return textureId;
}

public void loadTexture(GL10 gl, Context context){

    String[] filenamesplit = filename.split("\\.");

    name = filenamesplit[filenamesplit.length-2];

    int[] textures = new int[1];
    //Generate one texture pointer...
    //GLES20.glGenTextures(1, textures, 0);             
    textures[0] = ((IridianGraphicsEngine)context).texturecount;
    ((IridianGraphicsEngine)context).texturecount++;

    //...and bind it to our array
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);

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

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

    Bitmap bitmap = FileUtil.openBitmap(name, context);

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

    bitmap.recycle();   

    textureId = textures[0];

}
}

Тогда при рисовании:

public class Mesh{

private Texture texture;

public void draw(GL10 gl){

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    // Pass the vertex buffer in
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0,
                             vertices);

    int textureId = texture.getTextureId();

    if(textureID>=0){

        // Enable Textures
        gl.glEnable(GL10.GL_TEXTURE_2D);

        // Get specific texture.
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);

        // Use UV coordinates.
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // Pass in texture coordinates          
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureCoordinates);

    } 

    // Pass in vertex normals
    gl.glNormalPointer(GL10.GL_FLOAT, 0, normals);

    gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);

    gl.glDrawElements(GL10.GL_TRIANGLES, numindices,GL10.GL_UNSIGNED_SHORT, indices);

    gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);

    if(textureID>=0){
        // Disable buffers          
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    }

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

}

Однако все это в java и использует странную смесь opengl-es 2.0 для загрузки текстуры и opengl-es 1.1 для рисования

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...