2015-12-12 140 views
0

我製作了一個遊戲,可以正確繪製openGL形狀來屏蔽大部分遊戲。但出於某種原因,在遊戲中隨機間隔我得到了1282 glGetUniformLocation錯誤。奇怪的是,它有一段時間的工作,但後來失敗了?OpenGL 2.0 glGetUniformLocation:glError 1282 in draw()

這是堆棧跟蹤

12-12 12:31:54.781: E/AndroidRuntime(2531): FATAL EXCEPTION: GLThread 86993 
12-12 12:31:54.781: E/AndroidRuntime(2531): Process: com.laytonlabs.android.levelup, PID: 2531 
12-12 12:31:54.781: E/AndroidRuntime(2531): java.lang.RuntimeException: glGetUniformLocation: glError 1282 
12-12 12:31:54.781: E/AndroidRuntime(2531):  at com.laytonlabs.android.levelup.MyGLRenderer.checkGlError(MyGLRenderer.java:460) 
12-12 12:31:54.781: E/AndroidRuntime(2531):  at com.laytonlabs.android.levelup.shapes.Shape.draw(Shape.java:240) 
12-12 12:31:54.781: E/AndroidRuntime(2531):  at com.laytonlabs.android.levelup.MyGLRenderer.drawShapes(MyGLRenderer.java:350) 
12-12 12:31:54.781: E/AndroidRuntime(2531):  at com.laytonlabs.android.levelup.MyGLRenderer.drawFixedShapes(MyGLRenderer.java:324) 
12-12 12:31:54.781: E/AndroidRuntime(2531):  at com.laytonlabs.android.levelup.MyGLRenderer.onDrawFrame(MyGLRenderer.java:205) 
12-12 12:31:54.781: E/AndroidRuntime(2531):  at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1531) 
12-12 12:31:54.781: E/AndroidRuntime(2531):  at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248) 

這是生成錯誤(我想),內部Shape.java繪製()函數的部分。

Shape.java

mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
MyGLRenderer.checkGlError("glGetUniformLocation"); 

的下面是用於錯誤堆棧所引用的Java類的完整代碼。

MyGLRenderer.java

package com.laytonlabs.android.levelup; 

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import com.laytonlabs.android.levelup.game.Cell; 
import com.laytonlabs.android.levelup.game.CurrentAnswer; 
import com.laytonlabs.android.levelup.game.Equation; 
import com.laytonlabs.android.levelup.game.Game; 
import com.laytonlabs.android.levelup.game.Level; 
import com.laytonlabs.android.levelup.game.Score; 
import com.laytonlabs.android.levelup.game.Stage; 
import com.laytonlabs.android.levelup.game.Time; 
import com.laytonlabs.android.levelup.shapes.Color; 
import com.laytonlabs.android.levelup.shapes.EquationRectangle; 
import com.laytonlabs.android.levelup.shapes.Hexagon; 
import com.laytonlabs.android.levelup.shapes.InputSquare; 
import com.laytonlabs.android.levelup.shapes.Shape; 
import com.laytonlabs.android.levelup.shapes.StatsRectangle; 

import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.Matrix; 
import android.util.Log; 

public class MyGLRenderer implements GLSurfaceView.Renderer { 

    private static final String TAG = "MyGLRenderer"; 
    private static StatsRectangle levelRectangle; 
    private static StatsRectangle timeRectangle; 
    private static StatsRectangle scoreRectangle; 
    private static EquationRectangle equationRectangle; 
    private static EquationRectangle answerRectangle; 
    private ArrayList<Shape> gridShapes; 
    private ArrayList<Shape> bottomRowShapes; 
    private static ArrayList<Shape> inputShapes; 

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

    private float mMovementY; 
    private float mBottomRowScale; 
    private static String mAnswerText = CurrentAnswer.getLabel(); 
    private boolean isCorrectGuess = false; 
    private boolean renderCorrectGuess = false; 
    private boolean isWrongGuess = false; 
    private boolean renderOutput = false; 

