【问题标题】:Android: How can i put 2 textures into the same square in OpenGLES?Android:如何在 OpenGLES 中将 2 个纹理放入同一个正方形?
【发布时间】:2012-06-26 11:31:15
【问题描述】:

我需要在同一个 Square 上放置 2 个纹理,但是当我运行应用程序时它总是崩溃。我该怎么办?我必须使用 2 个不同的“上下文”变量吗?我是否必须创建 Square 类的 2 个实例(每个纹理一个)? 我的渲染器:

public class HelloOpenGLES10Renderer implements Renderer {
private Square      square;     // the square
private Context     context;
private Context     context2;


/** Constructor to set the handed over context */
public HelloOpenGLES10Renderer(Context context) {
    this.square     = new Square();
    this.context=context;
    this.context2=context2;
}

public void onDrawFrame(GL10 gl) {
    // clear Screen and Depth Buffer
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    // Reset the Modelview Matrix
    gl.glLoadIdentity();

    // Drawing
    gl.glTranslatef(0.0f, 0.0f, -5.0f);     // move 5 units INTO the screen
    square.loadGLTexture(gl, this.context,Square.getSex());
    square.loadGLTexture(gl, this.context2,Square.getHair());   // is the same as moving the camera 5 units away
    square.draw(gl);                        // Draw the triangle

}

我没有发布我的 onsurfacechanged 和 onsurfacecreated。

我的 Square 课程: 公共类 Square {

private FloatBuffer vertexBuffer;   // buffer holding the vertices
private static int sex=2130837504;
private static int hair=2130837511;

private FloatBuffer textureBuffer;
private FloatBuffer textureBuffer2;// buffer holding the texture coordinates
private float texture[] = {
        // Mapping coordinates for the vertices
        0.0f, 1.0f,     // top left     (V2)
        0.0f, 0.0f,     // bottom left  (V1)
        1.0f, 1.0f,     // top right    (V4)
        1.0f, 0.0f      // bottom right (V3)
};
private float texture2[] = {
        // Mapping coordinates for the vertices
        0.0f, 0.5f,     // top left     (V2)
        0.0f, 0.0f,     // bottom left  (V1)
        0.5f, 0.5f,     // top right    (V4)
        0.5f, 0.0f      // bottom right (V3)
};

private float vertices[] = {
        -1.0f, -2.0f,  0.0f,        // V1 - bottom left
        -1.0f,  2.0f,  0.0f,        // V2 - top left
         0.8f, -2.0f,  0.0f,        // V3 - bottom right
         0.8f,  2.0f,  0.0f         // V4 - top right
};

public Square() {
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuffer.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuffer.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
    byteBuffer.order(ByteOrder.nativeOrder());
    textureBuffer = byteBuffer.asFloatBuffer();
    textureBuffer.put(texture);
    textureBuffer.position(0);
    byteBuffer = ByteBuffer.allocateDirect(texture2.length * 4);
    byteBuffer.order(ByteOrder.nativeOrder());
    textureBuffer2 = byteBuffer.asFloatBuffer();
    textureBuffer2.put(texture2);
    textureBuffer2.position(0);
}

/** The draw method for the square with the GL context */
public void draw(GL10 gl) {
    // bind the previously generated texture
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);


    // Point to our buffers
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    // Set the face rotation
    gl.glFrontFace(GL10.GL_CW);

    // Point to our vertex buffer
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    // Draw the vertices as triangle strip
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

    //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}




/** The texture pointer */
private int[] textures = new int[1];

public void loadGLTexture(GL10 gl, Context context,int sex ) {
    // loading texture
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
            sex);

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

    // 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);

    // Use 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();
}

public void loadGLTextureHair(GL10 gl, Context context,int hair ) {
    // loading texture
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
            sex);

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

    // 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);

    // Use 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();
}

public static int getSex() {
    return sex;
}

public static void setSex(int sex) {
    Square.sex = sex;
}

public static int getHair() {
    return hair;
}

public static void setHair(int hair) {
    Square.hair = hair;
}

}

LogCat:

