Java Android OpenGLES2.0-渲染时纯黑色纹理

Java Android OpenGLES2.0-渲染时纯黑色纹理,java,android,opengl-es,opengl-es-2.0,textures,Java,Android,Opengl Es,Opengl Es 2.0,Textures,在过去一周左右的时间里,我一直在制作一个Android OpenGLES2.0 2D游戏引擎,在经历了几次坎坷之后,我基本上取得了成功。我已经实现了ModelMatrix、ProjectionMatrix、ViewMatrix、LightMatrix、着色器、2D平面和纹理。然而,尽管我的数据似乎很好地通过了这片管道丛林,但我的纹理并没有出现,而是一个纯黑色 我的大部分代码(如果不是所有代码都是从中派生出来的话)都是一样的,只是我创建了自己的着色器类、边界框类、房间类和游戏对象类,以简化在游戏中

在过去一周左右的时间里,我一直在制作一个Android OpenGLES2.0 2D游戏引擎,在经历了几次坎坷之后,我基本上取得了成功。我已经实现了ModelMatrix、ProjectionMatrix、ViewMatrix、LightMatrix、着色器、2D平面和纹理。然而,尽管我的数据似乎很好地通过了这片管道丛林,但我的纹理并没有出现,而是一个纯黑色

我的大部分代码(如果不是所有代码都是从中派生出来的话)都是一样的,只是我创建了自己的着色器类、边界框类、房间类和游戏对象类,以简化在游戏中实例化对象的过程。渲染器获取房间,房间获取游戏对象(太空船扩展游戏对象),游戏对象获取边界框,然后渲染器在for循环中渲染房间对象。为此,我移动了示例中的确切代码,以便某些句柄是我创建的某些类的元素,而不是渲染器的元素。这并没有给矩阵乘法或我的数据到达管道末端带来任何问题,所以我怀疑移动句柄是否是问题所在,但我觉得知道这一点很重要