    //To limit the number of renders per second 
    private long startTime; 
    private long endTime; 
    private long timeElapsed; 
    private int currentFrame = 0;    // active frame 
    private int outputCurrentFrame = 0;    // active frame 
    private final int FPS = 33;    // Frames per second 
    private final int FPS_ANIMATION_10 = 10; 
    private final int FPS_ANIMATION_20 = 20; 

    //Reducer values, these are used for animation scenes 
    private float mFPSMovementY; 
    private float mFPSBottomRowScale; 

    private int gridLevel = 0; //The cell layout level in the grid. 
    private int rowLevel = 1; //The current row in the grid user is selected. 

    //Constants for grid presentation 
    private final float CELL_SCALE = 0.3f; 
    private final float CELL_OFFSET_Y = 0.7f; 

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

     // Set the background frame color 
     GLES20.glClearColor(Color.DARK_GREY[0], Color.DARK_GREY[1], Color.DARK_GREY[2], Color.DARK_GREY[3]); 

     startTime = System.currentTimeMillis(); 

     //TODO Add code that sets current answer to whatever the current answer is. 

     //Initialise fixed shapes 
     equationRectangle = new EquationRectangle(-0.35f); 
     answerRectangle = new EquationRectangle(-0.5f); 

     equationRectangle.setShapes(0.2f, Equation.get()); 
     answerRectangle.setShapes(0.3f, mAnswerText); 

     //TODO - Change the below calculations to be align_left, align_centre, align_right, etc. 
     levelRectangle = new StatsRectangle(0 - (Screen.DEFAULT_WIDTH/3), Color.TURQUOISE, Color.TURQUOISE); 
     timeRectangle = new StatsRectangle(0, Color.PURPLE, Color.PURPLE); 
     scoreRectangle = new StatsRectangle(0 + (Screen.DEFAULT_WIDTH/3), Color.TURQUOISE, Color.TURQUOISE); 

     levelRectangle.setShapes(-1f, Level.getLabel()); 
     scoreRectangle.setShapes(-1f, Score.getScoreLabel()); 
     timeRectangle.setShapes(-1f, Time.getTimeRemainingLabel()); 

