2013-07-16 51 views
3

因此我從http://www.learnopengles.com/android-lesson-one-getting-started/開始編碼,並試圖繪製一個正方形(同時仍然保留其他所有內容)。無論出於何種原因,它顯示爲一個三角形。我的代碼將在下面提供。我知道要更改GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,4),但我無法找出我還缺少什麼。不能在OpenGL ES 2.0中爲Android繪製方塊,但可以繪製三角形

此外,有沒有更好的方法來了解如何使用GLES20類中的函數? http://developer.android.com/reference/android/opengl/GLES20.html在提供參數方面做得很好,但沒有解釋每個參數的作用。

我想我的錯誤是在我的代碼的底部,可能在函數drawSquare中,但整個文件將粘貼在這裏,以防萬一我誤會了。

public class LessonOneRenderer implements GLSurfaceView.Renderer 
{/** 
* 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]; 

/** Store our model data in a float buffer. */ 
private final FloatBuffer mTriangle1Vertices; 
private final FloatBuffer mTriangle2Vertices; 
private final FloatBuffer mTriangle3Vertices; 

private final FloatBuffer mSquare1Vertices; 

/** This will be used to pass in the transformation matrix. */ 
private int mMVPMatrixHandle; 

/** This will be used to pass in model position information. */ 
private int mPositionHandle; 

/** This will be used to pass in model color information. */ 
private int mColorHandle; 

/** How many bytes per float. */ 
private final int mBytesPerFloat = 4; 

/** How many elements per vertex. */ 
private final int mStrideBytes = 7 * mBytesPerFloat;  

/** Offset of the position data. */ 
private final int mPositionOffset = 0; 

/** Size of the position data in elements. */ 
private final int mPositionDataSize = 3;  

/** Offset of the color data. */ 
private final int mColorOffset = 3; 

/** Size of the color data in elements. */ 
private final int mColorDataSize = 4;  

/** 
* Initialize the model data. 
*/ 
public LessonOneRenderer() 
{ 
    // Define points for equilateral triangles. 

    // This triangle is red, green, and blue. 
    final float[] triangle1VerticesData = { 
      // X, Y, Z, 
      // R, G, B, A 
      -0.5f, -0.25f, 0.0f, 
      1.0f, 0.0f, 0.0f, 1.0f, 

      0.5f, -0.25f, 0.0f, 
      0.0f, 0.0f, 1.0f, 1.0f, 

      0.0f, 0.559016994f, 0.0f, 
      0.0f, 1.0f, 0.0f, 1.0f}; 

    // This triangle is yellow, cyan, and magenta. 
    final float[] triangle2VerticesData = { 
      // X, Y, Z, 
      // R, G, B, A 
      -0.5f, -0.25f, 0.0f, 
      1.0f, 1.0f, 0.0f, 1.0f, 

      0.5f, -0.25f, 0.0f, 
      0.0f, 1.0f, 1.0f, 1.0f, 

      0.0f, 0.559016994f, 0.0f, 
      1.0f, 0.0f, 1.0f, 1.0f}; 

    // This triangle is white, gray, and black. 
    final float[] triangle3VerticesData = { 
      // X, Y, Z, 
      // R, G, B, A 
      -0.5f, -0.25f, 0.0f, 
      1.0f, 1.0f, 1.0f, 1.0f, 

      0.5f, -0.25f, 0.0f, 
      0.5f, 0.5f, 0.5f, 1.0f, 

      0.0f, 0.559016994f, 0.0f, 
      0.0f, 0.0f, 0.0f, 1.0f}; 

    final float[] square1VerticesData = { 
      //topleft 
      -0.25f, 0.25f, -.5f, 
      1.0f, 0.0f, 0.0f, 1.0f, 
      //top right 
      0.25f,0.25f, -.5f, 
      0.0f, 1.0f, 0.0f, 1.0f, 
      //bottom left 
      -0.25f, -0.25f, -.5f, 
      1.0f, 0.0f, 0.0f, 1.0f, 
      //right 
      0.25f, -0.25f, -.5f, 
      1.0f, 0.0f, 0.0f, 1.0f}; 



    // Initialize the buffers. 
    mTriangle1Vertices = ByteBuffer.allocateDirect(triangle1VerticesData.length * mBytesPerFloat) 
    .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
    mTriangle2Vertices = ByteBuffer.allocateDirect(triangle2VerticesData.length * mBytesPerFloat) 
    .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
    mTriangle3Vertices = ByteBuffer.allocateDirect(triangle3VerticesData.length * mBytesPerFloat) 
    .order(ByteOrder.nativeOrder()).asFloatBuffer(); 

    mSquare1Vertices = ByteBuffer.allocateDirect(square1VerticesData.length * mBytesPerFloat) 
    .order(ByteOrder.nativeOrder()).asFloatBuffer(); 

    mTriangle1Vertices.put(triangle1VerticesData).position(0); 
    mTriangle2Vertices.put(triangle2VerticesData).position(0); 
    mTriangle3Vertices.put(triangle3VerticesData).position(0); 
    mSquare1Vertices.put(square1VerticesData).position(0); 
} 

@Override 
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
{ 
    // Set the background clear color to gray. 
    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f); 

