无法在Android打开GLES 2.0中渲染2D图像

时间:2014-01-09 12:22:46

标签: android opengl-es texture2d

我尝试渲染一些2D对象,但我能够做到这一点,但现在我尝试在opengl中渲染一些图像,但它没有显示任何内容。这是我的图像渲染代码。

package com.example.androidinternalmaps;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;

public class ImageObject 
{
    private final Context mActivityContext;

    private final FloatBuffer mCubeTextureCoordinates;
    private int mTextureUniformHandle;
    private int mTextureCoordinateHandle;
    private final int mTextureCoordinateDataSize = 2;
    private int mTextureDataHandle;

    private final String VerShader = 
    "uniform mat4 u_Matrix;"+
    "attribute vec4 a_Position;"+  
    "attribute vec2 a_TextureCoordinates;"+
    "varying vec2 v_TextureCoordinates;"+
    "void main()"+                    
    "{"+                            
        "v_TextureCoordinates = a_TextureCoordinates;"+       
        "gl_Position = u_Matrix * a_Position;"+    
    "}";

    private final String FragShader = 
            "precision mediump float;"+ 
            "uniform sampler2D u_TextureUnit;"+                                         
            "varying vec2 v_TextureCoordinates;"+                                       
            "void main()"+                          
            "{"+                                
                "gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);"+                                   
            "}";

    private final int shaderProgram;    
    private final FloatBuffer vertexBuffer;
    private final ShortBuffer drawListBuffer;
    private int mPositionHandle;
    private int mColorHandle;
    private int mMVPMatrixHandle;

    static final int COORDS_PER_VERTEX = 2;
    static float spriteCoords[] = { -0.5f,  0.5f,   // top left
                                -0.5f, -0.5f,   // bottom left
                                 0.5f, -0.5f,   // bottom right
                                 0.5f,  0.5f }; //top right

    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; //Order to draw vertices
    private final int vertexStride = COORDS_PER_VERTEX * 4; //Bytes per vertex

    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    public ImageObject(final Context activityContext)
    {
        mActivityContext = activityContext;

        ByteBuffer bb = ByteBuffer.allocateDirect(spriteCoords.length * 4); 
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(spriteCoords);
        vertexBuffer.position(0);

        final float[] cubeTextureCoordinateData =
        {                                               
            -0.5f,  0.5f,
            -0.5f, -0.5f,
             0.5f, -0.5f,
             0.5f,  0.5f
        };

        mCubeTextureCoordinates = ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);

        //Initialize byte buffer for the draw list
        ByteBuffer dlb = ByteBuffer.allocateDirect(spriteCoords.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);

        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, VerShader);
        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, FragShader);

        shaderProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(shaderProgram, vertexShader);
        GLES20.glAttachShader(shaderProgram, fragmentShader);

        //Texture Code
        GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");

        GLES20.glLinkProgram(shaderProgram);

        //Load the texture
        mTextureDataHandle = loadTexture(mActivityContext, R.drawable.air_hockey_surface);
    }

    public void Draw(float[] mvpMatrix)
    {
        //Add program to OpenGL ES Environment
        GLES20.glUseProgram(shaderProgram);

        //Get handle to vertex shader's vPosition member
        mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");

        //Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(mPositionHandle);

        //Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);

        //Get Handle to Fragment Shader's vColor member
        mColorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor");

        //Set the Color for drawing the triangle
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);

        //Set Texture Handles and bind Texture
        mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture");
        mTextureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "a_TexCoordinate");

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

        //Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
        GLES20.glUniform1i(mTextureUniformHandle, 0); 

        //Pass in the texture coordinate information
        mCubeTextureCoordinates.position(0);
        GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
        GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);

        //Get Handle to Shape's Transformation Matrix
        mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");

        //Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

        //Draw the triangle
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        //Disable Vertex Array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

    public static int loadTexture(final Context context, final int resourceId)
    {
        final int[] textureHandle = new int[1];

        GLES20.glGenTextures(1, textureHandle, 0);

        if (textureHandle[0] != 0)
        {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;   // No pre-scaling

        // Read in the resource
        final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);

        // Bind to the texture in OpenGL
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

        // Set filtering
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

        // Load the bitmap into the bound texture.
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

        // Recycle the bitmap, since its data has been loaded into OpenGL.
        bitmap.recycle();
        }

        if (textureHandle[0] == 0)
        {
        throw new RuntimeException("Error loading texture.");
        }

        return textureHandle[0];
    }
}