     setGridShapes(); 
     //Complete the bottom row for inputting guesses 
     bottomRowShapes = new ArrayList<Shape>(); 
     setBottomRowShapes(); 
     buildInputGrid(); 
     setBottomRowScale(1.0f); 
     setFPSBottomRowScale(getBottomRowScale()/FPS_ANIMATION_20); 
     setFPSMovementY((CELL_OFFSET_Y*CELL_SCALE)/FPS_ANIMATION_20); 
    } 

    private void buildInputGrid() { 
     inputShapes = new ArrayList<Shape>(); 

     inputShapes.add(new InputSquare(0.16f, -3.0f, 1.15f, "1")); //1 
     inputShapes.add(new InputSquare(0.16f, -1.8f, 1.15f, "2")); //2 
     inputShapes.add(new InputSquare(0.16f, -0.6f, 1.15f, "3")); //3 
     inputShapes.add(new InputSquare(0.16f, 0.6f, 1.15f, "4")); //4 
     inputShapes.add(new InputSquare(0.16f, 1.8f, 1.15f, "5")); //5 
     inputShapes.add(new InputSquare(0.16f, 3.0f, 1.15f, "6")); //6 
     inputShapes.add(new InputSquare(0.16f, -2.4f,  0, "7")); //7 
     inputShapes.add(new InputSquare(0.16f, -1.2f,  0, "8")); //8 
     inputShapes.add(new InputSquare(0.16f,  0,  0, "9")); //9 
     inputShapes.add(new InputSquare(0.16f, 1.2f,  0, "0")); //0 
     inputShapes.add(new InputSquare(0.16f, 2.4f,  0, "x")); //X - This is to clear input 
    } 

    @Override 
    public void onDrawFrame(GL10 unused) { 

     //We dont need continuous rendering, only needed for animation and time switching 
     endTime = System.currentTimeMillis(); 
     timeElapsed = endTime - startTime; 
     if (timeElapsed < FPS) { 
      try { 
       Log.d(TAG, "Sleeping until "+FPS+" millsecs pass"); 
       Thread.sleep(FPS - timeElapsed); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     startTime = endTime; 

     //Update the timers by deducting timeRemaining 
     Time.update(); 

     Matrix.setIdentityM(mGridModelMatrix, 0); // initialize to identity matrix 
     //Setup the equation display before we start moving the grid around 
     Matrix.setIdentityM(mFixedModelMatrix, 0); // initialize to identity matrix 

     // Draw background color 
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 

     // Enable transparency options for colors. 
     GLES20.glEnable(GLES20.GL_BLEND); 
     GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 

     // Set the camera position (View matrix) 
     Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 

     // Calculate the projection and view transformation 
     Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); 

     //Clone this for use with fixed and grid MVPs 
     mTempMatrix = mMVPMatrix.clone(); 

     // Create a rotation for the triangle 

     // Use the following code to generate constant rotation. 
     // Leave this code out when using TouchEvents. 
     // long time = SystemClock.uptimeMillis() % 4000L; 
     // float angle = 0.090f * ((int) time); 

     drawGridShapes(); 

     drawFixedShapes(); 
    } 

    private void drawGridShapes() {  
     //Start the grid drawing at bottom of screen. 
     Matrix.translateM(mGridModelMatrix, 0, 0, -0.1f, 0); 

     //Move the grid down or up the screen depending on touch events. 
     Matrix.translateM(mGridModelMatrix, 0, 0, mMovementY, 0); 

     // Combine the rotation matrix with the projection and camera view 
     // Note that the mMVPMatrix factor *must be first* in order 
     // for the matrix multiplication product to be correct. 
     //Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); 

     //Add the movement to the matrix 
     Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mGridModelMatrix, 0); 

     if (isCorrectGuess()) { 
      renderCorrectGuess = true; //This is to change the answer text to green inside drawFixedShapes 
      currentFrame++;     // step to next frame 
      setMovementY(getMovementY() - getFPSMovementY()); 
      setBottomRowScale(getBottomRowScale() - getFPSBottomRowScale()); 
      if (currentFrame >= FPS_ANIMATION_20) {   // if end of sequence 
       currentFrame = 0;    // restart sequence 
       setBottomRowScale(1.0f);  // Reset the scale 
       removeBottomRow(); 
       setCorrectGuess(false);   //Mark as false so animation stops and user can make new guess 
      } 
     } 

     //Draw all grid shapes 
     if (isCorrectGuess()) { 
      drawAllShapesAndShrinkBottomRow(mMVPMatrix); 
     } else { 
      drawAllShapes(getGridShapes(), mMVPMatrix); 
     } 
    } 

    private void drawAllShapes(ArrayList<Shape> shapes, float[] mMVPMatrix) { 
     for (Shape shape : shapes) { 
      Log.d(TAG, "Scale Hexagon ("+shape.toString()+") Aft ("+shape.getCentreX()+", "+shape.getCentreY()+")"); 
      drawShapes(shape, mMVPMatrix); 
     } 
    } 

    private void drawAllShapesAndShrinkBottomRow(float[] mMVPMatrix) { 
     float[] mMVPScaled = mMVPMatrix.clone(); 

     Matrix.scaleM(mMVPScaled, 0, getBottomRowScale(), getBottomRowScale(), 0); 

     int lastCellIndex = getBottomRowLastCellIndex(); 

     //Apply scaling to the bottom row and just move the other rows. 
     for (int i = 0; i < getGridShapes().size(); i++) { 
      if (i <= lastCellIndex) { 
       drawShapes(getGridShapes().get(i), mMVPScaled); 
      } else { 
       drawShapes(getGridShapes().get(i), mMVPMatrix); 
      } 
     } 
    } 

    private void drawFixedShapes() { 

     Matrix.multiplyMM(mMVPFixed, 0, mTempMatrix, 0, mFixedModelMatrix, 0); 

     if (isRenderOutput()) { 
      //Show the equation using the values from the selected cell. 
      equationRectangle.setShapes(0.2f, Equation.get()); 
      answerRectangle.setShapes(0.3f, mAnswerText); 

      setRenderOutput(false); 
     } 

     //Update the time if time has changed 
     if (!timeRectangle.toString().equals(Time.getTimeRemainingLabel())) { 
      //If the time remaining is almost up then change text to red. 
      if (Time.isTimeAlmostUp()) { 
       timeRectangle.setShapes(-1f, Time.getTimeRemainingLabel(), Color.RED); 
      } else { 
       timeRectangle.setShapes(-1f, Time.getTimeRemainingLabel()); 
      } 
     } 

     //Animation for changing color of the text 
     if (isWrongGuess()) { 
      if (outputCurrentFrame == 0) { 
       answerRectangle.setShapes(0.3f, mAnswerText, Color.RED); 
      } 
      outputCurrentFrame++; 
      if (outputCurrentFrame >= FPS_ANIMATION_10) { 
       outputCurrentFrame = 0; 
       setAnswerText(""); 
       answerRectangle.setShapes(0.3f, mAnswerText); 
       setWrongGuess(false);   
      } 
     } else if (renderCorrectGuess) { 
      if (outputCurrentFrame == 0) { 
       answerRectangle.setShapes(0.3f, mAnswerText, Color.GREEN); 
       levelRectangle.setShapes(-1f, Level.getLabel(), Color.YELLOW); 
       scoreRectangle.setShapes(-1f, Score.getScoreLabel(), Color.YELLOW); 
       timeRectangle.setShapes(-1f, Time.getTimeRemainingLabel(), Color.YELLOW); 
      } 
      outputCurrentFrame++; 
      if (outputCurrentFrame >= FPS_ANIMATION_20) { 
       outputCurrentFrame = 0; 
       answerRectangle.setShapes(0.3f, mAnswerText); 
       levelRectangle.setShapes(-1f, Level.getLabel()); 
       scoreRectangle.setShapes(-1f, Score.getScoreLabel()); 
       timeRectangle.setShapes(-1f, Time.getTimeRemainingLabel()); 
       setGridShapes(); 
       renderCorrectGuess = false;  
      } 
     } 

     drawShapes(answerRectangle, mMVPFixed); 
     drawShapes(equationRectangle, mMVPFixed); 
     drawShapes(levelRectangle, mMVPFixed); 
     drawShapes(timeRectangle, mMVPFixed); 
     drawShapes(scoreRectangle, mMVPFixed); 

     //Draw all input grid shapess 
     drawAllShapes(inputShapes, mMVPFixed); 
    } 

    public static void printStack() { 
     Log.e(TAG,"Level: " + Level.getLabel()); 
     Log.e(TAG,"Score: " + Score.getScoreLabel()); 
     Log.e(TAG,"Time: " + Time.getTimeRemainingLabel()); 
     Log.e(TAG,"mAnswerText: " + mAnswerText); 
     Log.e(TAG,"Equation: " + Equation.get()); 
     for (int i = 0; i < inputShapes.size(); i++) { 
      Log.e(TAG,"inputShapes[" + i + "]: " + inputShapes.get(i).toString()); 
     } 
    } 

    private void drawShapes(Shape parentShape, float[] mMVPMatrix) { 
     parentShape.draw(mMVPMatrix); 

     if (parentShape.getShapes() == null) { 
      return; 
     } 

     for (Shape nestedShapes : parentShape.getShapes()) { 
      nestedShapes.draw(mMVPMatrix); 
     } 
    } 

    private ArrayList<Shape> getGridShapes() { 
     return gridShapes; 
    } 

    private int getBottomRowLastCellIndex() { 
     int lastCellIndex = 0; 
     Shape prevShape = null; 
     for (int i = 0; i < getGridShapes().size(); i++) { 
      if (prevShape == null || getGridShapes().get(i).getCentreY() == prevShape.getCentreY()) { 
       lastCellIndex = i; 
       prevShape = getGridShapes().get(i); 
      } else { 
       return lastCellIndex; 
      } 
     } 
     return lastCellIndex; 
    } 

    private void removeBottomRow() { 
     for (int i = getBottomRowLastCellIndex(); i >= 0 ; i--) { 
      getGridShapes().remove(i); 
     } 
     //Reset the bottom row shapes 
     setBottomRowShapes(); 
    } 

    public ArrayList<Shape> getBottomRowShapes() { 
     return bottomRowShapes; 
    } 

    private void setBottomRowShapes() { 
     ArrayList<Shape> tempRowShapes = new ArrayList<Shape>(); 

     //Apply scaling to the bottom row and just move the other rows. 
     for (int i = 0; i <= getBottomRowLastCellIndex(); i++) { 
      tempRowShapes.add(getGridShapes().get(i)); 
     } 
     bottomRowShapes = tempRowShapes; 
    } 

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

     //Log.d("MyGLRenderer", "Width: " + width + " Height: " + height); 

     float ratio = (float) width/height; 

     Log.d("Screen","Width: "+ width +" - Height: "+ height +" - Ratio: "+ ratio); 

     // this projection matrix is applied to object coordinates 
     // in the onDrawFrame() method 
     if (ratio > 1) { 
      ratio = Screen.DEFAULT_LANDSCAPE_RATIO; 
     } else { 
      ratio = Screen.DEFAULT_PORTRAIT_RATIO; 
     } 

     Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 

     //TODO Store the current answer, the current answer Text and the current Equation. 
    } 

    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 + ": 1glError " + error); 
      printStack(); 
      //TODO - Print out the fixed shapes values to see if something wierd is being displayed after a while. 
      throw new RuntimeException(glOperation + ": glError " + error); 
     } 
    } 

    public float getMovementY() { 
     return mMovementY; 
    } 

    public void setMovementY(float movementY) { 
     mMovementY = movementY; 
    } 

    public float[] getProjectionMatrix() { 
     return mProjectionMatrix; 
    } 

    public float[] getGridModelMatrix() { 
     return mGridModelMatrix; 
    } 

    public float[] getFixedModelMatrix() { 
     return mFixedModelMatrix; 
    } 

    public String getAnswerText() { 
     return mAnswerText; 
    } 

    public void setAnswerText(String guessInput) { 
     if (guessInput == "") { 
      this.mAnswerText = getInputUnderscores(); 
      return; 
     } 

     this.mAnswerText = this.mAnswerText.replaceFirst("_", guessInput); 
    } 

    public void resetAnswerText() { 
     this.mAnswerText = CurrentAnswer.getLabel(); 
    } 

    private String getInputUnderscores() { 
     if (Equation.getExpectedAnswer() <= 0) { 
      return ""; 
     } 

     return Equation.getExpectedAnswerLabel().replaceAll("[0-9]", "_"); 
    } 

    public ArrayList<Shape> getInputShapes() { 
     return inputShapes; 
    } 