    // Position the eye behind the origin. 
    final float eyeX = 0.0f; 
    final float eyeY = 0.0f; 
    final float eyeZ = 1.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); 

    final String vertexShader = 
     "uniform mat4 u_MVPMatrix;  \n"  // A constant representing the combined model/view/projection matrix. 

     + "attribute vec4 a_Position;  \n"  // Per-vertex position information we will pass in. 
     + "attribute vec4 a_Color;  \n"  // Per-vertex color information we will pass in.    

     + "varying vec4 v_Color;   \n"  // This will be passed into the fragment shader. 

     + "void main()     \n"  // The entry point for our vertex shader. 
     + "{        \n" 
     + " v_Color = a_Color;   \n"  // Pass the color through to the fragment shader. 
               // It will be interpolated across the triangle. 
     + " gl_Position = u_MVPMatrix \n"  // gl_Position is a special variable used to store the final position. 
     + "    * a_Position; \n"  // Multiply the vertex by the matrix to get the final point in                 
     + "}        \n"; // normalized screen coordinates. 

    final String fragmentShader = 
     "precision mediump float;  \n"  // Set the default precision to medium. We don't need as high of a 
               // precision in the fragment shader.     
     + "varying vec4 v_Color;   \n"  // This is the color from the vertex shader interpolated across the 
               // triangle per fragment.    
     + "void main()     \n"  // The entry point for our fragment shader. 
     + "{        \n" 
     + " gl_FragColor = v_Color;  \n"  // Pass the color directly through the pipeline.   
     + "}        \n";             

    // Load in the vertex shader. 
    int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); 

    if (vertexShaderHandle != 0) 
    { 
     // Pass in the shader source. 
     GLES20.glShaderSource(vertexShaderHandle, vertexShader); 

     // Compile the shader. 
     GLES20.glCompileShader(vertexShaderHandle); 

     // Get the compilation status. 
     final int[] compileStatus = new int[1]; 
     GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 

     // If the compilation failed, delete the shader. 
     if (compileStatus[0] == 0) 
     {    
      GLES20.glDeleteShader(vertexShaderHandle); 
      vertexShaderHandle = 0; 
     } 
    } 

    if (vertexShaderHandle == 0) 
    { 
     throw new RuntimeException("Error creating vertex shader."); 
    } 

    // Load in the fragment shader shader. 
    int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); 

    if (fragmentShaderHandle != 0) 
    { 
     // Pass in the shader source. 
     GLES20.glShaderSource(fragmentShaderHandle, fragmentShader); 

     // Compile the shader. 
     GLES20.glCompileShader(fragmentShaderHandle); 

     // Get the compilation status. 
     final int[] compileStatus = new int[1]; 
     GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 

     // If the compilation failed, delete the shader. 
     if (compileStatus[0] == 0) 
     {    
      GLES20.glDeleteShader(fragmentShaderHandle); 
      fragmentShaderHandle = 0; 
     } 
    } 

    if (fragmentShaderHandle == 0) 
    { 
     throw new RuntimeException("Error creating fragment shader."); 
    } 

    // Create a program object and store the handle to it. 
    int programHandle = GLES20.glCreateProgram(); 

    if (programHandle != 0) 
    { 
     // Bind the vertex shader to the program. 
     GLES20.glAttachShader(programHandle, vertexShaderHandle);   

     // Bind the fragment shader to the program. 
     GLES20.glAttachShader(programHandle, fragmentShaderHandle); 

     // Bind attributes 
     GLES20.glBindAttribLocation(programHandle, 0, "a_Position"); 
     GLES20.glBindAttribLocation(programHandle, 1, "a_Color"); 

     // Link the two shaders together into a program. 
     GLES20.glLinkProgram(programHandle); 

     // Get the link status. 
     final int[] linkStatus = new int[1]; 
     GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0); 

     // If the link failed, delete the program. 
     if (linkStatus[0] == 0) 
     {    
      GLES20.glDeleteProgram(programHandle); 
      programHandle = 0; 
     } 
    } 

    if (programHandle == 0) 
    { 
     throw new RuntimeException("Error creating program."); 
    } 

    // Set program handles. These will later be used to pass in values to the program. 
    mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");   
    mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position"); 
    mColorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");   

    // Tell OpenGL to use this program when rendering. 
    GLES20.glUseProgram(programHandle);   
} 