06-26 10:15:10.320: D/dalvikvm(280): GC_EXTERNAL_ALLOC freed 923 objects / 64552 bytes in 83ms
06-26 10:15:10.921: D/libEGL(280): egl.cfg not found, using default config
06-26 10:15:10.921: D/libEGL(280): loaded /system/lib/egl/libGLES_android.so
06-26 10:15:11.260: I/ARMAssembler(280): generated scanline__000001B7:030101C1_00009501_00000000 [142 ipp] (234 ins) at [0x23a918:0x23acc0] in 5769170 ns
06-26 10:15:13.170: W/KeyCharacterMap(280): No keyboard for id 0
06-26 10:15:13.170: W/KeyCharacterMap(280): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
06-26 10:15:29.020: D/dalvikvm(312): GC_EXTERNAL_ALLOC freed 945 objects / 65408 bytes in 72ms
06-26 10:15:29.560: D/libEGL(312): egl.cfg not found, using default config
06-26 10:15:29.570: D/libEGL(312): loaded /system/lib/egl/libGLES_android.so
06-26 10:15:29.860: I/ARMAssembler(312): generated scanline__000001B7:030101C1_00009501_00000000 [142 ipp] (234 ins) at [0x23a830:0x23abd8] in 2951633 ns
06-26 10:15:54.629: W/KeyCharacterMap(312): No keyboard for id 0
06-26 10:15:54.639: W/KeyCharacterMap(312): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
06-26 11:21:50.350: D/dalvikvm(344): GC_EXTERNAL_ALLOC freed 967 objects / 66264 bytes in 75ms
06-26 11:21:50.950: D/libEGL(344): egl.cfg not found, using default config
06-26 11:21:50.950: D/libEGL(344): loaded /system/lib/egl/libGLES_android.so
06-26 11:21:51.290: I/ARMAssembler(344): generated scanline__000001B7:030101C1_00009501_00000000 [142 ipp] (234 ins) at [0x23a830:0x23abd8] in 12307152 ns
06-26 11:22:01.749: W/KeyCharacterMap(344): No keyboard for id 0
06-26 11:22:01.749: W/KeyCharacterMap(344): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
06-26 11:48:39.200: D/dalvikvm(371): GC_EXTERNAL_ALLOC freed 989 objects / 67120 bytes in 69ms
06-26 11:48:39.750: D/libEGL(371): egl.cfg not found, using default config
06-26 11:48:39.759: D/libEGL(371): loaded /system/lib/egl/libGLES_android.so
06-26 11:48:40.079: W/dalvikvm(371): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
06-26 11:48:40.109: E/AndroidRuntime(371): FATAL EXCEPTION: GLThread 8
06-26 11:48:40.109: E/AndroidRuntime(371): java.lang.NullPointerException
06-26 11:48:40.109: E/AndroidRuntime(371):  at hello.project.Square.loadGLTexture(Square.java:96)
06-26 11:48:40.109: E/AndroidRuntime(371):  at hello.project.HelloOpenGLES10Renderer.onDrawFrame(HelloOpenGLES10Renderer.java:34)
06-26 11:48:40.109: E/AndroidRuntime(371):  at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1332)
06-26 11:48:40.109: E/AndroidRuntime(371):  at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1116)
06-26 11:48:42.879: I/Process(371): Sending signal. PID: 371 SIG: 9

【问题讨论】:

  • 发布代码和错误日志..
  • 是的,感谢您的帮助,如果代码乱七八糟,我很抱歉,我是 openGL 的新手,但我会尽力而为

标签: android opengl-es bind textures


【解决方案1】:

我几乎可以肯定你得到了NullPointerException,因为BitmapFactory找不到你指定的资源id,所以Bitmap变成null,因此当你尝试recycle()它时会抛出异常.

您应该从生成的R 类中获取值,而不是像您那样使用 id 作为静态变量 (private static int sex=2130837504;):BitmapFactory.decodeResource(context.getResources(), R.drawable.sex);

除此之外,您的代码还有一些初学者问题:

  1. 您只需要一个Context 对象。

  2. 您不需要两种不同的方法来加载纹理(loadGLTextureHair(还有一个错误,它应该使用参数头发,而不是性别)和loadGLTexture):

    public void loadGLTexture(GL10 gl, Context context, int resourceId) {
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId);
    
        gl.glGenTextures(1, textures, 0);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    
        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);
        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);
    
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }  
    

你应该从你的 onSurfaceCreated() 方法调用这个方法,如果你从 onDrawFrame() 调用它,它会每帧加载一个新的纹理,你会耗尽内存。
要在纹理之间切换,请使用glBindTexture() 方法。 3. 由于您没有将 textures[] 中的值保存在其他地方,因此下次加载纹理时会被覆盖。

这些是我能看到的最明显的错误,如果你修复它们,你的程序至少应该可以运行。继续阅读大量教程和示例,直到你明白为止:)

【讨论】:

  • 我需要通过程序的 onclick 操作更改纹理。如果我不使用变量来保存纹理(性或头发),我该怎么做?
  • 使用变量,但不要像你一样从资源中设置默认值:sex=2130837504;,而是始终从Rsex = R.drawable.sex1; 获取值。这是因为当您添加新资源时,资源值会自动更改,因此您永远无法确定某个值是否仍然有效。
  • 我管理了一些东西,它现在可以工作了,但我仍然有一个问题:它只绘制了最后一个“loadGLTexture”调用。我该怎么做才能调用它们: public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -5.0f); square.loadGLTexture(gl, this.context,Square.getSex()); square.loadGLTexture(gl, this.context,Square.getHair()); square.draw(gl); glBindTexture() 会解决这个问题吗?以及如何使用 glBindTexture。很抱歉,但很多这些东西对我来说仍然是新的和困难的。
  • 它是gl.glBindTexture() ;)
  • 您已经交换了两个变量,glBindTexture() 应该与您从 glGenTextures() 获得的整数值一起使用(您正在使用资源 id)并且应该使用最后一个参数调用 loadGLTexture()资源 ID(您正在使用 GL10.GL_TEXTURE_2D)
猜你喜欢
  • 2017-06-11
  • 2020-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多