Shape.java

package com.laytonlabs.android.levelup.shapes; 

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

import android.opengl.GLES20; 

import com.laytonlabs.android.levelup.MyGLRenderer; 
import com.laytonlabs.android.levelup.Vec2; 
import com.laytonlabs.android.levelup.game.Cell; 

/** 
* A two-dimensional square for use as a drawn object in OpenGL ES 2.0. 
*/ 
public abstract class Shape { 

    private final String TAG = "Shape"; 

    private final String vertexShaderCode = 
      // This matrix member variable provides a hook to manipulate 
      // the coordinates of the objects that use this vertex shader 
      "uniform mat4 uMVPMatrix;" + 
      "attribute vec4 vPosition;" + 
      "void main() {" + 
      // The matrix must be included as a modifier of gl_Position. 
      // Note that the uMVPMatrix factor *must be first* in order 
      // for the matrix multiplication product to be correct. 
      " gl_Position = uMVPMatrix * vPosition;" + 
      "}"; 

    private final String fragmentShaderCode = 
      "precision mediump float;" + 
      "uniform vec4 vColor;" + 
      "void main() {" + 
      " gl_FragColor = vColor;" + 
      "}"; 

    private final FloatBuffer vertexBuffer; 
    private final ShortBuffer drawListBuffer; 
    private final int mProgram; 
    private int mPositionHandle; 
    private int mColorHandle; 
    private int mMVPMatrixHandle; 
    protected float[] shapeCoords; 
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex 

