2017-02-17 25 views
0

Я работаю над OpenGLES, и я пытаюсь добавить текстурированный квадрат на свой проект. Я проектирую простой мой текстурированный квадратный класс, и я пытаюсь его отобразить. Мой треугольник вызывается в классе Rendered. На данный момент класс TexturedSquare просто отображает пустое растровое изображение.Текстурированный образец андроида

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) 

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

Edit: Я до сих пор ту же ошибку:

MyGLRenderer: glGetUniformLocation: glError 1282 

ошибка появляется после того, что:

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

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

Edit 2: В этой строке: uTexture = GLES20.glGetAttribLocation (mProgram , "uTexture"); uTexture = -1 Я не думаю, что это нормально ... так что я изменить его на

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

Теперь uTexture равно 1, но программа все еще застряли на GLES20.glUniform1i(uTexture, 0); //glGetUniformLocation: glError 1282

Edit 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 

Ошибка отсутствует ... почему? Графический процессор не имеет времени для размещения данных в памяти?

+0

'textureHandle [0]! = 0' Текстура с идентификатором 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 не отправляет мне ошибку. –