2015-03-31 123 views
0

我跟着official OpenGL ES tutorial创建了一个可用的OpenGL环境。除了显示2D图像之外,我可以做任何我想做的事情。要做到这一点我通过this教程工作,并提出了以下几点:OpenGL ES 2.0 2D图像显示

这里是我的Sprite类:

public class Sprite 
{ 
    //Reference to Activity Context 
    private final Context mActivityContext; 

    //Added for Textures 
    private final FloatBuffer mCubeTextureCoordinates; 
    private int mTextureUniformHandle; 
    private int mTextureCoordinateHandle; 
    private final int mTextureCoordinateDataSize = 2; 
    private int mTextureDataHandle; 

    private final String vertexShaderCode = 
     "attribute vec2 a_TexCoordinate;" + 
       "varying vec2 v_TexCoordinate;" + 
       "uniform mat4 uMVPMatrix;" + 
       "attribute vec4 vPosition;" + 
       "void main() {" + 
       " gl_Position = vPosition * uMVPMatrix;" + 
       "v_TexCoordinate = a_TexCoordinate" + 
       "}"; 

    private final String fragmentShaderCode = 
     "precision mediump float;" + 
       "uniform vec4 vColor;" + 
       "uniform sampler2D u_Texture;" + 
       "varying vec2 v_TexCoordinate;" + 
       "void main() {" + 
       "gl_FragColor = (vColor * texture2D(u_Texture, v_TexCoordinate));" + 
       "}"; 

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

    // number of coordinates per vertex in this array 
    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 

    // Set color with red, green, blue and alpha (opacity) values 
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; 

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

     //Initialize Vertex Byte Buffer for Shape Coordinates/# of coordinate values * 4 bytes per float 
     ByteBuffer bb = ByteBuffer.allocateDirect(spriteCoords.length * 4); 
     //Use the Device's Native Byte Order 
     bb.order(ByteOrder.nativeOrder()); 
     //Create a floating point buffer from the ByteBuffer 
     vertexBuffer = bb.asFloatBuffer(); 
     //Add the coordinates to the FloatBuffer 
     vertexBuffer.put(spriteCoords); 
     //Set the Buffer to Read the first coordinate 
     vertexBuffer.position(0); 

     // S, T (or X, Y) 
     // Texture coordinate data. 
     // Because images have a Y axis pointing downward (values increase as you move down the image) while 
    // OpenGL has a Y axis pointing upward, we adjust for that here by flipping the Y axis. 
    // What's more is that the texture coordinates are the same for every face. 
    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, vertexShaderCode); 
    int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); 

    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.ic_launcher); 
} 

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]; 
} 
} 

这里是MyGLRenderer.java:

public class MyGLRenderer implements GLSurfaceView.Renderer { 

private static final String TAG = "MyGLRenderer"; 
private Context context; 

private Sprite sprite; 

// mMVPMatrix is an abbreviation for "Model View Projection Matrix" 
private final float[] mMVPMatrix = new float[16]; 
private final float[] mProjectionMatrix = new float[16]; 
private final float[] mViewMatrix = new float[16]; 

public MyGLRenderer(Context ctx) { 
    this.context = ctx; 
} 

@Override 
public void onSurfaceCreated(GL10 unused, EGLConfig config) { 

    // Set the background frame color 
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 

    sprite = new Sprite(context); 
} 


@Override 
public void onDrawFrame(GL10 unused) { 
    sprite.draw(mMVPMatrix); 
} 

@Override 
public void onSurfaceChanged(GL10 unused, int width, int height) { 
    // Adjust the viewport based on geometry changes, 
    // such as screen rotation 
    GLES20.glViewport(0, 0, width, height); 

    float ratio = (float) width/height; 

    // this projection matrix is applied to object coordinates 
    // in the onDrawFrame() method 
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 2, 7); 

} 

public static int loadShader(int type, String shaderCode){ 

    // create a vertex shader type (GLES20.GL_VERTEX_SHADER) 
    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) 
    int shader = GLES20.glCreateShader(type); 

    // add the source code to the shader and compile it 
    GLES20.glShaderSource(shader, shaderCode); 
    GLES20.glCompileShader(shader); 

    return shader; 
} 

public static void checkGlError(String glOperation) { 
    int error; 
    while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 
     Log.e(TAG, glOperation + ": glError " + error); 
     throw new RuntimeException(glOperation + ": glError " + error); 
    } 
} 




//NEW 
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]; 
} 

}

我的问题是,该应用程序崩溃与

java.lang.RuntimeException: glGetUniformLocation: glError 1282 

它甚至打开之前。感谢您提前提供任何帮助!

编辑: 我不知道如果这有助于但是当我开始我的应用程序在AVD我收到以下错误:

../../sdk/emulator/opengl//host/libs/Translator/GLES_V2//GLESv2Imp.cpp:glGetAttribLocation:857 error 0x502 
../../sdk/emulator/opengl//host/libs/Translator/GLES_V2//GLESv2Imp.cpp:glGetUniformLocation:1442 error 0x502 
../../sdk/emulator/opengl//host/libs/Translator/GLES_V2//GLESv2Imp.cpp:glGetUniformLocation:1442 error 0x502 
../../sdk/emulator/opengl//host/libs/Translator/GLES_V2//GLESv2Imp.cpp:glGetAttribLocation:857 error 0x502 
../../sdk/emulator/opengl//host/libs/Translator/GLES_V2//GLESv2Imp.cpp:glGetUniformLocation:1442 error 0x502 

回答

0

缺乏一个OpenGL的编译器我忘了一个分号。因此,这

"v_TexCoordinate = a_TexCoordinate" + 

应该是这样的:

"v_TexCoordinate = a_TexCoordinate;" + 

的Alper彻纳尔是正确的,他的答案了。

0

我没有检查所有的,但我想我已经找到代码中存在问题。 u_Texture在您的片段着色器中被定义为一个统一体,但您试图获得它的位置,就好像它是一个属性。

在您的Sprite类的绘制方法中更改此行。

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

这个

mTextureUniformHandle = GLES20.glGetUniformLocation(shaderProgram, "u_Texture"); 
+0

谢谢您的回答,我确实有混合这件事。不幸的是,该应用程序仍然崩溃,同样的例外。 – 2015-04-04 08:51:46

+0

你现在检查了其他代码吗?也许你会发现另一个错误。如果可以的话,会很高兴。 – 2015-04-24 17:01:41

0

的载体在这里订购似有不妥:

"gl_FragColor = (vColor * texture2D(u_Texture, v_TexCoordinate));" + 

您可能要更改,要

"gl_FragColor = texture2D(u_Texture, v_TexCoordinate) * vColor;" +