我尝试过的事情:

  • 更改位图
    • 将其更改为没有alpha通道的位图,两者都是32x32(2^5)和.png
  • 改变操作顺序
    • 我在实现中移动了glBindTexture,所以我将其移回,然后再移回
  • 更改纹理参数
    • 我尝试了几种组合,没有一种使用mip映射
  • 更改加载图像的方式
    • 从BitmapFactory.DecodeSource转到BitmapFactory.decodeStream
  • 将纹理移动到所有可绘制文件夹
    • 也在原始文件夹中尝试过
  • 在另一台设备上试用过
    • 我朋友的机器人(Froyo 2.2),我的下一本书(Gingerbread 2.3)。两者都支持OpenGLES2.0
  • 我没有尝试过(我知道的):

  • 更改纹理坐标
    • 它们直接来自示例。我只拍了立方体的一面
  • 更改我的着色器
    • 它也直接来自这个示例(除了它现在是自己的类之外)
  • 将我的程序重组为两个(3,4…x)类
    • 老兄
  • 我已经在模拟器(Eclipse Indigo、AVD、Intel Atom x86、ICS 4.2.2、API level 17)上测试了一段时间,就在我让所有矩阵工作的时候,模拟器没有呈现任何东西。它过去渲染得很好(当投影完全扭曲时),现在它只显示带有标题栏的黑色。这使得调试变得异常困难。我不确定这是否与我所做的(可能是)有关,或者是否与OpenGL的仿真器有关

    很抱歉这么冗长,包含这么多代码,但我不知道如何使用“显示/隐藏”按钮

    有什么想法吗

    编辑:我使用了示例中的错误着色器。这个名字很容易引起误解。我没有传递颜色信息。我仍然没有纹理,但仿真器再次工作。:)

    OpenGLES202DU渲染器

    package mycompany.OpenGLES20_2DEngine;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    
    import android.content.Context;
    import android.opengl.GLES20;
    import android.opengl.GLSurfaceView;
    import android.opengl.Matrix;
    import android.util.Log;
    
    public class OpenGLES20_2DRenderer implements GLSurfaceView.Renderer {
    
    /** Used for debug logs. */
    private static final String TAG = "Renderer";
    
    //Matrix Declarations*************************
    /**
     * Store the model matrix. This matrix is used to move models from object space (where each model can be thought
     * of being located at the center of the universe) to world space.
     */
    private float[] mModelMatrix = new float[16];
    /**
     * Store the view matrix. This can be thought of as our camera. This matrix transforms world space to eye space;
     * it positions things relative to our eye.
     */
    private float[] mViewMatrix = new float[16];
    /** Store the projection matrix. This is used to project the scene onto a 2D viewport. */
    private float[] mProjectionMatrix = new float[16];
    /** Allocate storage for the final combined matrix. This will be passed into the shader program. */
    private float[] mMVPMatrix = new float[16];
    /**
     * Stores a copy of the model matrix specifically for the light position.
     */
    private float[] mLightModelMatrix = new float[16];
    
    //********************************************
    
    //Global Variable Declarations****************
    //Shader
    Shader shader;
    //PointShader
    PointShader pointShader;
    //Application Context
    Context context;
    //A room to add objects to
    Room room;
    //********************************************
    
    public OpenGLES20_2DRenderer(Context ctx) {
        context = ctx;
    }
    
    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    
        //Initialize GLES20***************************
        // Set the background frame color
        GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
        // Use culling to remove back faces.
        GLES20.glEnable(GLES20.GL_CULL_FACE);
        // Enable depth testing
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        // Position the eye in front of the origin.
        final float eyeX = 0.0f;
        final float eyeY = 0.0f;
        final float eyeZ = -0.5f;
        // We are looking toward the distance
        final float lookX = 0.0f;
        final float lookY = 0.0f;
        final float lookZ = -5.0f;
        // Set our up vector. This is where our head would be pointing were we holding the camera.
        final float upX = 0.0f;
        final float upY = 1.0f;
        final float upZ = 0.0f;
        // Set the view matrix. This matrix can be said to represent the camera position.
        // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
        // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
        Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);    
        //********************************************
    
        //Initialize Shaders**************************
        shader = new Shader();
        pointShader = new PointShader();
        //********************************************
    
        //Load The Level******************************
        //Create a new room
        room = new Room(800,600, 0);
        //Load game objects
        SpaceShip user = new SpaceShip();
        //Load sprites
        for(int i=0;i<room.numberOfGameObjects;i++) {
            room.gameObjects[i].spriteGLIndex = room.gameObjects[i].loadSprite(context, room.gameObjects[i].spriteResId);   
        }
        //Add them to the room
        room.addGameObject(user);
        //********************************************
    
    }
    
    public void onDrawFrame(GL10 unused) {
    
        //Caclulate MVPMatrix*************************
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        // Set our per-vertex lighting program.
        GLES20.glUseProgram(shader.mProgram);
        // Set program handles for object drawing.
        shader.mMVPMatrixHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_MVPMatrix");
        shader.mMVMatrixHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_MVMatrix");
        shader.mLightPosHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_LightPos");
        shader.mTextureUniformHandle = GLES20.glGetUniformLocation(shader.mProgram, "u_Texture");
        shader.mPositionHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_Position");
        shader.mColorHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_Color");
        shader.mNormalHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_Normal");
        shader.mTextureCoordinateHandle = GLES20.glGetAttribLocation(shader.mProgram, "a_TexCoordinate");
    
        // Calculate position of the light. Rotate and then push into the distance.
        Matrix.setIdentityM(mLightModelMatrix, 0);
        Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, -5.0f);
        Matrix.rotateM(mLightModelMatrix, 0, 0, 0.0f, 1.0f, 0.0f);
        Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, 2.0f);
        Matrix.multiplyMV(shader.mLightPosInWorldSpace, 0, mLightModelMatrix, 0, shader.mLightPosInModelSpace, 0);
        Matrix.multiplyMV(shader.mLightPosInEyeSpace, 0, mViewMatrix, 0, shader.mLightPosInWorldSpace, 0); 
        //********************************************
    
        //Draw****************************************
        //Draw the background
        //room.drawBackground(mMVPMatrix);
        // Draw game objects
        for(int i=0;i<room.numberOfGameObjects;i++) {
    
            // Set the active texture unit to texture unit 0.
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            // Bind the texture to this unit.
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, room.gameObjects[i].spriteGLIndex);
            // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
            GLES20.glUniform1i(shader.mTextureUniformHandle, 0);
    
            //Set up the model matrix
            Matrix.setIdentityM(mModelMatrix, 0);
            Matrix.translateM(mModelMatrix, 0, 4.0f, 0.0f, -7.0f);
            Matrix.rotateM(mModelMatrix, 0, room.gameObjects[i].rotation, 1.0f, 0.0f, 0.0f); 
    
            //Draw the object
            room.gameObjects[i].draw(mModelMatrix, mViewMatrix, mProjectionMatrix, mMVPMatrix, shader);
        }
        //********************************************
    
        // Draw a point to indicate the light.********
        drawLight();
        //********************************************
    
    }
    
    public void onSurfaceChanged(GL10 unused, int width, int height) {
    
        //Initialize Projection Matrix****************
        // Set the OpenGL viewport to the same size as the surface.
        GLES20.glViewport(0, 0, width, height);
        // Create a new perspective projection matrix. The height will stay the same
        // while the width will vary as per aspect ratio.
        final float ratio = (float) width / height;
        final float left = -ratio;
        final float right = ratio;
        final float bottom = -1.0f;
        final float top = 1.0f;
        final float near = 1.0f;
        final float far = 10.0f;
        Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
        //********************************************
    
    }
    
    // Draws a point representing the position of the light.
    private void drawLight()
    {
        GLES20.glUseProgram(pointShader.mProgram);
        final int pointMVPMatrixHandle = GLES20.glGetUniformLocation(pointShader.mProgram, "u_MVPMatrix");
        final int pointPositionHandle = GLES20.glGetAttribLocation(pointShader.mProgram, "a_Position");
        // Pass in the position.
        GLES20.glVertexAttrib3f(pointPositionHandle, shader.mLightPosInModelSpace[0], shader.mLightPosInModelSpace[1], shader.mLightPosInModelSpace[2]);
        // Since we are not using a buffer object, disable vertex arrays for this attribute.
        GLES20.glDisableVertexAttribArray(pointPositionHandle);
        // Pass in the transformation matrix.
        Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mLightModelMatrix, 0);
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
        GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mMVPMatrix, 0);
        // Draw the point.
        GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
    }
    }
    
    边界框

    package mycompany.OpenGLES20_2DEngine;
    
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    //TODO: make this dynamic, both the constructor and the coordinates.
    class BoundingBox {
    
    //Variable Declarations***********************
    /** How many bytes per float. */
    private final int mBytesPerFloat = 4;
    /** Store our model data in a float buffer. */
    public final FloatBuffer mPositions;
    public final FloatBuffer mColors;
    public final FloatBuffer mNormals;
    public final FloatBuffer mTextureCoordinates;
    //Number of coordinates per vertex in this array
    final int COORDS_PER_VERTEX = 3;
    //Coordinates
    float[] positionData;
    //Texture Coordinates
    float[] textureCoordinateData;
    //Vertex Color
    float[] colorData;
    float[] normalData;
    //Vertex Stride
    final int vertexStride = COORDS_PER_VERTEX * 4;
    /** Size of the position data in elements. */
    public final int mPositionDataSize = 3; 
    /** Size of the color data in elements. */
    public final int mColorDataSize = 4;    
    /** Size of the normal data in elements. */
    public final int mNormalDataSize = 3;
    /** Size of the texture coordinate data in elements. */
    public final int mTextureCoordinateDataSize = 2;
    //********************************************
    
    public BoundingBox(float[] coords) {
        //TODO: Normalize values
        //Set Coordinates and Texture Coordinates*****
        if(coords==null) {
            float[] newPositionData = {
                    // Front face
                    -1.0f, 1.0f, 1.0f,  
                    -1.0f, -1.0f, 1.0f,
                    1.0f, 1.0f, 1.0f,
                    -1.0f, -1.0f, 1.0f,
                    1.0f, -1.0f, 1.0f,
                    1.0f, 1.0f, 1.0f
            };
            positionData = newPositionData;
    
            float[] newColorData = {
                    // Front face (red)
                    1.0f, 0.0f, 0.0f, 1.0f, 
                    1.0f, 0.0f, 0.0f, 1.0f,
                    1.0f, 0.0f, 0.0f, 1.0f,
                    1.0f, 0.0f, 0.0f, 1.0f, 
                    1.0f, 0.0f, 0.0f, 1.0f,
                    1.0f, 0.0f, 0.0f, 1.0f
            };
    
            colorData = newColorData;
    
            float[] newTextureCoordinateData =
                {   
                    // Front face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f, 
                };
            textureCoordinateData = newTextureCoordinateData;
    
            float[] newNormalData = {
                    // Front face
                    0.0f, 0.0f, 1.0f,   
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,   
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f
            };
    
            normalData = newNormalData;
        }
        else {
            positionData = coords;
            //TODO:Reverse coords HERE
            textureCoordinateData = coords;
        }
        //********************************************
    
        //Initialize Buffers**************************
        mPositions = ByteBuffer.allocateDirect(positionData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();    
        mPositions.put(positionData).position(0);   
    
        mColors = ByteBuffer.allocateDirect(colorData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();    
        mColors.put(colorData).position(0);
    
        mNormals = ByteBuffer.allocateDirect(normalData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();    
        mNormals.put(normalData).position(0);
    
        mTextureCoordinates = ByteBuffer.allocateDirect(textureCoordinateData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTextureCoordinates.put(textureCoordinateData).position(0);
        //********************************************
    }
    }
    
    宇宙飞船

    package mycompany.OpenGLES20_2DEngine;
    
    public class SpaceShip extends GameObject{
    
    public SpaceShip() {
        spriteResId = R.drawable.spaceship;
        boundingBox = new BoundingBox(null);
    }
    }
    

    明白了。在加载了太空船的位图(从房间中)后,我将其添加到房间中

    //加载级别******************************
    //创建一个新房间
    房间=新房间(800600,0);
    //加载游戏对象
    太空船用户=新太空船();
    **//加载精灵
    
    因为(int i=0;我不会说谎,因为你说“伙计…”代码墙
    o.o
    同意@BartekBanachewicz…你在这里添加的代码确实比你应该添加的多得多。你不应该期望我们费力地完成所有的工作。最好是尖锐化你的问题。@SebbyJohanns:每次我来到这个网站,用户要么对我的问题不满意,因为代码太多,而他们没有o“涉水”通过它,或者他们因为没有足够的代码而感到不安。所以我问叶:你想要多少代码?请启发我。我尽可能地剪短。所有这些代码都是相关的。你会拿出什么?这真的很令人恼火。
    package mycompany.OpenGLES20_2DEngine;
    
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    //TODO: make this dynamic, both the constructor and the coordinates.
    class BoundingBox {
    
    //Variable Declarations***********************
    /** How many bytes per float. */
    private final int mBytesPerFloat = 4;
    /** Store our model data in a float buffer. */
    public final FloatBuffer mPositions;
    public final FloatBuffer mColors;
    public final FloatBuffer mNormals;
    public final FloatBuffer mTextureCoordinates;
    //Number of coordinates per vertex in this array
    final int COORDS_PER_VERTEX = 3;
    //Coordinates
    float[] positionData;
    //Texture Coordinates
    float[] textureCoordinateData;
    //Vertex Color
    float[] colorData;
    float[] normalData;
    //Vertex Stride
    final int vertexStride = COORDS_PER_VERTEX * 4;
    /** Size of the position data in elements. */
    public final int mPositionDataSize = 3; 
    /** Size of the color data in elements. */
    public final int mColorDataSize = 4;    
    /** Size of the normal data in elements. */
    public final int mNormalDataSize = 3;
    /** Size of the texture coordinate data in elements. */
    public final int mTextureCoordinateDataSize = 2;
    //********************************************
    
    public BoundingBox(float[] coords) {
        //TODO: Normalize values
        //Set Coordinates and Texture Coordinates*****
        if(coords==null) {
            float[] newPositionData = {
                    // Front face
                    -1.0f, 1.0f, 1.0f,  
                    -1.0f, -1.0f, 1.0f,
                    1.0f, 1.0f, 1.0f,
                    -1.0f, -1.0f, 1.0f,
                    1.0f, -1.0f, 1.0f,
                    1.0f, 1.0f, 1.0f
            };
            positionData = newPositionData;
    
            float[] newColorData = {
                    // Front face (red)
                    1.0f, 0.0f, 0.0f, 1.0f, 
                    1.0f, 0.0f, 0.0f, 1.0f,
                    1.0f, 0.0f, 0.0f, 1.0f,
                    1.0f, 0.0f, 0.0f, 1.0f, 
                    1.0f, 0.0f, 0.0f, 1.0f,
                    1.0f, 0.0f, 0.0f, 1.0f
            };
    
            colorData = newColorData;
    
            float[] newTextureCoordinateData =
                {   
                    // Front face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f, 
                };
            textureCoordinateData = newTextureCoordinateData;
    
            float[] newNormalData = {
                    // Front face
                    0.0f, 0.0f, 1.0f,   
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,   
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f
            };
    
            normalData = newNormalData;
        }
        else {
            positionData = coords;
            //TODO:Reverse coords HERE
            textureCoordinateData = coords;
        }
        //********************************************
    
        //Initialize Buffers**************************
        mPositions = ByteBuffer.allocateDirect(positionData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();    
        mPositions.put(positionData).position(0);   
    
        mColors = ByteBuffer.allocateDirect(colorData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();    
        mColors.put(colorData).position(0);
    
        mNormals = ByteBuffer.allocateDirect(normalData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();    
        mNormals.put(normalData).position(0);
    
        mTextureCoordinates = ByteBuffer.allocateDirect(textureCoordinateData.length * mBytesPerFloat)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTextureCoordinates.put(textureCoordinateData).position(0);
        //********************************************
    }
    }
    
    package mycompany.OpenGLES20_2DEngine;
    
    public class SpaceShip extends GameObject{
    
    public SpaceShip() {
        spriteResId = R.drawable.spaceship;
        boundingBox = new BoundingBox(null);
    }
    }
    
        //Load The Level******************************
        //Create a new room
        room = new Room(800,600, 0);
        //Load game objects
        SpaceShip user = new SpaceShip();
        **//Load sprites
        for(int i=0;i<room.numberOfGameObjects;i++) {
            room.gameObjects[i].spriteGLIndex = room.gameObjects[i].loadSprite(context, room.gameObjects[i].spriteResId);   
        }
        //Add them to the room
        room.addGameObject(user);**
        //********************************************