    // number of coordinates per vertex in this array 
    static final int COORDS_PER_VERTEX = 3; 

    //These will be initiated by the abstract class 
    private final float[] ORIGINAL_COORDS; 
    private final short[] DRAW_ORDER; // order to draw vertices 

    //#RGB: white (255, 255, 255) 
    private final float[] COLOR; 

    //Sets the scale of the shape and where the X centre is. 
    private final float SCALE; 
    private final float CENTRE_X; 
    private final float CENTRE_Y; 

    public abstract float getCentreX(); 
    public abstract float getCentreY(); 

    public float[] getNestedTextColor() { 
     return null; 
    } 

    public void setNestedTextColor(float[] textColor) {} 

    public Cell getCell() { 
     return null; 
    } 

    public ArrayList<Shape> getShapes() { 
     return null; 
    } 

    public void setShapes(float scale, String nestedText) {} 

    public void setShapes(float scale, String nestedText, float[] textColor) {} 

    public boolean intersects(Vec2 touchCoords) { 
     return false; 
    } 

    public float getMinX() {return getMin(getArraySubset(0));} 
    public float getMaxX() {return getMax(getArraySubset(0));} 
    public float getMinY() {return getMin(getArraySubset(1));} 
    public float getMaxY() {return getMax(getArraySubset(1));} 

