2013-07-15 5 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

. По крайней мере, не учитывайте импорт, атрибуты и значительную часть комментариев, которые могут быть дефинитивно не релевантными. Это примерно от трети до половины того, что вы разместили. –

ответ

0

походку расстояние между атрибутами в байтах, и используется, если вы упаковки более одного атрибута в одном массиве. Кажется, что вы используете один массив для каждого атрибута, поэтому вы можете перейти в 0 как шаг, чтобы сказать OpenGL, что атрибуты плотно упакованы.

Ваши позиции и цветные массивы должны быть одинаковой длины с точки зрения компонентов. то есть одной позиции для одного цвета. Вероятно, поэтому цвета не выходят, как вы ожидаете.

Если вы хотите, чтобы каждая грань была другой, твердой, цветной, настройте вершины так, чтобы каждый треугольник был разным и рисовал с помощью 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

Я пробовал это, и он создает 2D-треугольник 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 цветов. Вы указываете 1 цвет vec4 для verts 0-11 и рисуете треугольники между индексами 0-3, поэтому используются только первые 4 ваших цвета.

+0

Это имеет смысл, так что есть способ, которым я могу прикрепить разные цвета к каждой грани вершины, а не только к одному цвету для каждой вершины, поэтому я могу получить лица, которые являются одним цветом, а не многоцветными, как это: http: // oi42.tinypic.com/15e8y6t.jpg при использовании TRIANGLE_STRIP – Ion

+0

Поскольку цвет, используемый в шейдере фрагмента, является «переменным», то есть он является результатом интерполяции значений из трех вершин, составляющих лицо, единственный способ вы можете иметь лица с их собственными цветами блоков, чтобы дублировать вершины, которые его составляют, чтобы они вносили разные цвета на каждое лицо, к которому они принадлежат. Таким образом, угол куба может составлять всего 6 треугольников, поэтому его нужно будет дублировать 6 раз, причем каждый из них имеет свой собственный цвет.В принципе, я не думаю, что с GL_TRIANGLE_STRIP можно делать то, что вы хотите, но другие ответы здесь работают. – chrisvarnz

Смежные вопросы