Android OpengL多个纹理无法显示

时间:2012-11-26 14:40:02

标签: android opengl-es textures

我已经成功地在所有6个侧面(例如一个箱子)上显示了具有相同纹理的立方体,但我现在正在尝试制作一个天空盒(每侧有6个不同的纹理1)。天空盒只在四面都显示白色。每个纹理都在箱子立方体上工作,所以纹理很好(我想。)这是我的代码和一些屏幕截图。

TexturedCube类(用于crate等的类)

package com.dissertation.dnativeapp;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.util.Log;
/*
 * A cube with texture. 
 * Define the vertices for only one representative face.
 * Render the cube by translating and rotating the face.
 */
public class TexturedCube {
    private static final String TAG = "texcube";
   private FloatBuffer vertexBuffer; // Buffer for vertex-array
   private FloatBuffer texBuffer;    // Buffer for texture-coords-array (NEW)

   private float[] vertices = { // Vertices for a face
      -1.0f, -1.0f, 0.0f,  // 0. left-bottom-front
       1.0f, -1.0f, 0.0f,  // 1. right-bottom-front
      -1.0f,  1.0f, 0.0f,  // 2. left-top-front
       1.0f,  1.0f, 0.0f   // 3. right-top-front
   };

   float[] texCoords = { // Texture coords for the above face (NEW)
      0.0f, 1.0f,  // A. left-bottom (NEW)
      1.0f, 1.0f,  // B. right-bottom (NEW)
      0.0f, 0.0f,  // C. left-top (NEW)
      1.0f, 0.0f   // D. right-top (NEW)
   };
   int[] textureIDs = new int[1];   // Array for 1 texture-ID (NEW)

   // Constructor - Set up the buffers
   public TexturedCube() {
      // Setup vertex-array buffer. Vertices in float. An float has 4 bytes
      ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
      vbb.order(ByteOrder.nativeOrder()); // Use native byte order
      vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
      vertexBuffer.put(vertices);         // Copy data into buffer
      vertexBuffer.position(0);           // Rewind

      // Setup texture-coords-array buffer, in float. An float has 4 bytes (NEW)
      ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
      tbb.order(ByteOrder.nativeOrder());
      texBuffer = tbb.asFloatBuffer();
      texBuffer.put(texCoords);
      texBuffer.position(0);
   }

   // Draw the shape
   public void draw(GL10 gl) {
      gl.glFrontFace(GL10.GL_CCW);    // Front face in counter-clockwise orientation
      gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face
      gl.glCullFace(GL10.GL_BACK);    // Cull the back face (don't display) 

      gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
      gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  // Enable texture-coords-array (NEW)
      gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords buffer (NEW)

      // front
      gl.glPushMatrix();
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // left
      gl.glPushMatrix();
      gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // back
      gl.glPushMatrix();
      gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // right
      gl.glPushMatrix();
      gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // top
      gl.glPushMatrix();
      gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // bottom
      gl.glPushMatrix();
      gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  // Disable texture-coords-array (NEW)
      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glDisable(GL10.GL_CULL_FACE);
   }

   // Load an image into GL texture
   public void loadTexture(GL10 gl, Context context) {
      gl.glGenTextures(1, textureIDs, 0); // Generate texture-ID array
      Log.d(TAG, "gen number = " + textureIDs[0]);
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);   // Bind to texture ID
      // Set up texture filters
      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);

      // Construct an input stream to texture image "res\drawable\nehe.png"
      InputStream istream = context.getResources().openRawResource(R.drawable.crate);
      Bitmap bitmap;
      try {
         // Read and decode input as bitmap
         bitmap = BitmapFactory.decodeStream(istream);
      } finally {
         try {
            istream.close();
         } catch(IOException e) { }
      }

      // Build Texture from loaded bitmap for the currently-bind texture ID
      GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
      bitmap.recycle();
   }
}

SkyBox类

package com.dissertation.dnativeapp;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.util.Log;
/*
 * A photo cube with 6 pictures (textures) on its 6 faces.
 */
