Android Opengl:仅显示我的3D立方体的正面

时间:2013-02-08 13:15:20

标签: android opengl-es

我正在尝试使用OpenGL ES2绘制3D立方体,而我的代码只绘制了立方体的正面(正方形),如此image所示。我无法弄清楚什么是错的。我已经尝试过基于其他教程实现我的立方体,但没有运气。

我的代码有什么问题?我在某处错过了一些重要的代码吗?

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    // TODO Auto-generated method stub
    GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    GLES20.glDepthFunc(GLES20.GL_LEQUAL);


    GLES20.glFrontFace(GLES20.GL_CCW);
    GLES20.glCullFace(GLES20.GL_BACK);
    GLES20.glEnable(GLES20.GL_CULL_FACE);


    Matrix.setLookAtM(mVMatrix,0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
}

DrawFrame方法

@Override
public void onDrawFrame(GL10 gl) {
    // TODO Auto-generated method stub
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);

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

    //Calling draw method of shapes
    square.draw(mMVPMatrix);
}

多维数据集类

                                // x, y, z  
static float squareCoords[] = {-1f, -1f, 1f,//Bottom Left
                                1f, -1f, 1f, //Bottom Right
                                1f, 1f, 1f,  //Top Right
                               -1f, 1f, 1f, //Top left

                               -1f, -1f, -1f,//Bottom Left
                               1f, -1f, -1f, //Bottom Right
                               1f, 1f, -1f,  //Top Right
                               -1f, 1f, -1f //Top left
                                };



private short drawOrder[] = {0,1,2, 0,2,3,//front
                             0,3,7, 0,7,4,//Left    
                             0,1,5, 0,5,4,//Bottom

                             6,7,4, 6,4,5,//Back
                             6,7,3, 6,3,2,//top
                             6,2,1, 6,1,5//right
}; //Order to draw vertices



private int vertaxCount = 0; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z)
private int vertaxStride = 0; //4 are how many bytes in a float

private float [] color = new float[]{
    0.1f, 0.5f, 1.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f,
    0.0f, 10.0f, 0.0f, 1.0f,
    0.0f, 1.0f, 1.0f, 1.0f,
    1.0f, 0.0f, 0.0f, 1.0f,
    1.0f, 0.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 0.0f, 1.0f,
    1.0f, 1.0f, 1.0f, 1.0f
};

public Square()
{
    //initialising vertex byte buffer for shape coordinates
    // (number of coordinate values * 4 bytes per float)
    ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);

    bb.order(ByteOrder.nativeOrder());

    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(squareCoords);
    vertexBuffer.position(0);


    //Initialise byte buffer for the draw list
    //(number of draw values * 2 bytes per short )
    ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);

    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer = dlb.asShortBuffer();
    drawListBuffer.put(drawOrder);
    drawListBuffer.position(0);


    ByteBuffer colors = ByteBuffer.allocateDirect(color.length * 4);
    colors.order(ByteOrder.nativeOrder());
    bufferColor = colors.asFloatBuffer();
    bufferColor.put(color);
    bufferColor.position(0);



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

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

    vertaxCount = squareCoords.length / COORDS_PER_VERTEX; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z)
    vertaxStride = COORDS_PER_VERTEX * 4; //4 are how many bytes in a float


}

public void draw(float[] mMVPMatrix)
{
    //Add program to OpenGL environment
    GLES20.glUseProgram(mProg);

    //Get Handle to the vertices
    int mPositionHandle = GLES20.glGetAttribLocation(mProg, "vPosition");



    //Prepare the shape coordinate data
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, 
                                    GLES20.GL_FLOAT, false, 
                                    vertaxStride, vertexBuffer);

    //Enable a handle to the shape vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);


    int mColorHandle = GLES20.glGetUniformLocation(mProg, "v_color");

    GLES20.glVertexAttribPointer(mColorHandle, 3, GLES20.GL_FLOAT, false, 0, bufferColor);
    GLES20.glEnableVertexAttribArray(mColorHandle);


    float [] tm = new float[16];
    float [] rm = new float[16];

    Matrix.scaleM(mMVPMatrix, 0, 0.35f, 0.35f, 0);
    Matrix.translateM(tm, 0, mMVPMatrix, 0, 0f, 0f, 0);
    Matrix.rotateM(rm, 0, tm, 0, 45f, 0, 0, 1);

    // get handle to shape's transformation matrix
    int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProg, "u_MVPMatrix");

    // Apply the projection and view transformation
    //GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, rm, 0);


    //Draw the shape
    //GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertaxCount);
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

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

}

2 个答案:

答案 0 :(得分:0)

class Cube {

private FloatBuffer mVertexBuffer;
private FloatBuffer mColorBuffer;
private ShortBuffer  mIndexBuffer;
private  int mProgram, mPositionHandle, mColorHandle, mMVPMatrixHandle ; 

private final String vertexShaderCode =
        "uniform mat4 uMVPMatrix;" +
        "attribute vec4 vPosition;" +
        "attribute vec4 aColor;" +  
        "varying vec4 vColor;" +

        "void main() {" +
        "vColor = aColor;" +
        "gl_Position = vPosition * uMVPMatrix;" +
        "}";

