2017-02-17 58 views
0

我正在使用OpenGLES,並嘗試在我的projet上添加紋理正方形。 我設計了一個簡單的我有紋理的方形課,我試着展示它。我的三角形在渲染類中調用。現在TexturedSquare類只顯示一個空位圖。紋理android示例

package com.example.nativecpp; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.opengl.GLES20; 
import android.opengl.GLUtils; 

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

public class TexturedSquare { 

    private static int[] textureHandle; 

    private final String vertexShaderCode = 
    "uniform mat4 uMVPMatrix;\n" + 
      "attribute vec2 aPosition;\n" + 
      "attribute vec2 aTexPos;\n" + 
      "varying vec2 vTexPos;\n" + 
      "void main() {\n" + 
      " vTexPos = aTexPos;\n" + 
      " gl_Position = uMVPMatrix * vec4(aPosition.xy, 0.0, 1.0);\n" + 
      "}"; 

    private final String fragmentShaderCode = 
      "precision mediump float;\n"+ 
        "uniform sampler2D uTexture;\n" + 
        "varying vec2 vTexPos;\n" + 
        "void main(void)\n" + 
        "{\n" + 
        " gl_FragColor = texture2D(uTexture, vTexPos);\n" + 
        "}"; 

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


    // number of coordinates per vertex in this array 
    final int COORDS_PER_VERTEX = 4; 
    float squareCoords[] = { 
      -1.0f,-1.0f,  0.0f, 0.0f, // vertex 3 
      -1.0f, 1.0f,  0.0f, 1.0f, // vertex 1 
      1.0f,-1.0f,  1.0f, 0.0f, // vertex 2 
      1.0f, 1.0f,  1.0f, 1.0f, // vertex 0 
    }; // top right 

    private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices 

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

    float color[] = { 0.2f, 0.709803922f, 0.898039216f, 1.0f }; 

    /** 
    * Sets up the drawing object data for use in an OpenGL ES context. 
    */ 
    public TexturedSquare() { 
     // initialize vertex byte buffer for shape coordinates 
     ByteBuffer bb = ByteBuffer.allocateDirect(
     // (# of coordinate values * 4 bytes per float) 
       squareCoords.length * 4); 
     bb.order(ByteOrder.nativeOrder()); 
     vertexBuffer = bb.asFloatBuffer(); 
     vertexBuffer.put(squareCoords); 
     vertexBuffer.position(0); 

     // initialize byte buffer for the draw list 
     ByteBuffer dlb = ByteBuffer.allocateDirect(
       // (# of coordinate values * 2 bytes per short) 
       drawOrder.length * 2); 
     dlb.order(ByteOrder.nativeOrder()); 
     drawListBuffer = dlb.asShortBuffer(); 
     drawListBuffer.put(drawOrder); 
     drawListBuffer.position(0); 

     // prepare shaders and OpenGL program 
     int vertexShader = MyGLRenderer.loadShader(
       GLES20.GL_VERTEX_SHADER, 
       vertexShaderCode); 
     int fragmentShader = MyGLRenderer.loadShader(
       GLES20.GL_FRAGMENT_SHADER, 
       fragmentShaderCode); 

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


    } 


    public int loadTexture() 
    { 
     textureHandle = new int[1]; 
if (textureHandle[0] != -1) 
{ 
      GLES20.glGenTextures(1, textureHandle, 0); 

      int uTexture = GLES20.glGetAttribLocation(mProgram, "uTexture"); 

      final BitmapFactory.Options options = new BitmapFactory.Options(); 
      options.inScaled = false; // No pre-scaling 

      // Read in the resource 
      Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types 
      Bitmap bitmap = Bitmap.createBitmap(640, 480, conf); // this creates a MUTABLE bitmap 

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

      GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]); 
      GLES20.glUniform1i(uTexture, 0); 

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

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

