2014-07-16 1 views
1

Android 용 단순한 게임 인 Dots를 개발했습니다. 화면에 점이 사라지기 전에 점을 찍는 임무가 주어집니다. 그 중 하나를 제외하고 지금까지 재생 된 모든 장치에서 게임이 올바르게 작동합니다. 안드로이드 4.1.2와 함께 일부 장치에서 실행에도 불구하고, 게임은 안드로이드 4.1.2를 실행하는 삼성 갤럭시 노트 10.1 (나는 믿습니다)에 서클 (OpenGL ES 2.0으로 그려진)을 렌더링하지 않을 것입니다. 앱의 다른 모든면은 올바르게 작동하지만 원은 화면에 그려지지 않습니다. 내가 처분 할 수 있도록 테스트 용 Nexus 10과 HTC One m7이 있으므로 휴대 전화보다 큰 기기에서 게임이 제대로 작동한다는 것을 알고 있습니다. 스택 오버플로에 대한 다른 질문과 유사하다면 사과하지만 스택 오버플로 및 다른 웹 사이트에서 솔루션을 찾으려고합니다. 문제의 기기를 갖고 있지 않기 때문에 Google Play 패치를 배포하지 않고 수정본이 작동하는지 여부를 테스트하는 것이 더 어렵습니다. 여러분들의 도움에 감사 드리며 필요할 경우 도움을 줄 코드를 게시 할 의향이 있습니다! 미리 감사드립니다. 참고로 OpenGL ES 2.0은 대부분의 Android 기기에서 모양을 렌더링하지만 모두는 아닙니다.

가 여기 내 서클 생성자입니다 : 내 CircleRenderer

public class Circle { 

public FloatBuffer vertexBuffer; 
public float[] circleCoords = new float[364*3];  //changed to public 
public final int mProgram; 
public int mPositionHandle; 
public int mColorHandle; 
public int mMVPMatrixHandle; 

public final int vertexCount = circleCoords.length/3; 

float color[] = {0.0f, 0.0f, 0.0f, 1.0f}; 


public Circle(int w, int h){ 

    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;" + //took out uMVPMatrix part, adding it back in makes the circle unrenderable 
        "}"; 

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



    circleCoords[0] = (float) -0.82*w/h + (float)(Math.random() * (0.72*w/h + 0.82*w/h)); 
    circleCoords[1] = (float) -0.82 + (float)(Math.random() * (0.72 + 0.82)); 
    circleCoords[2] = 0; 


    //set up values for all coordinates (2-D) 
    for (int i = 1; i < vertexCount; i++){ 
     circleCoords[(i*3)] = (float) (0.12*Math.cos((3.1416/180) * (float) i) + circleCoords[0]); 
     circleCoords[(i*3)+1] = (float) (0.12*Math.sin((3.1416/180) * (float) i) + circleCoords[1]); 
     circleCoords[(i*3)+2] = 0 + circleCoords[2]; 

    } 


    //allocate number of coords * 4 bytes per coord 
    //changing this from allocate to allocateDirect fixed the rendering issue about using native order buffer 
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(circleCoords.length * 4); 

    //use device hardware's native byteorder 
    byteBuffer.order(ByteOrder.nativeOrder()); 

    //create floating point buffer from the ByteBuffer 
    vertexBuffer = byteBuffer.asFloatBuffer(); 

    //add coordinates to float buffer 
    vertexBuffer.put(circleCoords); 

    //set buffer to read from first position 
    vertexBuffer.position(0); 

    int vertexShader = CircleRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); 
    int fragmentShader = CircleRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); 

    mProgram = GLES20.glCreateProgram(); 
    GLES20.glAttachShader(mProgram, vertexShader); 
    GLES20.glAttachShader(mProgram, fragmentShader); 
    GLES20.glLinkProgram(mProgram); 



} 
public void draw(float[] mvpMatrix){ 
    //add program to opengles environment 
    GLES20.glUseProgram(mProgram); 

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

    //enable a handle to the circle vertices 
    GLES20.glEnableVertexAttribArray(mPositionHandle); 

    //prepare the circle's coordinate data 
    GLES20.glVertexAttribPointer(
      mPositionHandle, 3,   //coords per vertex is 3 
      GLES20.GL_FLOAT, false, 
      12, vertexBuffer);   //colors per coord * coords per vertex 


    //enable a handle to the circle vertices 
    //GLES20.glEnableVertexAttribArray(mPositionHandle); 

    // 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"); 
    //CircleRenderer.checkGlError("glGetUniformLocation");     //if errors persist, uncomment this out 

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


    // Draw the circle as filled shape 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount); 



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

} 

}

