2013-07-15 2 views
0

나는 감독 연구를 위해 OpenGL ES 2를 배우고 있으며, 내가 이해하지 못하는 몇 가지 사항이 있습니다. 나는 glVertexAttribPointer에 전달되는 스트라이드가 무엇인지 이해하지 못합니다. 또한 솔리드 컬러 사면체를 그릴 수 있었지만 지금은 모든면을 다른 색으로 만들기 위해 확장하려고합니다. 잘 진행되지 않습니다. 누군가가 내가 쉐이더 측면에서 잘못하고있는 것과 왜 펑키 한 색상을 그리는가/올바르게 회전하지 않는 것을 도울 수 있습니까? 나는 드로어의 작동 원리를 이해하기 위해 http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/을 기본으로 사용하고있었습니다. 셰이더가 작동하는 방식과 걸음 걸이 등을 이해하는 데 도움이되고 내가 잘못하고있는 것을 크게 이해하게 될 것입니다.색이있는면이있는 OpenGL ES 2 면체

package com.example.lab5task1; 

//middle of screen is 0,0. To left/right is -/+ x, up/down is +/- y 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 
import java.util.Random; 

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

import android.annotation.SuppressLint; 
import android.content.Context; 
import android.graphics.Point; 
import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.Matrix; 
import android.os.SystemClock; 
import android.util.Log; 
import android.view.Display; 
import android.view.WindowManager; 

public class MyGLRenderer implements GLSurfaceView.Renderer 
{ 

private static final String TAG = "MyGLRenderer"; 
private Tetrahedron mTet; 
private float height, width; 
public float xTouch, yTouch; 
Random rand = new Random(); 

private final float[] mMVPMatrix = new float[16]; //model view and projection matrix 
private final float[] mProjMatrix = new float[16]; //projection matrix 
private final float[] mVMatrix = new float[16]; //view matrix 
private final float[] mRotationMatrix = new float[16]; //rotation matrix 
private float[] drawColor = { rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), 1f }; 
private float[] mModelMatrix = new float[16]; 

@SuppressLint("NewApi") 
MyGLRenderer(Context context) 
{ 
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
    Display display = wm.getDefaultDisplay(); 
    Point size = new Point(); 
    display.getSize(size); 

    //used for correct drawing and touch 
    this.height = size.y; 
    this.width = size.x; 
    this.xTouch = this.yTouch = 0; 
} 

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

    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 

    // Use culling to remove back faces. 
    GLES20.glEnable(GLES20.GL_CULL_FACE); 

    // Enable depth testing 
    GLES20.glEnable(GLES20.GL_DEPTH_TEST); 

    //eye positions 
    final float eyeX = 0.0f; 
    final float eyeY = 0.0f; 
    final float eyeZ = -3f; 

    // We are looking toward the distance 
    final float lookX = 0.0f; 
    final float lookY = 0.0f; 
    final float lookZ = -1.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. 
    Matrix.setLookAtM(mVMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); 

} 

@Override 
public void onDrawFrame(GL10 unused) 
{ 

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

    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 

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

    long time = SystemClock.uptimeMillis() % 10000L; 
    float angleInDegrees = (360.0f/10000.0f) * ((int) time); 

    mTet = new Tetrahedron(); 

    // Draw the triangle facing straight on. 
    Matrix.setIdentityM(mRotationMatrix, 0); 
    Matrix.rotateM(mRotationMatrix, 0, angleInDegrees, .5f, .5f, 0.0f); 
    Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0); 

    mTet.draw(mMVPMatrix); 
} 

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

    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(mProjMatrix, 0, left, right, bottom, top, near, far); 

} 

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

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

