2016-03-06 75 views
0

我想在android上使用OpenGL 2.0繪製立方體。但是,這看起來不正確。這是結果在opengl es 2.0中着色的立方體

enter image description here

,這是我的代碼

Cube.java

package com.example.android.opengl; 

/** 
* Created by duykq57hotmail.com on 3/6/2016. 
*/ 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 

import android.opengl.GLES20; 

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

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;" + 
       //"attribute vec4 aColor;" + 
       //"uniform vec4 vColor;" + 
       "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;" + 
       //" vColor = aColor;" + 
       "}"; 

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

private final FloatBuffer vertexBuffer; 
private final FloatBuffer colorBuffer; 
private final int mProgram; 
private int mPositionHandle; 
private int mColorHandle; 
private int mMVPMatrixHandle; 

// number of coordinates per vertex in this array 
static final int COORDS_PER_VERTEX = 3; 
static final int COLORS_PER_VERTEX = 4; 
static float triangleCoords[] = { 
     // Front face 
     -1.0f, 1.0f, 1.0f, 
     -1.0f, -1.0f, 1.0f, 
     1.0f, 1.0f, 1.0f, 
     -1.0f, -1.0f, 1.0f, 
     1.0f, -1.0f, 1.0f, 
     1.0f, 1.0f, 1.0f, 

     // Right face 
     1.0f, 1.0f, 1.0f, 
     1.0f, -1.0f, 1.0f, 
     1.0f, 1.0f, -1.0f, 
     1.0f, -1.0f, 1.0f, 
     1.0f, -1.0f, -1.0f, 
     1.0f, 1.0f, -1.0f, 

     // Back face 
     1.0f, 1.0f, -1.0f, 
     1.0f, -1.0f, -1.0f, 
     -1.0f, 1.0f, -1.0f, 
     1.0f, -1.0f, -1.0f, 
     -1.0f, -1.0f, -1.0f, 
     -1.0f, 1.0f, -1.0f, 

     // Left face 
     -1.0f, 1.0f, -1.0f, 
     -1.0f, -1.0f, -1.0f, 
     -1.0f, 1.0f, 1.0f, 
     -1.0f, -1.0f, -1.0f, 
     -1.0f, -1.0f, 1.0f, 
     -1.0f, 1.0f, 1.0f, 

     // Top face 
     -1.0f, 1.0f, -1.0f, 
     -1.0f, 1.0f, 1.0f, 
     1.0f, 1.0f, -1.0f, 
     -1.0f, 1.0f, 1.0f, 
     1.0f, 1.0f, 1.0f, 
     1.0f, 1.0f, -1.0f, 

     // Bottom face 
     1.0f, -1.0f, -1.0f, 
     1.0f, -1.0f, 1.0f, 
     -1.0f, -1.0f, -1.0f, 
     1.0f, -1.0f, 1.0f, 
     -1.0f, -1.0f, 1.0f, 
     -1.0f, -1.0f, -1.0f, 
}; 
float color[] = { 0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 

     // right, blue 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 

     // back, also green 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 
     0f, 0.5273f, 0.2656f, 1.0f, 

     // left, also blue 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 
     0.0f, 0.3398f, 0.9023f, 1.0f, 

     // top, red 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 

     // bottom, also red 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, 
     0.8359375f, 0.17578125f, 0.125f, 1.0f, }; 
private final int vertexCount = triangleCoords.length/COORDS_PER_VERTEX; 
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex 
private final int colorStride = COLORS_PER_VERTEX*4; 


/** 
* Sets up the drawing object data for use in an OpenGL ES context. 
*/ 
public Cube() { 
    // initialize vertex byte buffer for shape coordinates 
    ByteBuffer bb = ByteBuffer.allocateDirect(
      // (number of coordinate values * 4 bytes per float) 
      triangleCoords.length * 4); 
    // use the device hardware'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(triangleCoords); 
    // set the buffer to read the first coordinate 
    vertexBuffer.position(0); 


    ByteBuffer bb2 = ByteBuffer.allocateDirect(
      // (number of coordinate values * 4 bytes per float) 
      color.length * 4); 
    // use the device hardware's native byte order 
    bb2.order(ByteOrder.nativeOrder()); 

    // create a floating point buffer from the ByteBuffer 
    colorBuffer = bb2.asFloatBuffer(); 
    // add the coordinates to the FloatBuffer 
    colorBuffer.put(color); 
    // set the buffer to read the first coordinate 
    colorBuffer.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 

} 