그리고 여기

public class CircleRenderer implements GLSurfaceView.Renderer { 

//private static final String TAG = "CircleRenderer"; 
//changed to public 
public Circle mCircle; 
//public Circle m2Circle; 

private final float[] mMVPMatrix = new float[16]; 
private final float[] mProjectionMatrix = new float[16]; 
private final float[] mViewMatrix = new float[16]; 

public void onSurfaceCreated(GL10 unused, EGLConfig config){ 


    GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 


    //mCircle = new Circle(); 

} 

public void onDrawFrame(GL10 unused){ 


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

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

    //Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); 

    // Draw circle 
    mCircle.draw(mMVPMatrix); 


} 

public void onSurfaceChanged(GL10 unused, int width, int height){ 

    GLES20.glViewport(0, 0, width, height); 

    float ratio = (float) width/height; 

    // this projection matrix is applied to object coordinates 
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 


    //Log.d("Width in onSurfaceChanged is", width+""); 
    mCircle = new Circle(width, height); 

    //m2Circle = new Circle(width, height); 


} 

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

/** 
* Utility method for debugging OpenGL calls. Provide the name of the call 
* just after making it: 
* 
* If the operation is not successful, the check throws an error. 
* 
* param glOperation - Name of the OpenGL call to check. 
*/ 
//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); 
    //} 
//} 


public void clearCircle(){ //does clear screen 

    mCircle.color[0] = 1.0f; 
    mCircle.color[1] = 1.0f; 
    mCircle.color[2] = 1.0f; 
} 


public void newCircle(float radius, String newColor, int w, int h){ 


    float max = (float)(1 - radius*0.12 - 0.06); //initially 0.83 
    float min = (float)(0.9 - radius*0.12 - 0.06); //initially 0.73 

    mCircle.circleCoords[0] = -max*w/h + (float)(Math.random() * (min*w/h + max*w/h)); 
    mCircle.circleCoords[1] = -max + (float)(Math.random() * (min + max)); 
    mCircle.circleCoords[2] = 0; 


    //set up values for all coordinates (2-D) 
    for (int i = 1; i < mCircle.vertexCount; i++){ 
     mCircle.circleCoords[(i*3)] = (float) (0.12*radius*Math.cos((3.1416/180) * (float) i) + mCircle.circleCoords[0]); 
     mCircle.circleCoords[(i*3)+1] = (float) (0.12*radius*Math.sin((3.1416/180) * (float) i) + mCircle.circleCoords[1]); 
     mCircle.circleCoords[(i*3)+2] = 0 + mCircle.circleCoords[2]; 

    } 

    int color = 0; 
    if (newColor.equals("Black")) 
     color = 0; 
    else if(newColor.equals("Red")) 
     color = 1; 
    else if (newColor.equals("Green")) 
     color = 2; 
    else if (newColor.equals("Blue")) 
     color = 3; 
    else if (newColor.equals("Yellow")) 
     color = 4; 
    else if (newColor.equals("Purple")) 
     color = 5; 
    else if (newColor.equals("LightBlue")) 
     color = 6; 
    else if (newColor.equals("darkRed")) 
     color = 7; 
    else if (newColor.equals("darkRed")) 
     color = 8; 
    else if (newColor.equals("darkBlue")) 
     color = 9; 
    else if (newColor.equals("brownGreen")) 
     color = 10; 
    else if (newColor.equals("darkPurple")) 
     color = 11; 
    else if (newColor.equals("Teal")) 
     color = 12; 

    switch (color) { //set colors 
     case 0: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 0.0f; 
      break; 

     case 1: 
      mCircle.color[0] = 1.0f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 0.0f; 
      break; 

     case 2: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 1.0f; 
      mCircle.color[2] = 0.0f; 
      break; 

     case 3: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 1.0f; 
      break; 

     case 4: 
      mCircle.color[0] = 1.0f; 
      mCircle.color[1] = 1.0f; 
      mCircle.color[2] = 0.0f; 
      break; 

     case 5: 
      mCircle.color[0] = 1.0f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 1.0f; 
      break; 

     case 6: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 1.0f; 
      mCircle.color[2] = 1.0f; 
      break; 

     case 7: 
      mCircle.color[0] = 0.5f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 0.0f; 
      break; 

     case 8: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 0.5f; 
      mCircle.color[2] = 0.0f; 
      break; 

     case 9: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 0.5f; 
      break; 

     case 10: 
      mCircle.color[0] = 0.5f; 
      mCircle.color[1] = 0.5f; 
      mCircle.color[2] = 0.0f; 
      break; 

     case 11: 
      mCircle.color[0] = 0.5f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 0.5f; 
      break; 

     case 12: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 0.5f; 
      mCircle.color[2] = 0.5f; 
      break; 

     default: 
      mCircle.color[0] = 0.0f; 
      mCircle.color[1] = 0.0f; 
      mCircle.color[2] = 0.0f; 
      break; 

    } 

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(mCircle.circleCoords.length * 4); 

    //use device hardware's native byte order 
    byteBuffer.order(ByteOrder.nativeOrder()); 

    //create floating point buffer from the ByteBuffer 
    mCircle.vertexBuffer = byteBuffer.asFloatBuffer(); 

    //add coordinates to float buffer 
    mCircle.vertexBuffer.put(mCircle.circleCoords); 

    //set buffer to read from first position 
    mCircle.vertexBuffer.position(0); 

} 

마지막으로, 여기 내 GLSurfaceView 클래스의

class CircleGLSurfaceView extends GLSurfaceView { 

public CircleRenderer circleRend; 

//these two variables are for controlling spawn timer 
public Handler spawnHandler; 
public timerRunnable timeRunnable; 

public CircleGLSurfaceView(Context context) { 
    super(context); 

    super.setEGLConfigChooser(8, 8, 8, 8, 16, 0); 
    setEGLContextClientVersion(2); 

    circleRend = new CircleRenderer(); 
    setRenderer(circleRend); 

    //render view only when there is a change in the drawing data 
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 

    //start a new 
    spawnHandler = new Handler(); 
    timeRunnable = new timerRunnable(); 
    spawnHandler.postDelayed(timeRunnable, visibleTime); 


} 

편집 : 나는 그것이 갤럭시 노트에 다소 관련 문제에 도움이되도록 다른 곳에서 읽은 이후로는 super.setEGLConfigChooser 메서드 호출을 추가 2

--edit : solution-- 찾을 수

솔루션은 여기 내가 ARM 말리 400MP GPU

Android OpenGL ES not rasterizing - Matrix multiplication switched

는 당신의 도움에 대해 감사를 안드로이드 4.1.x의를 실행하는 장치에 모양을 렌더링 소유로 가지고 있던 문제를 해결 끝났다!

+0

해당 동작은 GPU 유형에 따라 다를 수 있습니다 (다른 모든 요소가 동일한 OpenGL 컨텍스트를 사용하여 올바르게 그려진 경우). 그 서클들은 약간의 특수하거나 까다로운 기술을 사용하여 그린 것입니까? – marekb

+0

서클은 가능한 한 간단하게 그려집니다. 나는 circle 좌표를 얻기 위해 http://stackoverflow.com/questions/18140117/how-to-draw-basic-circle-in-opengl-es-2-0-android와 sethu의 대답을 사용한다. 저는 단 하나의 원을 그리기 만하기 때문에 화면에 다른 요소가 전혀 없습니다. 그 외, 나는 모양 렌더링 (onDrawFrame, onSurfaceCreated, onSurfaceChanged)에 필요한 세 가지 메서드를 사용하고 있습니다. – BradSnyder

답변

0

정점 당 좌표 수를 확인하십시오.

(매트 4가 곱해지기 때문에) 쉐이더에 vec4가 있어야하지만 정점에는 3 개의 좌표 만 있고 glVertexAttribPointer로는 3 개의 좌표 만 보내면됩니다.

사이드 노트 : 코드를 게시하는 경우 주석 처리 된 코드를 먼저 제거하고 게시 한 댓글이 올바른지 확인하십시오.

+0

그래, 좋은 지적입니다. 주석 처리 된 코드와 주석의 대부분을 제거하는 코드를 편집했습니다. – BradSnyder