    private float getMin(float[] values) { 
     float minVal = 1000f; 
     for (float value : values) { 
      if (value < minVal) { 
       minVal = value; 
      } 
     } 
     return minVal; 
    } 

    private float getMax(float[] values) { 
     float maxVal = -1000f; 
     for (float value : values) { 
      if (value > maxVal) { 
       maxVal = value; 
      } 
     } 
     return maxVal; 
    } 

    private float[] getArraySubset(int offset) { 
     if (shapeCoords == null || shapeCoords.length == 0) { 
      return null; 
     } 

     float[] subsetArray = new float[shapeCoords.length/COORDS_PER_VERTEX]; 
     int subsetIndex = 0; 

     for (int i = offset; i < shapeCoords.length; i=(i+COORDS_PER_VERTEX)) { 
      subsetArray[subsetIndex] = shapeCoords[i]; 
      subsetIndex++; 
     } 
     return subsetArray; 
    } 

    /** 
    * Sets up the drawing object data for use in an OpenGL ES context. 
    */ 
    public Shape(float[] originalCoords, short[] drawOrder, float[] color, 
      float scale, float centreX, float centreY) { 

     this.ORIGINAL_COORDS = originalCoords; 
     this.DRAW_ORDER = drawOrder; 
     this.COLOR = color; 
     this.SCALE = scale; 
     this.CENTRE_X = centreX; 
     this.CENTRE_Y = centreY; 

     this.shapeCoords = ORIGINAL_COORDS.clone(); 

     adjustShape(scale, centreX, centreY); 
     //Resize based on the scale 
     //adjustSize(scale); 

     // initialize vertex byte buffer for shape coordinates 
     ByteBuffer bb = ByteBuffer.allocateDirect(
     // (# of coordinate values * 4 bytes per float) 
       shapeCoords.length * 4); 
     bb.order(ByteOrder.nativeOrder()); 
     vertexBuffer = bb.asFloatBuffer(); 
     vertexBuffer.put(shapeCoords); 
     vertexBuffer.position(0); 

     // initialize byte buffer for the draw list 
     ByteBuffer dlb = ByteBuffer.allocateDirect(
       // (# of coordinate values * 2 bytes per short) 
       DRAW_ORDER.length * 2); 
     dlb.order(ByteOrder.nativeOrder()); 
     drawListBuffer = dlb.asShortBuffer(); 
     drawListBuffer.put(DRAW_ORDER); 
     drawListBuffer.position(0); 

     // prepare shaders and OpenGL program 
     int vertexShader = MyGLRenderer.loadShader(
       GLES20.GL_VERTEX_SHADER, 
       vertexShaderCode); 
     int fragmentShader = MyGLRenderer.loadShader(
       GLES20.GL_FRAGMENT_SHADER, 
       fragmentShaderCode); 

     mProgram = GLES20.glCreateProgram();    // create empty OpenGL Program 
     GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program 
     GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program 
     GLES20.glLinkProgram(mProgram);     // create OpenGL program executables 
    } 