class Tetrahedron 
{ 

enum STYLE 
{ 
    OLD, NEW 
}; 

private STYLE codeType = STYLE.NEW; 

private final FloatBuffer vertexBuffer; 
private final FloatBuffer mColors; 
private final ShortBuffer drawListBuffer; 
private final int mProgram; 
private int mPositionHandle; 
private int mColorHandle; 
private int mMVPMatrixHandle; 
private int mMVMatrixHandle; 

private final String vertexShaderCode = "uniform mat4 uMVPMatrix;" + " attribute vec4 vPosition;" + "void main() {" + " gl_Position = vPosition * uMVPMatrix;" + "}"; 

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

// number of coordinates per vertex in this array 
// 72d angles at center, 108 angle at vertex 
static final int COORDS_PER_VERTEX = 3; 
static final int COLOR_DATA_SIZE = 4; 

static float tetCoords[] = { 0.0f, 0.622008459f, 0.0f,// 
     -0.5f, -0.311004243f, 0.0f,// 
     0.5f, -0.311004243f, 0.0f,// 
     0.0f, 0.0f, .622008459f }; 

static float colors[] = { 
     //face one 
     1.0f, 0.0f, 0.0f, 1.0f,//    
     1.0f, 0.0f, 0.0f, 1.0f,// 
     1.0f, 0.0f, 0.0f, 1.0f,// 
     //face two 
     0.0f, 1.0f, 0.0f, 1.0f,//    
     0.0f, 1.0f, 0.0f, 1.0f,// 
     0.0f, 1.0f, 0.0f, 1.0f,// 
     //face three 
     0.0f, 0.0f, 1.0f, 1.0f,//    
     0.0f, 0.0f, 1.0f, 1.0f,// 
     0.0f, 0.0f, 1.0f, 1.0f,// 
     //face four 
     1.0f, 1.0f, 0.0f, 1.0f,//    
     1.0f, 1.0f, 0.0f, 1.0f,// 
     1.0f, 1.0f, 0.0f, 1.0f,// 
}; 

String[] attributes = { "a_Position", "a_Color" }; 

private short drawOrder[] = { 0, 1, 2, 3, 0, 1 }; 
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex 
private final int colorStride = COLOR_DATA_SIZE * 4; 

float color[] = { .5f, .5f, .5f, 1f }; 

public Tetrahedron() 
{ 
    // initialize vertex byte buffer for shape coordinates 

    //this.color = color; 
    ByteBuffer bb = ByteBuffer.allocateDirect(
    // (# of coordinate values * 4 bytes per float) 
      tetCoords.length * 4); 
    bb.order(ByteOrder.nativeOrder()); 
    vertexBuffer = bb.asFloatBuffer(); 
    vertexBuffer.put(tetCoords); 
    vertexBuffer.position(0); 

    // initialize byte buffer for the draw list 
    // (# of coordinate 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); 

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

    if (codeType == STYLE.NEW) 
    { 

     final String vertexShader = getVertexShader(); 
     final String fragmentShader = getFragmentShader(); 

     int vertexShaderHandle = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShader); 
     int fragmentShaderHandle = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, 
       fragmentShader); 
     mProgram = GLES20.glCreateProgram(); 
     GLES20.glAttachShader(mProgram, vertexShaderHandle); 
     GLES20.glAttachShader(mProgram, fragmentShaderHandle); 
     for (int i = 0; i < attributes.length; i++) 
     { 
      GLES20.glBindAttribLocation(mProgram, i, attributes[i]); 
     } 

     GLES20.glLinkProgram(mProgram); 

    } 
    else 
    { 
     int vertexShaderHandle = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, 
       vertexShaderCode); 
     int fragmentShaderHandle = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, 
       fragmentShaderCode); 
     mProgram = GLES20.glCreateProgram(); 
     GLES20.glAttachShader(mProgram, vertexShaderHandle); 
     GLES20.glAttachShader(mProgram, fragmentShaderHandle); 
     for (int i = 0; i < attributes.length; i++) 
     { 
      GLES20.glBindAttribLocation(mProgram, i, attributes[i]); 
     } 

     GLES20.glLinkProgram(mProgram); 

    } 
} 

protected String getVertexShader() 
{ 

    // TODO: Explain why we normalize the vectors, explain some of the vector math behind it all. Explain what is eye space. 
    final String vertexShader = "uniform mat4 u_MVPMatrix;  \n" // A constant representing the combined model/view/projection matrix. 
      + "uniform mat4 u_MVMatrix;  \n" // A constant representing the combined model/view 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" 
      // Transform the vertex into eye space. 
      + " vec3 modelViewVertex = vec3(u_MVMatrix * a_Position);    \n" 
      // Multiply the color by the illumination level. It will be interpolated across the triangle. 
      + " v_Color = a_Color;          \n" 
      // gl_Position is a special variable used to store the final position. 
      // Multiply the vertex by the matrix to get the final point in normalized screen coordinates.  
      + " gl_Position = u_MVPMatrix * a_Position;       \n" + "}                  \n"; 

    return vertexShader; 
} 

protected String getFragmentShader() 
{ 
    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"; 

    return fragmentShader; 
} 

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

    if (codeType == STYLE.NEW) 
    { 
     mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix"); 
     mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVMatrix"); 
     mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position"); 
     mColorHandle = GLES20.glGetAttribLocation(mProgram, "a_Color"); 
     // Prepare the triangle coordinate data 
     GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, 
       false, vertexStride, vertexBuffer); 

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

     // Pass in the color information 
     GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, 
       colorStride, mColors); 
     GLES20.glEnableVertexAttribArray(mColorHandle); 

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

    } 
    else 
    { 

     // 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 triangle 
     GLES20.glUniform4fv(mColorHandle, 1, color, 0); 

     // get handle to shape's transformation matrix 
     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 square 
    GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, 
      drawListBuffer); 

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