     return textureHandle[0]; 
    } 


    /** 
    * Encapsulates the OpenGL ES instructions for drawing this shape. 
    * 
    * @param mvpMatrix - The Model View Project matrix in which to draw 
    * this shape. 
    */ 
    public void draw(float[] mvpMatrix) { 

     // Add program to OpenGL environment 
     GLES20.glUseProgram(mProgram); 

     // get handle to vertex shader's vPosition member 
     mPositionHandle  = GLES20.glGetAttribLocation(mProgram, "aPosition"); 
     mTexturePosHandle = GLES20.glGetAttribLocation(mProgram, "aTexPos"); 

     // Enable a handle to the triangle vertices 
     GLES20.glEnableVertexAttribArray(mPositionHandle); 
     MyGLRenderer.checkGlError("glGetUniformLocation"); 

     // Prepare the triangle coordinate data 
     GLES20.glVertexAttribPointer(
       mPositionHandle, 2, 
       GLES20.GL_FLOAT, false, 
       vertexStride, vertexBuffer); 

     GLES20.glEnableVertexAttribArray(mTexturePosHandle); 

     GLES20.glVertexAttribPointer(
       mPositionHandle, 2, 
       GLES20.GL_FLOAT, false, 
       vertexStride, (vertexBuffer.position(2))); 

     // 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_TRIANGLES, drawOrder.length, 
       GLES20.GL_UNSIGNED_SHORT, drawListBuffer); 

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

} 

我的程序崩潰與錯誤:

FATAL EXCEPTION: GLThread 6633 
                        Process: com.example.nativecpp, PID: 3281 
                      java.lang.RuntimeException: glGetUniformLocation: glError 1282 
                        at com.example.nativecpp.MyGLRenderer.checkGlError(MyGLRenderer.java:198) 
                         at com.example.nativecpp.TexturedSquare.draw(TexturedSquare.java:179) 
                         at com.example.nativecpp.MyGLRenderer.onDrawFrame(MyGLRenderer.java:118) 
                         at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1553) 
                         at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1253) 

似乎有在我的索引頂點位置的錯誤,但我不解決這個問題。

編輯: 我仍然有相同的錯誤:出現

MyGLRenderer: glGetUniformLocation: glError 1282 

錯誤之後:

GLES20.glVertexAttribPointer(
     mPositionHandle, 2, 
     GLES20.GL_FLOAT, false, 
     vertexStride, vertexBuffer); 

GLES20.glEnableVertexAttribArray(mPositionHandle); 
MyGLRenderer.checkGlError("glGetUniformLocation"); ####ERROR!!! 

編輯2: 在該行: uTexture = GLES20.glGetAttribLocation(mProgram ,「uTexture」); uTexture = -1我不認爲這是正常的...所以我將其更改爲

int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture"); 

現在uTexture等於1,但該計劃仍然停留在GLES20.glUniform1i(uTexture, 0); //glGetUniformLocation: glError 1282

編輯3: 當我把這些線放在繪圖函數中時:

int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture"); 
      GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]); 
      MyGLRenderer.checkGlError("glGetUniformLocation"); 
      GLES20.glUniform1i(uTexture, 0); 
      MyGLRenderer.checkGlError("glGetUniformLocation"); 

      GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 
      // Draw the square 

有沒有錯誤...爲什麼? GPU沒有足夠的時間將數據放入內存中?

+0

'textureHandle [0]!= 0'具有id 0的紋理是完全有效的,您不應該檢查此 –

+0

您還將頂點數據加載到位置屬性兩次。 –

回答

0

您意外地在位置屬性中加載了紋理座標。更改

GLES20.glVertexAttribPointer(
      mPositionHandle, 2, 
      GLES20.GL_FLOAT, false, 
      vertexStride, (vertexBuffer.position(2))); 

GLES20.glVertexAttribPointer(
      mTexturePosHandle, 2, 
      GLES20.GL_FLOAT, false, 
      vertexStride, (vertexBuffer.position(2))); 

幾個顯着的 「失誤」:

你應該只得到屬性位置一次,NIT每幀,因爲它是一個costy功能。

如果紋理的編號爲0,那麼您不會執行任何操作,但仍然有效,請檢查編號爲-1的紋理。

鏈接着色器程序時可能會出現問題,ypu應檢查它的鏈接狀態是否有誤,如果是,則記錄輸出glGetProgramInfoLog

+0

謝謝我做了修改。 glGetProgramInfoLog向我發送一個空字符串:String LogInfo = GLES20.glGetProgramInfoLog(mProgram); –

+0

@Xavier只有在鏈接失敗時才使用。 –

+0

好的抱歉,我認爲錯誤來自loadTexture方法,因爲當我刪除它時,checkGlError不會向我發送錯誤。 –