public class SkyBox {
    private static final String TAG = "skybox";
    private FloatBuffer vertexBuffer;  // Vertex Buffer
   private FloatBuffer texBuffer;     // Texture Coords Buffer

   private int numFaces = 6;
   private int[] imageFileIDs = {  // Image file IDs
      R.drawable.front3,
      R.drawable.left3,
      R.drawable.back3,
      R.drawable.right3,
      R.drawable.top3,
      R.drawable.bot3
   };
   private int[] textureIDs = new int[numFaces];
   private Bitmap[] bitmap = new Bitmap[numFaces];
   private float cubeHalfSize = 1.2f;

   // Constructor - Set up the vertex buffer
   public SkyBox(Context context) {
      // Allocate vertex buffer. An float has 4 bytes
      ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces);
      vbb.order(ByteOrder.nativeOrder());
      vertexBuffer = vbb.asFloatBuffer();

      // Read images. Find the aspect ratio and adjust the vertices accordingly.
      for (int face = 0; face < numFaces; face++) {
         bitmap[face] = BitmapFactory.decodeStream(
               context.getResources().openRawResource(imageFileIDs[face]));
         int imgWidth = bitmap[face].getWidth();
         int imgHeight = bitmap[face].getHeight();
         float faceWidth = 2.0f;
         float faceHeight = 2.0f;
         // Adjust for aspect ratio
         if (imgWidth > imgHeight) {
            faceHeight = faceHeight * imgHeight / imgWidth; 
         } else {
            faceWidth = faceWidth * imgWidth / imgHeight;
         }
         float faceLeft = -faceWidth / 2;
         float faceRight = -faceLeft;
         float faceTop = faceHeight / 2;
         float faceBottom = -faceTop;

         // Define the vertices for this face
         float[] vertices = {
            faceLeft,  faceBottom, 0.0f,  // 0. left-bottom-front
            faceRight, faceBottom, 0.0f,  // 1. right-bottom-front
            faceLeft,  faceTop,    0.0f,  // 2. left-top-front
            faceRight, faceTop,    0.0f,  // 3. right-top-front
         };
         vertexBuffer.put(vertices);  // Populate
      }
      vertexBuffer.position(0);    // Rewind

      // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces.
      float[] texCoords = {
         0.0f, 1.0f,  // A. left-bottom
         1.0f, 1.0f,  // B. right-bottom
         0.0f, 0.0f,  // C. left-top
         1.0f, 0.0f   // D. right-top
      };
      ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces);
      tbb.order(ByteOrder.nativeOrder());
      texBuffer = tbb.asFloatBuffer();
      for (int face = 0; face < numFaces; face++) {
         texBuffer.put(texCoords);
      }
      texBuffer.position(0);   // Rewind
   }

   // Render the shape
   public void draw(GL10 gl) {
      gl.glFrontFace(GL10.GL_CCW);

      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, texBuffer);

      // front
      gl.glPushMatrix();
      gl.glTranslatef(0f, 0f, cubeHalfSize);
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // left
      gl.glPushMatrix();
      gl.glRotatef(270.0f, 0f, 1f, 0f);
      gl.glTranslatef(0f, 0f, cubeHalfSize);
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[1]);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
      gl.glPopMatrix();

      // back
      gl.glPushMatrix();
      gl.glRotatef(180.0f, 0f, 1f, 0f);
      gl.glTranslatef(0f, 0f, cubeHalfSize);
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[2]);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
      gl.glPopMatrix();

      // right
      gl.glPushMatrix();
      gl.glRotatef(90.0f, 0f, 1f, 0f);
      gl.glTranslatef(0f, 0f, cubeHalfSize);
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[3]);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
      gl.glPopMatrix();

      // top
      gl.glPushMatrix();
      gl.glRotatef(270.0f, 1f, 0f, 0f);
      gl.glTranslatef(0f, 0f, cubeHalfSize);
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[4]);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
      gl.glPopMatrix();

      // bottom
      gl.glPushMatrix();
      gl.glRotatef(90.0f, 1f, 0f, 0f);
      gl.glTranslatef(0f, 0f, cubeHalfSize);
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[5]);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
      gl.glPopMatrix();

      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
   }

   // Load images into 6 GL textures
   public void loadTexture(GL10 gl) {
      gl.glGenTextures(6, textureIDs, 0); // Generate texture-ID array for 6 IDs

      Log.d(TAG, "gen number = " + textureIDs[0]);
      // Generate OpenGL texture images
      for (int face = 0; face < numFaces; face++) {
          Log.d(TAG, "gen number " + face + " = " + textureIDs[face]);
         gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]);
         // Build Texture from loaded bitmap for the currently-bind texture ID
         GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0);
         bitmap[face].recycle();
      }
   }
}

