2016-09-21 1 views
0

ich es schaffen, die Pyramide mit der Standard-Kesselplatte opengl ES2 Codierung zu machen, aber die Pyramide schien während der Wiedergabe mit Rotation um die Y-Achse verzerrt zu sein.Pyramide verzerrt beim Rendern unter android OpenGL ES2

Ich glaube, das hat etwas mit der Matrix Projektionsmatrizen oder Kameraansicht zu tun, hoffentlich könnte jemand helfen, durch Aufzeigen des Fehlers zu lösen. Dank

Distorted Pyramid

class MyGLRenderer1 implements GLSurfaceView.Renderer { 
     Context context; // Application's context 
     private pyramid1 pyramid; // (NEW) 
     private Circle circle;   // (NEW) 

     private int anglePyramid = 0; // Rotational angle in degree for pyramid (NEW) 
     private float angleCube = 0; // Rotational angle in degree for cube (NEW) 
     private float speedPyramid = 1.5f; // Rotational speed for pyramid (NEW) 
     private float speedCube = -1.5f; // Rotational speed for cube (NEW) 
     private float[] mViewMatrix = new float[16]; 
     private float[] mProjectionMatrix = new float[16]; 
     private float[] mModelMatrix = new float[16]; 
     private final int mBytesPerFloat = 4; 
     // ** 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; 
     // Constructor with global application context 

     private float[] mMVPMatrix = new float[16]; 

     /** 
     * 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; 

     private FloatBuffer vertexBuffer; // Buffer for vertex-array 
     private FloatBuffer colorBuffer; // Buffer for color-array 
     private ByteBuffer indexBuffer; // Buffer for index-array 
     private FloatBuffer textureBuffer; 
     private float scale_x = 0.5f; 
     private float[] vertices = { // 5 vertices of the pyramid in (x,y,z) 
       -1.0f * scale_x, -1.0f * scale_x, -1.0f * scale_x, // 0. left-bottom-back 
       1.0f, 0.0f, 0.0f, 1.0f, // 4. red 

       1.0f * scale_x, -1.0f * scale_x, -1.0f * scale_x, // 1. right-bottom-back 
       0.0f, 1.0f, 0.0f, 1.0f, // 1. green 


       1.0f * scale_x, -1.0f * scale_x, 1.0f * scale_x, // 2. right-bottom-front 
       0.0f, 0.0f, 1.0f, 1.0f, // 2. blue 


       -1.0f * scale_x, -1.0f * scale_x, 1.0f * scale_x, // 3. left-bottom-front 
       0.0f, 1.0f, 0.0f, 1.0f, // 3. green 

       0.0f, 0.5f, 0.0f, // 4. top 

       0.0f, 0.0f, 1.0f, 1.0f, // 0. blue 
     }; 
     private byte[] indices = { // Vertex indices of the 4 Triangles 

       0, 3, 4, 
       0, 4, 1, 
       1, 4, 2, 
       2, 3, 4, 
       0, 1, 2, 
       0, 2, 3 


     }; 




     public MyGLRenderer1() { 
      // pyramid = new pyramid1(); 
      // circle = new Circle(); 
      this.context = context; 


     } 

     // Call back when the surface is first created or re-created 
     @Override 
     public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set color's clear-value to black 
      // 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 // 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 // precision in the fragment shader. 
          + "varying vec4 v_Color; \n" // This is the color from the vertex shader // 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 vertex 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 vertex 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."); 
      } 

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








     } 

     // Call back after onSurfaceCreated() or whenever the window's size changes 
     @Override 
     public void onSurfaceChanged(GL10 gl, int width, int height) { 
      if (height == 0) height = 1; // To prevent divide by zero 
      float aspect = (float) width/height; 

      // Set the viewport (display area) to cover the entire window 
      GLES20.glViewport(0, 0, width, 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 = 5.0f; 

      Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); 


     } 

     // Call back to draw the current frame. 
     @Override 
     public void onDrawFrame(GL10 gl) { 
      // Clear color and depth buffers using clear-value set earlier 
      GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 

      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); 
      Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -2f, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 
      // Draw the triangle facing straight on. 
      Matrix.setIdentityM(mModelMatrix, 0); 
      Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 1.0f, 0.0f); 
      drawTriangle(); 


      anglePyramid += speedPyramid; 


      // You OpenGL|ES rendering code here 
      // ...... 
     } 

     private void drawTriangle() { 
      FloatBuffer aTriangleBuffer; 
      vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4) 
        .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
      vertexBuffer.put(vertices);   // Copy data into buffer 
      vertexBuffer.position(0); 


      // Setup index-array buffer. Indices in byte. 
      indexBuffer = ByteBuffer.allocateDirect(indices.length); 
      indexBuffer.put(indices); 
      indexBuffer.position(0); 

      aTriangleBuffer = vertexBuffer; 
      // 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.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_BYTE, 
        indexBuffer); 
      // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); 
     } 


    } 

enter image description here

Überarbeitete Bild

+0

Hinzufügen in der Anweisung schien ein wenig zu verbessern, immer noch nicht mit dem Rendering-Effekt Matrix.setLookAtM (mViewMatrix, 0, 0, 0, -2f, 0f, 0f, 0f, 0f, 1.0f, 0.0f); – TSG

Antwort

0

Sie die vordere Ecke zu verlieren, weil sie die in der Nähe von Clip-Ebene schneidet, ist, die, warum es sieht aus wie Sie 6 Ecken haben (5 um die Kante, und eine in der Mitte der farbigen Region) anstelle der tatsächlichen 5.

Der Rest ist, weil Ihre Ausrichtung es entweder falsch oder nicht aktiviert prüft, so dass der Boden der Pyramide sichtbar ist, anstatt dass die Vorderseite sichtbar ist.

+0

danke, ich schaffe es, den clipping point zu lösen, indem ich den pyramidenobersten scheitelpunkt verkleinere, da der unterteil der pyramide eine quadratische basis ist, ist es sichtbar und in gewissem umfang würde die optische illusion mit bloßem auge wie eine rechtsdrehung erscheinen die standardmäßige Drehung gegen den Uhrzeigersinn wie codiert. – TSG

Verwandte Themen