2015-06-17 4 views
1

Я пытаюсь текстурировать ArrayList прямоугольника «кирпичи» для моей игры. У меня есть код, который отлично работает, когда есть только один прямоугольник для текстуры, но в любое время, когда я добавляю больше, шейдер фрагмента применяет текстуру только к выделенному последнему прямоугольнику, а остальные визуализируются невидимыми. Мне не нужно использовать разные текстуры, точно такую ​​же текстуру для каждого прямоугольника. Что мне нужно изменить с помощью моих шейдеров фрагментов, чтобы это произошло?Несколько объектов с одинаковой текстурой

Вот код для моего графика класса:

private ArrayList<FloatBuffer> bricks; 
private FloatBuffer textureBuffer; 
private ShortBuffer drawListBuffer; 
static final int COORDS_PER_VERTEX = 3; 
private short drawOrder[] = {0, 1, 2, 0, 2, 3}; //Order to draw vertices 

private float[] textureCoords = 
       { 1.0f, 1.0f, 
       1.0f, 0.0f, 
       0.0f, 0.0f, 
       0.0f, 1.0f }; 

private final int mProgram; 

//New variables for textures 
private int[] texBufferID = new int[1]; 
private int texCoordID; 
private int texID; 

//Use this guy to access and set the view transformation 
private int mMVPMatrixHandle; 

private final String vertexShaderCode = 
     //These are the coordinates used to pass texCoord over to the fragmentShader 
     "attribute vec2 s_vTexCoord;" + 
       "varying vec2 texCoord;" + 

       "uniform mat4 uMVPMatrix;" + 
       "attribute vec4 vPosition;" + 
       "void main() {" + 
       //The line that does the aforementioned pass 
       " texCoord = s_vTexCoord;" + 
       //the matrix has to modify glPosition 
       //Note: uMVPMatrix has to be first here. Cuz reasons 
       " gl_Position = uMVPMatrix * vPosition;" + 
       "}"; 

private final String fragmentShaderCode = 
     "varying vec2 texCoord;" + 
       "precision mediump float;" + 
       "uniform sampler2D texture;" + 
       "void main() {" + 
       " gl_FragColor = texture2D(texture, texCoord);" + //How is texture defined? 
       "}"; 

public Graphics(Context context) { 
    //Load our texture coordinates into a buffer 
    ByteBuffer b = ByteBuffer.allocateDirect(textureCoords.length * 4); 
    b.order(ByteOrder.nativeOrder()); 
    //create a floating point buffer from bb 
    textureBuffer = b.asFloatBuffer(); 
    //Add our coordinates to the float buffer 
    textureBuffer.put(textureCoords); 
    //Set the buffer to read the first coordinate 
    textureBuffer.position(0); 

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

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

    //create empty OpenGL ES Program 
    mProgram = GLES20.glCreateProgram(); 

    //Add the shaders 
    GLES20.glAttachShader(mProgram, vertexShader); 
    GLES20.glAttachShader(mProgram, fragmentShader); 

    //Create OpenGL program executables 
    GLES20.glLinkProgram(mProgram); 

    GLES20.glEnable(GLES20.GL_TEXTURE_2D); 
    //Pass in our texture coordinates to the vertex shader 
    texCoordID = GLES20.glGetAttribLocation(mProgram, "s_vTexCoord"); 
    GLES20.glEnableVertexAttribArray(texCoordID); 
    GLES20.glVertexAttribPointer(texCoordID, 2, GLES20.GL_FLOAT, false, 0, textureBuffer); 

    //Read in the bmp from file to bmp 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inScaled = false; // No pre-scaling 
    Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.brick, options); 

    //Read bmp into OpenGL as texture 0 
    GLES20.glGenTextures(1, texBufferID, 0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texBufferID[0]); 

    //This is basically OpenGL texture preferences 
    //GL_NEAREST means it grabs the color value of the nearest pixel for scaling. Fast and dirty. 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); 
    bmp.recycle(); 

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

    //Tell our vertex shader that texture 0 is the active texture 
    texID = GLES20.glGetUniformLocation(mProgram, "texture"); 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    GLES20.glUniform1i(texID, 0); 
} 

public void newBricks(ArrayList<float[]> brickList){ 
    bricks = new ArrayList<>(); 
    for (int i = 0; i < brickList.size(); i++) { 
     float[] brick = brickList.get(i); 

     // initialize a buffer to hold the vertices 
     ByteBuffer bb = ByteBuffer.allocateDirect(
       //4 bytes per float 
       brick.length * 4); 
     //Tells bb to use the devices native byte order 
     bb.order(ByteOrder.nativeOrder()); 

     //create a floating point buffer from bb 
     FloatBuffer vertexBuffer = bb.asFloatBuffer(); 
     //Add our coordinates to the float buffer 
     vertexBuffer.put(brick); 
     //Set the buffer to read the first coordinate 
     vertexBuffer.position(0); 

     bricks.add(vertexBuffer); 
    } 
} 

public void remove(int brick){ 
    bricks.remove(brick); 
} 

private int mPositionHandle; 

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

//We now pass draw the calculated camera and projection view matrix 
public void draw(float[] mvpMatrix) { 
    //Add program to the OpenGL ES environment 
    GLES20.glUseProgram(mProgram); 

    //Pass in our texture coordinates to the vertex shader 
    texCoordID = GLES20.glGetAttribLocation(mProgram, "s_vTexCoord"); 
    GLES20.glEnableVertexAttribArray(texCoordID); 
    GLES20.glVertexAttribPointer(texCoordID, 2, GLES20.GL_FLOAT, false, 0, textureBuffer); 

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

    //enable a handle to the brick vertices 
    GLES20.glEnableVertexAttribArray(mPositionHandle); 

    //get handle to the transformation matrix 
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 

    //pass the transformation matrix to the shader 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 

    for (int i = bricks.size() - 1; i >= 0; i--) { 

     //Prepare the brick coordinate data 
     GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, 
       GLES20.GL_FLOAT, false, 
       vertexStride, bricks.get(0)); 

     //Draw the brick 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount); 
    } 

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

ответ

1

Вы писали bricks.get(0) вместо bricks.get(i) в for петле public void draw(float[] mvpMatrix) функции.

А также вы можете удалить эту строку GLES20.glEnable(GLES20.GL_TEXTURE_2D);, потому что от фиксированной функции трубопровода OpenGL, но использовать шейдеры с OpenGL ES 2.0

+0

Вау .... Это работало. Не могу поверить, что я забыл об этом, я изменил его раньше, в то время как мои растровые изображения не загружались, чтобы попытаться заставить его работать. Чувствовать себя как дурака, не замечая, что за все эти часы! –

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