MyGLRenderer

package com.dissertation.dnativeapp;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.util.Log;

import com.dissertation.dnativeapp.GVariables;

public class MyGLRenderer implements GLSurfaceView.Renderer {

   private static final String TAG = "render";
   private Context context;   // Application context needed to read image (NEW)
   private TexturedCube cube;
   private Cube cube1;
   private SkyBox skybox;
   private int scene;
   private int number;

// For controlling cube's z-position, x and y angles and speeds (NEW)
   float angleX = 0;   
   float angleY = 0;  
   float speedX = 0;   
   float speedY = 0;   
   float z = -6.0f;    

   // Constructor
   public MyGLRenderer(Context context) {
      this.context = context;   // Get the application context (NEW)
      cube = new TexturedCube();
      cube1 = new Cube();
      skybox = new SkyBox(context);
      //get scene value
      scene = GVariables.getScene();
   }

   // Call back when the surface is first created or re-created.

   public void onSurfaceCreated(GL10 gl, EGLConfig config) {
      gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  // Set color's clear-value to black
      gl.glClearDepthf(1.0f);            // Set depth's clear-value to farthest
      gl.glEnable(GL10.GL_DEPTH_TEST);   // Enables depth-buffer for hidden surface removal
      gl.glDepthFunc(GL10.GL_LEQUAL);    // The type of depth testing to do
      gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);  // nice perspective view
      gl.glShadeModel(GL10.GL_SMOOTH);   // Enable smooth shading of color
      gl.glDisable(GL10.GL_DITHER);      // Disable dithering for better performance

      if(scene == 1)
      {
          // Setup Texture, each time the surface is created (NEW)
          cube.loadTexture(gl, context);    // Load image into Texture (NEW)
      }
      if(scene == 2)
      {
          skybox.loadTexture(gl);
      }
          gl.glEnable(GL10.GL_TEXTURE_2D);  // Enable texture (NEW)

   }

   // Call back after onSurfaceCreated() or whenever the window's size changes.

   public void onSurfaceChanged(GL10 gl, int width, int height) {
          if (height == 0) height = 1;   // To prevent divide by zero
          float aspect = (float)width / height;

          // Set the viewport (display area) to cover the entire window
          gl.glViewport(0, 0, width, height);

          // Setup perspective projection, with aspect ratio matches viewport
          gl.glMatrixMode(GL10.GL_PROJECTION); // Select projection matrix
          gl.glLoadIdentity();                 // Reset projection matrix
          // Use perspective projection
          GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.f);

          gl.glMatrixMode(GL10.GL_MODELVIEW);  // Select model-view matrix
          gl.glLoadIdentity();                 // Reset

          // You OpenGL|ES display re-sizing code here
          // ......
       }

   // Call back to draw the current frame.

   public void onDrawFrame(GL10 gl) {

      //get number of objects
      Log.d(TAG, "getting number");
      number = GVariables.getNumberOfObjects();
      Log.d(TAG, "number got");
      // Clear color and depth buffers
      gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

      if(scene == 1)
      {
         for(int i = 0; i < number; i++)
         {
              // ----- Render the Cube -----
              gl.glLoadIdentity();                  // Reset the current model-view matrix
              gl.glTranslatef((-3 + (3*i)), 0.0f, z);   // Translate into the screen
              gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
              gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
              gl.glScalef(0.8f, 0.8f, 0.8f);
              cube.draw(gl);
          }
      }
      if(scene == 0)
      {
          for(int i = 0; i < number; i++)
          {
              gl.glLoadIdentity();
              gl.glTranslatef((-3 + (3*i)), 0.0f, z);
              gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
              gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
              gl.glScalef(0.8f, 0.8f, 0.8f);
              cube1.draw(gl);
          }
      }
      if(scene == 2)
      {
          gl.glLoadIdentity();
          gl.glTranslatef(0.0f, 0.0f, z);
          gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
          gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
          gl.glScalef(1.0f, 1.0f, 1.0f);
          skybox.draw(gl);
      }

      // Update the rotational angle after each refresh (NEW)
      angleX += speedX;  
      angleY += speedY;  
   }
}