    private final String fragmentShaderCode =
        "precision mediump float;" +
        "varying vec4 vColor;" +
        "void main() {" +
        "gl_FragColor = vColor;" +  //  vec4(0.0, 1.0, 0.0, 1.0);" +
        "}";

private float vertices[] = {
        -0.5f, -0.5f, 0.5f,//Bottom Left
         0.5f, -0.5f, 0.5f, //Bottom Right
         0.5f, 0.5f, 0.5f,  //Top Right
        -0.5f, 0.5f, 0.5f, //Top left

        -0.5f, -0.5f, -0.5f,//Bottom Left
         0.5f, -0.5f, -0.5f, //Bottom Right
         0.5f, 0.5f, -0.5f,  //Top Right
        -0.5f, 0.5f, -0.5f //Top left
                            };

private float colors[] = {
                           0.0f,  1.0f,  0.0f,  1.0f,
                           0.0f,  1.0f,  0.0f,  1.0f,
                           1.0f,  0.5f,  0.0f,  1.0f,
                           1.0f,  0.5f,  0.0f,  1.0f,
                           1.0f,  0.0f,  0.0f,  1.0f,
                           1.0f,  0.0f,  0.0f,  1.0f,
                           0.0f,  0.0f,  1.0f,  1.0f,
                           1.0f,  0.0f,  1.0f,  1.0f
                        };

private short indices[] = {
        0,1,2, 0,2,3,//front
        0,3,7, 0,7,4,//Left    
        0,1,5, 0,5,4,//Bottom

        6,7,4, 6,4,5,//Back
        6,7,3, 6,3,2,//top
        6,2,1, 6,1,5//right
                          };

public Cube() {

        ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mVertexBuffer = byteBuf.asFloatBuffer();
        mVertexBuffer.put(vertices);
        mVertexBuffer.position(0);

        byteBuf = ByteBuffer.allocateDirect(colors.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mColorBuffer = byteBuf.asFloatBuffer();
        mColorBuffer.put(colors);
        mColorBuffer.position(0);

        byteBuf = ByteBuffer.allocateDirect(indices.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mIndexBuffer = byteBuf.asShortBuffer();
        mIndexBuffer.put(indices);
        mIndexBuffer.position(0);

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

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

}


public static int loadShader(int type, String shaderCode){

    int shader = GLES20.glCreateShader(type);
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);
    return shader;
}

public void draw (float[] mvpMatrix){

    //GLES20.glFrontFace(GLES20.GL_CCW);



    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, 3,
                                 GLES20.GL_FLOAT, false,
                                 12, mVertexBuffer);

    // get handle to fragment shader's vColor member
    mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");

    GLES20.glEnableVertexAttribArray(mColorHandle);

    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(mColorHandle, 4,
                                 GLES20.GL_FLOAT, false,
                                 0, mColorBuffer);

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

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

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



    // Draw the triangle
     GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);

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

}

}

public abstract class GLRenderer implements GLSurfaceView.Renderer {

boolean mFirstDraw;
boolean mSurfaceCreated;
int mWidth;
int mHeight;
long mLastTime;
int mFPS;
float[] mProjMatrix = new float[16];
float[] mVMatrix = new float[16];
float[] mMVPMatrix = new float[16];
private float[] rotationMatrix = new float[16];
private float angle = 0f;

GLRenderer() {
    mFirstDraw = true;
    mSurfaceCreated = false;
    mWidth = -1;
    mHeight = -1;
    mLastTime = System.currentTimeMillis();
    mFPS = 0;
}

@Override
public void onDrawFrame(GL10 arg0) {
    // TODO Auto-generated method stub
    Cube mCube = new Cube();
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);

    if (mFirstDraw)
        mFirstDraw = false;

    angle += 0.7f;
    if (angle > 360f)
        angle = 0f;
    Matrix.setLookAtM(mVMatrix, 0, 0f, 0f, 4f, 0f, 0f, 0f, 0f, 1f, 0f);
    // projection x view = modelView
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
    // Creating rotation matrix
    Matrix.setRotateM(rotationMatrix, 0, angle, 0f, 0f, -1f);

    // rotation x camera = modelView
    float[] duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);

    Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);

    Matrix.setRotateM(rotationMatrix, 0, angle, 0f, -1f, 0f);
    duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
    Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);

    Matrix.setRotateM(rotationMatrix, 0, angle, -1f, 0f, 0f);
    duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
    Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);
    // rotation x camera = modelView
    mCube.draw(mMVPMatrix);




}

@Override
public void onSurfaceChanged(GL10 arg0, int arg1, int arg2) {
    // TODO Auto-generated method stub

    mWidth = arg1;
    mHeight = arg2;

    GLES20.glViewport(0, 0, mWidth, mHeight);

    float ratio = (float) mWidth / mHeight;

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(mProjMatrix, 0, -1, 1, -1, 1, 3, 7);

}



@Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
    // TODO Auto-generated method stub

    mSurfaceCreated = true;
    mWidth = -1;
    mHeight = -1;
    GLES20.glClearColor(0f, 0f, 0f, 0f);
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
}

}

public class MainActivity extends Activity {

GLSurfaceView glView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    if(hasGL20()){
        glView = new GLSurfaceView(getApplicationContext());
        glView.setEGLContextClientVersion(2);
        glView.setPreserveEGLContextOnPause(true);
        glView.setRenderer(new GL20Renderer());

    }else{
        Log.v ("No Req Version","");
    }

    setContentView(glView);
}

@Override
protected void onPause() {
    super.onPause();
    if(glView != null)
      glView.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    if(glView != null)
       glView.onResume();

}

private boolean hasGL20(){
    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    ConfigurationInfo info = am.getDeviceConfigurationInfo();
    return info.reqGlEsVersion >= 0x20000;
}


}

答案 1 :(得分:0)

可能是你的三角形并非全部以一致的方向缠绕。尝试禁用背面剔除:

GLES20.glDisable(GLES20.GL_CULL_FACE);

或者,将CullFace反转到前面:

GLES20.glCullFace(GLES20.GL_FRONT);

如果这会改变立方体的哪一面被渲染,那么你的三角形并非全部以一致的方向缠绕。