没有显示任何内容。只是空白屏幕。我不知道我做错了什么。需要帮忙。谢谢。

我的渲染器类

package com.example.androidinternalmaps;


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;

public class MyGLRenderer implements GLSurfaceView.Renderer {

    private FloorPolygon floorPolygon;
    private ImageObject imageObject;
    private final float[] mMVPMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];
    private final float[] mRotationMatrix = new float[16];

    private float originX = 0.0f, originY = 0.0f;
    private float translationDx=0.0f,translationDy=0.0f;
    private float originScaleX = 2.5f, originScaleY = 2.5f;
    private float scaleDx = 1.0f, scaleDy = 1.0f; 
    private float surfaceViewWidth, surfaceViewHeight;
    private Context mContext;

    public MyGLRenderer(Context context)
    {
        mContext = context;
    }
    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    floorPolygon = new FloorPolygon();
    imageObject = new ImageObject(mContext);
    }

    public void onDrawFrame(GL10 unused) 
    {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    Matrix.translateM(mMVPMatrix, 0, originX+translationDx, originY+translationDy, 0.0f);
    Matrix.scaleM(mMVPMatrix, 0, scaleDx*originScaleX, scaleDy*originScaleY, 0.0f);

    imageObject.Draw(mMVPMatrix);
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) 
    {
        surfaceViewHeight = height;
        surfaceViewWidth = width;

    GLES20.glViewport(0, 0, width, height);
    GLES20.glViewport(0, 0, width, height);
    float ratio = (float) width / height;
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
    }

    public static int loadShader(int type, String shaderCode)
    {
    int shader = GLES20.glCreateShader(type);
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);

    return shader;
    }

    public void setTranslationPoints(float translationDx, float translationDy)
    {
        this.translationDx = ((translationDx/surfaceViewWidth)*2);
        this.translationDy = -((translationDy/surfaceViewHeight)*2);
    }

    public void setScalePoints(float scaleDx, float scaleDy)
    {
        this.scaleDx = scaleDx;
        this.scaleDy = scaleDy;
    }
}

1 个答案:

答案 0 :(得分:1)

我认为有一个问题是:

Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

您的外观向量是(0,0,0),它不描述方向。您的眼睛位置是(0,0,5),表示从原点沿z轴朝向您的位置。所以你的外观矢量需要远离你回到原点。因此,请尝试将外观向量更改为(0,0,-1):

Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, -1f, 0f, 1.0f, 0.0f);

编辑:

对于初学者来说,将其移到onSurfaceChanged,因为你不需要在每一帧上调用它,就像表面构造一样:

Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, -1f, 0f, 1.0f, 0.0f);

现在为ImageObject类。在顶点着色器中,将“a_TextureCoordinates”更改为“a_TexCoordinate”,以使该名称与您在构造函数代码中使用的名称相匹配。

在构造函数中,进行此更改:

//GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");
GLES20.glBindAttribLocation(shaderProgram, 0, "a_Position");
GLES20.glBindAttribLocation(shaderProgram, 1, "a_TexCoordinate");

在将“a_TexCoordinate”绑定到位置0之前,它应该是位置1,因为它是着色器中的第二个属性。着色器中的第一个属性是“a_Position”,因此应绑定到位置0。

在Draw中,进行以下更改:

//mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "a_Position");

//mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture");
mTextureUniformHandle = GLES20.glGetUniformLocation(shaderProgram, "u_TextureUnit");

//mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "u_Matrix");

这是因为名称与着色器中的名称无法正确匹配。对于纹理处理程序,这是一个Uniform,而不是一个Attribute,因此你需要使用glGetUniformLocation。

我认为应该是这样。我运行了你的代码,我在屏幕上绘制了一个纹理。