2012-10-09 19 views
20

を使用して、2D画像を描画し、私は、AndroidのためのOpenGL ES 2.0を使用してJPG/PNGファイルから2D画像を描画するために苦労してきました。 どこでも私はチュートリアルが3D画像をテクスチャ化するために見えるので、通常の2Dスプライトの描画方法を大まかに把握しています。描画と回転の四角形が得られましたが、一旦テクスチャリングが行われると、DrawElementsがどのデータにもバインドされていないとエラーが発生し続けるため、どこかでうんざりしているはずです。のOpenGL ES 2.0

ご協力いただければ幸いです。ここで

は私のSpriteクラスとレンダラクラスのための私のコードです:

public class Sprite 
{ 
//Reference to Activity Context 
private final Context mActivityContext; 

//Added for Textures 
private final FloatBuffer mCubeTextureCoordinates; 
private int mTextureUniformHandle; 
private int mTextureCoordinateHandle; 
private final int mTextureCoordinateDataSize = 2; 
private int mTextureDataHandle; 

private final String vertexShaderCode = 
//Test 
"attribute vec2 a_TexCoordinate;" + 
"varying vec2 v_TexCoordinate;" + 
//End Test 
"uniform mat4 uMVPMatrix;" + 
"attribute vec4 vPosition;" + 
"void main() {" + 
" gl_Position = vPosition * uMVPMatrix;" + 
    //Test 
    "v_TexCoordinate = a_TexCoordinate" + 
    //End Test 
"}"; 

private final String fragmentShaderCode = 
"precision mediump float;" + 
"uniform vec4 vColor;" + 
//Test 
"uniform sampler2D u_Texture;" + 
"varying vec2 v_TexCoordinate;" + 
//End Test 
"void main() {" + 
//"gl_FragColor = vColor;" + 
"gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate));" + 
"}"; 

private final int shaderProgram;  
private final FloatBuffer vertexBuffer; 
private final ShortBuffer drawListBuffer; 
private int mPositionHandle; 
private int mColorHandle; 
private int mMVPMatrixHandle; 

// number of coordinates per vertex in this array 
static final int COORDS_PER_VERTEX = 2; 
static float spriteCoords[] = { -0.5f, 0.5f, // top left 
           -0.5f, -0.5f, // bottom left 
           0.5f, -0.5f, // bottom right 
           0.5f, 0.5f }; //top right 

private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; //Order to draw vertices 
private final int vertexStride = COORDS_PER_VERTEX * 4; //Bytes per vertex 

// Set color with red, green, blue and alpha (opacity) values 
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; 

public Sprite(final Context activityContext) 
{ 
    mActivityContext = activityContext; 

    //Initialize Vertex Byte Buffer for Shape Coordinates/# of coordinate values * 4 bytes per float 
    ByteBuffer bb = ByteBuffer.allocateDirect(spriteCoords.length * 4); 
    //Use the Device'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(spriteCoords); 
    //Set the Buffer to Read the first coordinate 
    vertexBuffer.position(0); 

    // S, T (or X, Y) 
    // Texture coordinate data. 
    // Because images have a Y axis pointing downward (values increase as you move down the image) while 
    // OpenGL has a Y axis pointing upward, we adjust for that here by flipping the Y axis. 
    // What's more is that the texture coordinates are the same for every face. 
    final float[] cubeTextureCoordinateData = 
    {            
      //Front face 
      /*0.0f, 0.0f,    
      0.0f, 1.0f, 
      1.0f, 0.0f, 
      0.0f, 1.0f, 
      1.0f, 1.0f, 
      1.0f, 0.0f*/ 

      -0.5f, 0.5f, 
      -0.5f, -0.5f, 
      0.5f, -0.5f, 
      0.5f, 0.5f 
    }; 

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

    //Initialize byte buffer for the draw list 
    ByteBuffer dlb = ByteBuffer.allocateDirect(spriteCoords.length * 2); 
    dlb.order(ByteOrder.nativeOrder()); 
    drawListBuffer = dlb.asShortBuffer(); 
    drawListBuffer.put(drawOrder); 
    drawListBuffer.position(0); 

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

    shaderProgram = GLES20.glCreateProgram(); 
    GLES20.glAttachShader(shaderProgram, vertexShader); 
    GLES20.glAttachShader(shaderProgram, fragmentShader); 

    //Texture Code 
    GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate"); 

    GLES20.glLinkProgram(shaderProgram); 

    //Load the texture 
    mTextureDataHandle = loadTexture(mActivityContext, R.drawable.brick); 
} 

public void Draw(float[] mvpMatrix) 
{ 
    //Add program to OpenGL ES Environment 
    GLES20.glUseProgram(shaderProgram); 

    //Get handle to vertex shader's vPosition member 
    mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "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(shaderProgram, "vColor"); 

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

    //Set Texture Handles and bind Texture 
    mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture"); 
    mTextureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "a_TexCoordinate"); 