@Override 
public void onSurfaceChanged(GL10 glUnused, int width, int height) 
{ 
    // 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); 
} 

@Override 
public void onDrawFrame(GL10 glUnused) 
{ 
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);      

    // Do a complete rotation every 10 seconds. 
    long time = SystemClock.uptimeMillis() % 10000L; 
    float angleInDegrees = (360.0f/10000.0f) * ((int) time); 

    // Draw the triangle facing straight on. 
    Matrix.setIdentityM(mModelMatrix, 0); 
    Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);   
    drawTriangle(mTriangle1Vertices); 

    // Draw one translated a bit down and rotated to be flat on the ground. 
    Matrix.setIdentityM(mModelMatrix, 0); 
    Matrix.translateM(mModelMatrix, 0, 0.0f, -1.0f, 0.0f); 
    Matrix.rotateM(mModelMatrix, 0, 90.0f, 1.0f, 0.0f, 0.0f); 
    Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);   
    drawTriangle(mTriangle2Vertices); 

    // Draw one translated a bit to the right and rotated to be facing to the left. 
    Matrix.setIdentityM(mModelMatrix, 0); 
    Matrix.translateM(mModelMatrix, 0, 1.0f, 0.0f, 0.0f); 
    Matrix.rotateM(mModelMatrix, 0, 90.0f, 0.0f, 1.0f, 0.0f); 
    Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f); 
    drawTriangle(mTriangle3Vertices); 

    // Draw square facing strait on 
    float smallerAngle = -angleInDegrees; 
    Matrix.setIdentityM(mModelMatrix, 0); 
    Matrix.translateM(mModelMatrix, 0, 0, 0, 0.0f); 
    Matrix.rotateM(mModelMatrix, 0, smallerAngle, 0.0f, 0.0f, 1.0f);   
    drawSquare(mSquare1Vertices); 
} 

/** 
* Draws a triangle from the given vertex data. 
* 
* @param aTriangleBuffer The buffer containing the vertex data. 
*/ 
private void drawTriangle(final FloatBuffer aTriangleBuffer) 
{  
    // Pass in the position information 
    aTriangleBuffer.position(mPositionOffset); 
    GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 
      mStrideBytes, aTriangleBuffer);   

    GLES20.glEnableVertexAttribArray(mPositionHandle);   

    // Pass in the color information 
    aTriangleBuffer.position(mColorOffset); 
    GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, 
      mStrideBytes, aTriangleBuffer);   

    GLES20.glEnableVertexAttribArray(mColorHandle); 

    // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix 
    // (which currently contains model * view). 
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 

    // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix 
    // (which now contains model * view * projection). 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 

    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);        
} 

