2017-02-17 61 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不会向我发送错误。 –