    //Set the active texture unit to texture unit 0. 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 

    //Bind the texture to this unit. 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle); 

    //Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0. 
    GLES20.glUniform1i(mTextureUniformHandle, 0); 

    //Pass in the texture coordinate information 
    mCubeTextureCoordinates.position(0); 
    GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates); 
    GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 

    //Get Handle to Shape's Transformation Matrix 
    mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix"); 

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

    //Draw the triangle 
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer); 

    //Disable Vertex Array 
    GLES20.glDisableVertexAttribArray(mPositionHandle); 
} 

public static int loadTexture(final Context context, final int resourceId) 
{ 
    final int[] textureHandle = new int[1]; 

    GLES20.glGenTextures(1, textureHandle, 0); 

    if (textureHandle[0] != 0) 
    { 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inScaled = false; // No pre-scaling 

     // Read in the resource 
     final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options); 

     // Bind to the texture in OpenGL 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]); 

     // Set filtering 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 

     // Load the bitmap into the bound texture. 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

     // Recycle the bitmap, since its data has been loaded into OpenGL. 
     bitmap.recycle(); 
    } 

    if (textureHandle[0] == 0) 
    { 
     throw new RuntimeException("Error loading texture."); 
    } 

    return textureHandle[0]; 
} 
} 

私のレンダラクラス:

public class MyGL20Renderer implements GLSurfaceView.Renderer 
{ 
private final Context mActivityContext; 

//Matrix Initializations 
private final float[] mMVPMatrix = new float[16]; 
private final float[] mProjMatrix = new float[16]; 
private final float[] mVMatrix = new float[16]; 
private float[] mRotationMatrix = new float[16]; 

//Declare as volatile because we are updating it from another thread 
public volatile float mAngle; 

//private Triangle triangle; 
private Sprite sprite; 

public MyGL20Renderer(final Context activityContext) 
{ 
    mActivityContext = activityContext; 
} 

public void onSurfaceCreated(GL10 unused, EGLConfig config) 
{ 
    //Set the background frame color 
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 

    //Initialize Shapes 
    //triangle = new Triangle(); 
    sprite = new Sprite(mActivityContext); 
} 

public void onDrawFrame(GL10 unused) 
{ 
    //Redraw background color 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    //Set the camera position (View Matrix) 
    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); 

    //Create a rotation transformation for the triangle 
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f); 

    //Combine the rotation matrix with the projection and camera view 
    Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0); 

    //Draw Shape 
    //triangle.Draw(mMVPMatrix); 
    sprite.Draw(mMVPMatrix); 
} 

public void onSurfaceChanged(GL10 unused, int width, int height) 
{ 
    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(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 
} 

public static int loadShader(int type, String shaderCode) 
{ 
    //Create a Vertex Shader Type Or a Fragment Shader Type (GLES20.GL_VERTEX_SHADER OR GLES20.GL_FRAGMENT_SHADER) 
    int shader = GLES20.glCreateShader(type); 

    //Add The Source Code and Compile it 
    GLES20.glShaderSource(shader, shaderCode); 
    GLES20.glCompileShader(shader); 

    return shader; 
} 
} 
+0

[リンク](http://developer.android.com/training/graphics/opengl/index.html)は、その良いチュートリアルです。 – sarabhai05

+0

私はこのチュートリアルを終了しましたが、テクスチャリングに何も含まれていません – Strifex

+0

この投稿の変更後にスプライトクラスを使用しようとしています。しかし、私がスプライトを翻訳しようとすると、それは私に有線の動作を与えます。翻訳に同じ問題があったのだろうかと思います。 – user1673892

答えて

20

"v_TexCoordinate = a_TexCoordinate" +

されている必要があります

"v_TexCoordinate = a_TexCoordinate;" +

どうやら私は今、私はときに私が台無しに愚かなことを(笑)私に教えて、私のIDEのに頼っているだけでどれだけ実現し、セミコロンを忘れていました。

0

ソリューションはmTextureCoordを有効にするのと同じくらい簡単かもしれない... VertexAttribPointerを割り当てる前に、 ;

+0

私はそれを試みたが、それは私の問題を解決しなかった。 – Strifex

+0

固定!!、私の問題は、頂点シェーダにセミコロンがないことが判明しました。 – Strifex

1

テクスチャを以下で試し座標:

最終フロート[] cubeTextureCoordinateData = {
0.5、-0.5、 0.5,0.5、 -0.5,0.5、 -0.5、-0.5 }。

その作業。どうもありがとうございました。

9

fragmentShaderCodeに命名(または使用)変数vColorと間違いがあります。ここにあなたの変数は、名前vColorがあります

uniform vec4 vColor; 

と、この行で、それは私も

gl_Position = vPosition * uMVPMatrix; 

この

gl_Position = uMVPMatrix * vPosition; 
にシェーダでこれを変更します

gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate)); 
1

名v_Colorを持って

これは、イメージの位置を翻訳しようとするときに。