오 세상에, 코드를 적게 게시해야합니다. 자신의 문제를 직접적으로 드러내는 코드의 직접 관련 스 니펫으로 자신을 제한하십시오. 아무도 오류를 찾기 위해 수백 줄을 읽으 려하지 않을 것입니다. –

+0

코드의 대부분은이 점을 이해하는 데 관련이 있습니다. setLookAt를 변경해야하는지, 클래스의 쉐이더 또는 다른 것인지 알 수 없었습니다. – Ion

+0

최소한 수입, 속성 및 커다란 주석은 정의 적으로 관련성이없는 코드 부분을 주석 처리했습니다. 그것은 당신이 게시 한 것의 약 3 분의 1에 해당합니다. –

답변

0

스트라이드는 속성 간의 거리이며, 동일한 배열에 둘 이상의 속성을 채우는 경우에 사용됩니다. 여기에 속성 하나당 하나의 배열을 사용하고있는 것으로 보입니다. 따라서 OpenGL에게 속성이 단단히 묶여 있음을 알리기 위해 보폭으로 0을 전달할 수 있습니다.

위치와 색상 배열은 구성 요소의 길이가 같아야합니다. 즉 하나의 색에 대해 하나의 위치에 배치된다. 이것은 아마도 색상이 예상대로 나오지 않는 이유 일 것입니다.

각면을 다른 색, 단색, 색으로 설정하려면 각 삼각형이 구별되도록 꼭지점을 설정하고 GL_TRIANGLES를 사용하여 그립니다. 예 :

{ 0f, 1f, 0f, // Left 
    -1, 0f, 1f, 
    -1, 0f, -1f, 

    0f, 1f, 0f, // Right 
    1f, 0f, 1f, 
    1f, 0f, 1f, 

    0f, 1f, 0f, // Near 
-1f, 0f, 1f, 
    1f, 0f, 1f, 

    0f, 1f, 0f, // Far 
-1f, 0f, -1f, 
    1f, 0f, -1f } 

및 그리기 GL_TRIANGLES. 이것이 개선 될 경우 알려주십시오!

+0

나는 그것을 시도했고, 2 개의 삼각형을 생성했다. http://oi39.tinypic.com/2d94iub.jpg 1 개의 얼굴은 2 개의 읽기와 1 개의 녹색 꼭지점을 갖고, 다른 하나의 얼굴은 모두 빨간색이다. – Ion

+0

위의 스크래치는 내가 제대로하지 못했습니다. 그것은 거의 작동, 나는 넣어 GLES20.glDrawArrays (GLES20.GL_TRIANGLES, 0, 12); 하지만 얼굴 중 일부는 연결되지 않았거나 여전히 나타나지 않습니다. – Ion

+0

좌표가 될 수 있습니다. 1 삼각형 (GL_TRIANGLES, 0, 3)으로 내려가보십시오. 그런 다음 각 삼각형의 데이터가 정상인지 확인하면서 12로 증가시킵니다. 종이에 그려내는 것이 도움이 될 수 있습니다 (심각하게! 그 방법은 저에게 효과적이었습니다). –

1

4 개의 꼭지점과 12 개의 색상을 전달하고 있습니다. verts 0-11에 vec4 색상을 1 개 지정하고 인덱스 0-3 사이에만 삼각형을 그리기 때문에 색상의 처음 4 개만 사용됩니다.

+0

그게 의미가 있습니다, 그래서 거기에 각 꼭지점에 단 하나의 색상 대신 정점의 각 얼굴에 다른 색상을 첨부 할 수있는 방법입니다 그래서 나는이 같은 멀티 컬러 대신 단 하나의 색상 얼굴을 얻을 수 있습니다 : http : // oi42.tinypic.com/15e8y6t.jpg TRIANGLE_STRIP을 사용하는 동안 – Ion

+0

프래그먼트 셰이더에서 사용되는 색상이 "변화"이기 때문에 즉, 얼굴을 구성하는 3 개의 꼭지점의 값을 보간 한 결과입니다. 당신은 자신의 블록 색상으로 얼굴을 가질 수 있습니다, 그들이 속한 각 얼굴에 다른 색상을 공헌하도록 그것을 구성하는 정점을 복제하는 것입니다. 따라서 큐브의 모서리는 총 6 개의 삼각형에 속할 수 있습니다. 따라서 6 번씩 복제해야합니다. 각각의 색마다 고유 한 색이 있습니다.기본적으로 GL_TRIANGLE_STRIP을 사용하여 원하는 것을 수행 할 수 있다고 생각하지 않지만 다른 답변은 여기에서 작동합니다. – chrisvarnz