2017-03-11 155 views
-1

我正在尝试为Android实现3D应用,并且在绘制像锥体这样的3D对象时遇到了麻烦。 问题是,我不能注意到不同面孔之间的过渡,所有这些都是用相同的颜色绘制的。 我想我需要给多边形添加阴影,但我无法找到任何教程向我展示如何做到这一点。 这是我用来绘制一个圆锥体的代码。Open GL ES 2.0 Android底纹

public class Cone{ 
float baseSize = 0f; 
float height = 0f; 
protected final float[] mTransformMatrix = new float[16]; 
private FloatBuffer vertexBuffer; 
private final int mProgram; 
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;" + 
       "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;" + 
       "}"; 

// Use to access and set the view transformation 
private int mMVPMatrixHandle; 
private final String fragmentShaderCode = 
     "precision mediump float;" + 
       "uniform vec4 vColor;" + 
       "void main() {" + 
       " gl_FragColor = vColor;" + 
       "}"; 

// number of coordinates per vertex in this array 
static final int COORDS_PER_VERTEX = 3; 
static float topCoords[] = new float[30]; 
static float baseCoords[] = new float[30]; 
static float lineCoords[] = new float[96]; 
// Set color with red, green, blue and alpha (opacity) values 
float color[] = { 1f, 0f, 0f, 1.0f }; 
float linecolor[] = { 1f, 1f, 1f, 1.0f }; 

public Cone(float baseSize , float height) { 
    this.baseSize = baseSize; 
    this.height = height; 
    float ang = (float) ((2*Math.PI)/8); 
    Matrix.setIdentityM(mTransformMatrix, 0); 
    // initialize vertex byte buffer for shape coordinates 
    ByteBuffer bb = ByteBuffer.allocateDirect(
      // (number of coordinate values * 4 bytes per float) 
      (topCoords.length * 2 + lineCoords.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 
    topCoords[0] = 0; 
    topCoords[1] = height; 
    topCoords[2] = 0; 
    baseCoords[0]= 0; 
    baseCoords[1]= 0; 
    baseCoords[2]= 0; 
    for(int i=1; i < 10;i++) { 
     topCoords[i*3] = this.baseSize * (float) Math.cos(i*ang); 
     topCoords[i*3 + 1] = 0; 
     topCoords[i*3 + 2] = this.baseSize * (float) Math.sin(i*ang); 

     baseCoords[i*3] = this.baseSize * (float) Math.cos(i*ang); 
     baseCoords[i*3 + 1] = 0; 
     baseCoords[i*3 + 2] = this.baseSize * (float) Math.sin(i*ang); 

    } 
    for (int i = 0 ; i < 8 ; i ++) { 
     lineCoords[i*6] = 0; 
     lineCoords[i*6 + 1] = height; 
     lineCoords[i*6 + 2] = 0; 
     lineCoords[i*6 + 3] = this.baseSize *(float) Math.cos((i+1)*ang); 
     lineCoords[i*6 + 4] = 0; 
     lineCoords[i*6 + 5] = this.baseSize * (float) Math.sin((i+1)*ang); 

    } 
    int j = 0; 
    for (int i = 8 ; i < 16 ; i++){ 
     lineCoords[i*6] = this.baseSize *(float) Math.cos((j+1)*ang); 
     lineCoords[i*6 + 1] = 0; 
     lineCoords[i*6 + 2] = this.baseSize * (float) Math.sin((j+1)*ang); 

     lineCoords[i*6 + 3] = this.baseSize *(float) Math.cos((j+2)*ang); 
     lineCoords[i*6 + 4] = 0; 
     lineCoords[i*6 + 5] = this.baseSize * (float) Math.sin((j+2)*ang); 
     j++; 
    } 



    vertexBuffer.put(topCoords); 
    vertexBuffer.put(baseCoords); 
    vertexBuffer.put(lineCoords); 
    // set the buffer to read the first coordinate 
    vertexBuffer.position(0); 

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

    // create empty OpenGL ES Program 
    mProgram = GLES20.glCreateProgram(); 

    // add the vertex shader to program 
    GLES20.glAttachShader(mProgram, vertexShader); 

    // add the fragment shader to program 
    GLES20.glAttachShader(mProgram, fragmentShader); 

    // creates OpenGL ES program executables 
    GLES20.glLinkProgram(mProgram); 
} 
private int mPositionHandle; 
private int mColorHandle; 

private final int topVertexCount = topCoords.length/COORDS_PER_VERTEX; 
private final int lineVertexCount = lineCoords.length/COORDS_PER_VERTEX; 


private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex 

public void draw(float[] mvpMatrix) { 
    // Add program to OpenGL ES 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, 
      vertexStride, vertexBuffer); 
    // get handle to fragment shader's vColor member 
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 
    // Set color for drawing the cone 
    GLES20.glUniform4fv(mColorHandle, 1, color, 0); 

    // get handle to shape's transformation matrix 
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 

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

    // Draw the cone 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, topVertexCount); 
    //Draw base 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, topVertexCount, topVertexCount); 
    //Draw cone lines 

    GLES20.glUniform4fv(mColorHandle, 1, linecolor, 0); 
    GLES20.glDrawArrays(GLES20.GL_LINES, topVertexCount*2, lineVertexCount); 

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

} 

}

感谢您的帮助

回答

0

你的片段着色器的代码确实是分配相同的颜色到每一个片段的过程。有许多不同的方法可以将“照明”添加到场景中。 'Gouraud shading'是使用现代着色器最容易实现的之一。它在三角形的三角形的每个顶点插入法线,并根据光线方向计算光强度。在现代着色语言(包括OpenGL ES 2)中,这种插值是为您完成的。

还有many其他可能的照明模型,但是大多数(如果不是全部,包括Gouraud着色)将需要您生成顶点法线,这是您在锥形网格生成代码中没有执行的。