如果你需要它 MainActivity

package com.dissertation.dnativeapp;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.util.Log;

public class MainActivity extends Activity {
    private static final String TAG = MainActivity.class.getSimpleName();
    int scene;
    int number;
     /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        scene = 0;
        Button basic = (Button) findViewById(R.id.Basic_Button);
        Button textured = (Button) findViewById(R.id.Textured_Button);
        Button complicated = (Button) findViewById(R.id.Complicated_Button);
        final CheckBox cb1 = (CheckBox) findViewById(R.id.checkBox1);
        final CheckBox cb2 = (CheckBox) findViewById(R.id.checkBox2);
        final CheckBox cb3 = (CheckBox) findViewById(R.id.checkBox3);

        cb1.setOnCheckedChangeListener(new OnCheckedChangeListener()
        {

            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) 
            {
                cb2.setChecked(false);
                cb3.setChecked(false);

            }

        });

        cb2.setOnCheckedChangeListener(new OnCheckedChangeListener()
        {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
            {
                cb1.setChecked(false);
                cb3.setChecked(false);
            }
        });

        cb3.setOnCheckedChangeListener(new OnCheckedChangeListener()
        {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
            {
                cb1.setChecked(false);
                cb2.setChecked(false);
            }
        });


        basic.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                if(cb1.isChecked())
                {
                    GVariables.setNumberOfObjects(1);
                }
                else if(cb2.isChecked())
                {
                    GVariables.setNumberOfObjects(2);
                }
                else if(cb3.isChecked())
                {
                    GVariables.setNumberOfObjects(3);
                }
                else
                {
                    GVariables.setNumberOfObjects(1);
                }
                scene = 0;
                GVariables.setScene(scene);
                Intent myIntent = new Intent(view.getContext(), MyGLActivity.class);

                startActivityForResult(myIntent, 0);
            }

        });

        textured.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                if(cb1.isChecked())
                {
                    GVariables.setNumberOfObjects(1);
                }
                else if(cb2.isChecked())
                {
                    GVariables.setNumberOfObjects(2);
                }
                else if(cb3.isChecked())
                {
                    GVariables.setNumberOfObjects(3);
                }
                else
                {
                    GVariables.setNumberOfObjects(1);
                }
                scene = 1;
                GVariables.setScene(scene);
                Intent myIntent = new Intent(v.getContext(), MyGLActivity.class);

                startActivityForResult(myIntent, 0);
            }
        });

        complicated.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                // TODO Auto-generated method stub
                scene = 2;
                GVariables.setScene(scene);
                Intent myIntent = new Intent(v.getContext(), MyGLActivity.class);
                startActivityForResult(myIntent, 0);
            }
        });



    }
}

-edit我无法发布图片,但天空盒的白色面孔

1 个答案:

答案 0 :(得分:2)

我不太确定,但可能是你缺少设置纹理参数:

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

在创建纹理时的“for”循环中(在每次“绑定”调用之后)。

无论如何,你发布了太多代码来阅读这个......