private void drawSquare(final FloatBuffer aSquareBuffer) { 
    // Pass in the position information 
    aSquareBuffer.position(mPositionOffset); 
    GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 
      mStrideBytes, aSquareBuffer);   

    GLES20.glEnableVertexAttribArray(mPositionHandle);   

    // Pass in the color information 
    aSquareBuffer.position(mColorOffset); 
    GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, 
      mStrideBytes, aSquareBuffer);   

    GLES20.glEnableVertexAttribArray(mColorHandle); 

    // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix 
    // (which currently contains model * view). 
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 

    // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix 
    // (which now contains model * view * projection). 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 

    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 4);        
} 
} 

回答

2

我假設您對OpenGL ES 2.0編程非常新穎。所以,你開始3.D-變換矩陣玩耍(如,建模,可視,或投影)之前,請先嚐試這個簡單的例子(呈現矩形) -

public class GLES20Renderer implements Renderer { 
    private int _rectangleProgram; 
    private int _rectangleAPositionLocation; 
    private FloatBuffer _rectangleVFB; 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
     gl.glClearColor(0.0f, 0.0f, 0.0f, 1); 
     initShapes(); 
     int _rectangleVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, _rectangleVertexShaderCode); 
     int _rectangleFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, _rectangleFragmentShaderCode); 
     _rectangleProgram = GLES20.glCreateProgram(); 
     GLES20.glAttachShader(_rectangleProgram, _rectangleVertexShader); 
     GLES20.glAttachShader(_rectangleProgram, _rectangleFragmentShader); 
     GLES20.glLinkProgram(_rectangleProgram); 
     _rectangleAPositionLocation = GLES20.glGetAttribLocation(_rectangleProgram, "aPosition"); 
    } 

    public void onSurfaceChanged(GL10 gl, int width, int height) { 
     gl.glViewport(0, 0, width, height); 
    } 

    public void onDrawFrame(GL10 gl) { 
     gl.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 

     GLES20.glUseProgram(_rectangleProgram); 
     GLES20.glVertexAttribPointer(_rectangleAPositionLocation, 3, GLES20.GL_FLOAT, false, 12, _rectangleVFB); 
     GLES20.glEnableVertexAttribArray(_rectangleAPositionLocation); 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); 
    } 

    private void initShapes() { 
     float rectangleVFA[] = { 
        0,  0,  0, 
        0,  0.5f, 0, 
        0.75f, 0.5f, 0, 
        0.75f, 0.5f, 0, 
        0.75f, 0,  0, 
        0,  0,  0, 
       }; 
     ByteBuffer rectangleVBB = ByteBuffer.allocateDirect(rectangleVFA.length * 4); 
     rectangleVBB.order(ByteOrder.nativeOrder()); 
     _rectangleVFB = rectangleVBB.asFloatBuffer(); 
     _rectangleVFB.put(rectangleVFA); 
     _rectangleVFB.position(0); 
    } 

    private final String _rectangleVertexShaderCode = 
      "attribute vec4 aPosition;    \n" 
     + "void main() {       \n" 
     + " gl_Position = aPosition;    \n" 
     + "}          \n"; 

    private final String _rectangleFragmentShaderCode = 
      "void main() {       \n" 
     + " gl_FragColor = vec4(1,1,1,1);   \n" 
     + "}          \n"; 

    private int loadShader(int type, String source) { 
     int shader = GLES20.glCreateShader(type); 
     GLES20.glShaderSource(shader, source); 
     GLES20.glCompileShader(shader); 
     return shader; 
    } 

} 

更多的在這些 - http://www.apress.com/9781430250531

0

將您的方塊定義爲兩個三角形。我做這樣(我給你舉個例子沒有顏色的數據,只有頂點):

final float[] squareCoords = { 
      //first triangle 
      -1.0f, 1.0f, 0.0f, 
      -1.0f, -1.0f, 0.0f, 
      1.0f, 1.0f, 0.0f, 
      //second triangle 
      -1.0f, -1.0f, 0.0f, 
      1.0f, -1.0f, 0.0f, 
      1.0f, 1.0f, 0.0f 
    }; 

,然後在drawSquare()使用

 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); 

它將汲取兩個三角形與你方COORDS 。

相關問題