/** 
* 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, 
      0, vertexBuffer); 

    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 

    // Set color for drawing the triangle 
    GLES20.glUniform4fv(mColorHandle, 1, color, 0); 
//  mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor"); 
//  GLES20.glEnableVertexAttribArray(mColorHandle); 
//  GLES20.glVertexAttribPointer(
//    mColorHandle, COLORS_PER_VERTEX, 
//    GLES20.GL_FLOAT, false, 
//    0, colorBuffer); 

    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 triangle 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); 

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

} 

MyGLRenderer.java

/* 
* Copyright (C) 2011 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 
package com.example.android.opengl; 

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

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

/** 
* Provides drawing instructions for a GLSurfaceView object. This class 
* must override the OpenGL ES drawing lifecycle methods: 
* <ul> 
* <li>{@link android.opengl.GLSurfaceView.Renderer#onSurfaceCreated}</li> 
* <li>{@link android.opengl.GLSurfaceView.Renderer#onDrawFrame}</li> 
* <li>{@link android.opengl.GLSurfaceView.Renderer#onSurfaceChanged}</li> 
* </ul> 
*/ 
public class MyGLRenderer implements GLSurfaceView.Renderer { 

    private static final String TAG = "MyGLRenderer"; 
    private Triangle mTriangle; 
    private Square mSquare; 

    // 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]; 
    private final float[] mRotationMatrix = new float[16]; 

    private float mAngle; 
    private Cube mCube; 

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

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

     mTriangle = new Triangle(); 
     mSquare = new Square(); 
     mCube = new Cube(); 
    } 

    @Override 
    public void onDrawFrame(GL10 unused) { 
     float[] scratch = new float[16]; 

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

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

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

     // Draw square 
     //mSquare.draw(mMVPMatrix); 
     mCube.draw(mMVPMatrix); 
     // 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); 

     Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f); 

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

     // Draw triangle 
     //mTriangle.draw(scratch); 
    } 

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

    } 

    /** 
    * Utility method for compiling a OpenGL shader. 
    * 
    * <p><strong>Note:</strong> When developing shaders, use the checkGlError() 
    * method to debug shader coding errors.</p> 
    * 
    * @param type - Vertex or fragment shader type. 
    * @param shaderCode - String containing the shader code. 
    * @return - Returns an id for the shader. 
    */ 
    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: 
    * 
    * <pre> 
    * mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 
    * MyGLRenderer.checkGlError("glGetUniformLocation");</pre> 
    * 
    * 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); 
     } 
    } 

    /** 
    * Returns the rotation angle of the triangle shape (mTriangle). 
    * 
    * @return - A float representing the rotation angle. 
    */ 
    public float getAngle() { 
     return mAngle; 
    } 

    /** 
    * Sets the rotation angle of the triangle shape (mTriangle). 
    */ 
    public void setAngle(float angle) { 
     mAngle = angle; 
    } 

} 

你能幫我解決這個問題?非常感謝你

+0

你希望哪個輸出?你正在從(1,1,-6)看到orgin,並看到你的立方體的「後面」。對我而言,這看起來像它看起來應該如何。 – derhass

+0

感謝您的幫助。但我的魔方只是綠色的。立方體的其他面是相同的。你可以幫我嗎。對不起,因爲我的英語不好 –

+0

你永遠不會看到你的多維數據集的任何其他面對你的當前代碼,所以你怎麼知道這一點? – derhass

回答

0

我認爲你希望立方體的每個面都是不同的顏色。

在你的代碼中,vColor是統一的。這意味着您的多維數據集中的每個點都將具有相同的顏色值。

您需要將vColor作爲屬性傳遞給您的頂點着色器,然後將其作爲變化傳遞給您的片段着色器。

你的着色器的代碼應該是這樣的

頂點着色器

attribute vec4 vColor; 
varying vec4 vColorVarying; 

void main() { 
// other shader code ... 

    vColorVarying = vColor; 
} 

片段着色器

varying vec4 vColorVarying; 

void main() { 
    gl_FragColor = vColorVarying; 
} 
+0

謝謝。它爲我工作^^ –