    //Adjust the original scale of the shape and position 
    private void adjustShape(float scale, float centreX, float centreY) { 
     for (int i = 0; i < shapeCoords.length; i++) { 
      //Apply the scale 
      shapeCoords[i] = (ORIGINAL_COORDS[i] * scale); 

      //Apply the x offset 
      shapeCoords[i] += (i % 3 == 0 ? centreX : 0); 

      //Apply the y offset 
      shapeCoords[i] += (i % 3 == 1 ? centreY : 0); 
     } 
    } 

    /** 
    * Encapsulates the OpenGL ES instructions for drawing this shape. 
    * 
    * @param mvpMatrix - The Model View Project matrix in which to draw 
    * this shape. 
    */ 
    public void draw(float[] mvpMatrix) { 
     // Add program to OpenGL environment 
     GLES20.glUseProgram(mProgram); 

     // get handle to vertex shader's vPosition member 
     mPositionHandle = GLES20.glGetAttribLocation(mProgram, "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(mProgram, "vColor"); 

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

     // get handle to shape's transformation matrix 
     mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
     MyGLRenderer.checkGlError("glGetUniformLocation"); 

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

     // Draw the square 
     GLES20.glDrawElements(
       GLES20.GL_TRIANGLES, DRAW_ORDER.length, 
       GLES20.GL_UNSIGNED_SHORT, drawListBuffer); 

     // Disable vertex array 
     GLES20.glDisableVertexAttribArray(mPositionHandle); 
    } 
} 

回答

1

只有兩個原因glGetUniformLocation會發出GL_INVALID_OPERATION錯誤:因爲程序不是一個程序對象或者因爲它沒有成功鏈接。

我看不到任何代碼,你實際上是test whether glLinkProgram was successful。您從不致電glGetProgramiv(program, GL_LINK_STATUS)來測試程序是否正確鏈接。顯然,鏈接在某個時候失敗了。

錯誤處理(在C++)一般的代碼將是:

//Link the program. 
glLinkProgram(program); 

GLint isLinked = 0; 
glGetProgramiv(program, GL_LINK_STATUS, &isLinked); 
if(isLinked == GL_FALSE) 
{ 
    GLint maxLength = 0; 
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); 

    //The maxLength includes the NULL character 
    std::vector<GLchar> infoLog(maxLength); 
    glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]); 

    //The program is useless now. So delete it. 
    glDeleteProgram(program); 

    //Provide the infolog in whatever manner you deem best. 
    //Exit with failure. 
    return; 
} 
+0

感謝您的答覆。我對opengl很新,所以我很幸運,避免了很多錯誤。我會研究這個鏈接處理程序的Java版本,但是您提供的代碼會在失敗之前嘗試修復問題嗎?從我的代碼中可以看到,如果鏈接失敗,它的應用程序出錯了嗎? –

+0

@MatthewLayton:它從該函數返回。你用這個回報值做什麼取決於你。 –

+0

好的,我添加了你建議的代碼。下面是java版本,但它仍然崩潰?當我看到InfoLog的輸出時,它不顯示任何內容?我看到的只是這個錯誤。那麼這是一個記憶問題? '12-14 09:09:35.889:I/System.out(16537):得到鏈接狀態 12-14 09:09:35.889:E/Shape(16537):程序鏈接錯誤: 12-14 09: 09:35.889:W/Adreno-GSL(16537)::sharedmem_gpumem_alloc:mmap失敗errno 1不允許操作 12-14 09:09:35.889:E/Adreno-GSL(16537)::GSL MEM ERROR:kgsl_sharedmem_alloc ioctl failed.' –