2012-10-03 14 views
6

Estoy tratando de hacer una aplicación que muestre texto usando OpenGL. Obtengo un comportamiento inesperado cuando trato de usar Matrix.translateM para mover el objeto especificado a una posición específica. Todas las demás matrices de transformación funcionan como yo esperaba.Android OpenGL ES 2.0: No obtengo los resultados que quiero con Matrix.traslateM

Esto es lo que me pasa cuando llamo Matrix.translateM(model_matrix, 0, -1.0f, 0, 0): result image

Ésta es la imagen sin necesidad de traducción: enter image description here

Este es mi código de render.

@Override 
public void onSurfaceCreated(GL10 unused, EGLConfig config) { 
    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 
    GLES20.glDisable(GLES20.GL_DEPTH_TEST); 
    GLES20.glEnable(GLES20.GL_BLEND); 
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 

    // create programs 
    simple_texture = new SimpleTexture(); 

    // create shapes 
    square = new Square(); 

    // create debug text handlers 
    text_fps = new Text(this.font, this.text_scale); 
    text_fps.setSize(50); 
    text_fps.setText("Test\nLonger line"); 

    // set camera position 
    final float eyeX = 0.0f; 
    final float eyeY = 0.0f; 
    final float eyeZ = -3.0f; 

    final float lookX = 0.0f; 
    final float lookY = 0.0f; 
    final float lookZ = 0.0f; 

    final float upX = 0.0f; 
    final float upY = 1.0f; 
    final float upZ = 0.0f; 

    Matrix.setLookAtM(view_matrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); 
} 

@Override 
public void onSurfaceChanged(GL10 unused, int width, int height) { 
    GLES20.glViewport(0, 0, width, height); 

    // set projection matrix 
    float ratio = (float) width/height; 
    Matrix.orthoM(projection_matrix, 0, -ratio, ratio, -1, 1, 3, 7); 

    setScreenRatio(ratio); 
    setScreenHeight(height); 
} 

@Override 
public void onDrawFrame(GL10 unused) { 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    // calculate projection and view transformation 
    Matrix.multiplyMM(vp_matrix, 0, projection_matrix, 0, view_matrix, 0); 

    // if we are connected to debugger draw statistics 
    drawStatistics(vp_matrix); 
} 

Y este es mi código draw para el texto.

// use predefined program 
    GLES20.glUseProgram(program); 

    // get attribute positions 
    attr_matrix = GLES20.glGetUniformLocation(program, "u_Matrix"); 
    attr_position = GLES20.glGetAttribLocation(program, "a_Position"); 
    attr_texture_position = GLES20.glGetAttribLocation(program, "a_TexturePosition"); 
    attr_texture = GLES20.glGetUniformLocation(program, "u_Texture"); 

    // set program parameters 
    GLES20.glEnableVertexAttribArray(attr_position); 
    GLES20.glVertexAttribPointer(attr_position, 2, GLES20.GL_FLOAT, false, 2 * 4, square_buffer); 

    // set texture parameters 
    GLES20.glEnableVertexAttribArray(attr_texture_position); 
    GLES20.glVertexAttribPointer(attr_texture_position, 2, GLES20.GL_FLOAT, false, 2 * 4, texture_buffer); 

    // set matrix 
    float[] result = new float[16]; 
    float ratio = (float) texture_height/texture_width; 
    float screen_scale = (float) texture_height/PageRenderer.getScreenHeight(); 

    Matrix.setIdentityM(model_matrix, 0); 
    Matrix.translateM(model_matrix, 0, -1, 0, 0); 
    Matrix.scaleM(model_matrix, 0, screen_scale, screen_scale * ratio, screen_scale); 

    Matrix.setIdentityM(result, 0); 
    Matrix.multiplyMM(result, 0, matrix, 0, model_matrix, 0); 
    GLES20.glUniformMatrix4fv(attr_matrix, 1, false, result, 0); 

    // assign texture 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, index); 
    GLES20.glUniform1i(attr_texture, 0); 

    // perform drawing 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 

    // disable vertex array 
    GLES20.glDisableVertexAttribArray(attr_position); 
    GLES20.glDisableVertexAttribArray(attr_texture_position); 

Shaders:

int vertex_shader = PageRenderer.loadShader(
      GLES20.GL_VERTEX_SHADER, 
      "uniform mat4 u_Matrix;" + 
      "attribute vec4 a_Position;" + 
      "attribute vec2 a_TexturePosition;" + 
      "varying vec2 v_TexturePosition;" + 
      "void main() {" + 
      " gl_Position = a_Position * u_Matrix;" + 
      " v_TexturePosition = a_TexturePosition;" + 
      "}" 
     ); 
    int fragment_shader = PageRenderer.loadShader(
      GLES20.GL_FRAGMENT_SHADER, 
      "precision mediump float;" + 
      "varying vec2 v_TexturePosition;" + 
      "uniform sampler2D u_Texture;" + 
      "void main() {" + 
      " gl_FragColor = texture2D(u_Texture, v_TexturePosition);" + 
      "}" 
     ); 

Escalado y rotación de trabajo como se esperaba, pero no puedo entender por qué se traduce no lo hace. Tenga en cuenta que no utilicé OpenGL hasta hace poco.

Esperaba que translateM moviera el texto a la izquierda, no lo 'rotó'.

+0

¿Qué se supone que parecen? ¿Que esperabas? Además, ¿puedes mostrar tus sombreadores? – Tim

+0

@Tim seguro. Perdón por la falta de detalles. Agregué el código de sombreado y la imagen de la forma que se ve sin 'translateM'. Esperaba que 'translateM' moviera la imagen hacia la izquierda. – MeanEYE

+0

Ah, lo siento. Encontré el problema ahora que eché un segundo vistazo al código del sombreador. :) Gracias. – MeanEYE

Respuesta

11

¡El orden de las variables al calcular gl_Position es importante! La matriz mundial va primero y luego las coordenadas del vértice. Al hacer la pregunta, lo sabía, pero no presté atención, ya que el código del sombreador está tomado del tutorial de Android OpenGL. Se ware gente. ¡El tutorial no es correcto!

correcta de código de sombreado:

int vertex_shader = PageRenderer.loadShader(
      GLES20.GL_VERTEX_SHADER, 
      "uniform mat4 u_Matrix;" + 
      "attribute vec4 a_Position;" + 
      "attribute vec2 a_TexturePosition;" + 
      "varying vec2 v_TexturePosition;" + 
      "void main() {" + 
      " gl_Position = u_Matrix * a_Position;" + 
      " v_TexturePosition = a_TexturePosition;" + 
      "}" 
     ); 
    int fragment_shader = PageRenderer.loadShader(
      GLES20.GL_FRAGMENT_SHADER, 
      "precision mediump float;" + 
      "varying vec2 v_TexturePosition;" + 
      "uniform sampler2D u_Texture;" + 
      "void main() {" + 
      " gl_FragColor = texture2D(u_Texture, v_TexturePosition);" + 
      "}" 
     ); 
+0

Lo más horrible es que este error es invisible si dibujas formas simples y será desastroso cuando dibujas formas complejas. Gracias a MeanEYE !!! –

+0

Estoy teniendo el mismo problema pero su solución solo bloquea el sombreador para mí. Solo puedo hacer que las cosas se rendericen cuando hago 'gl_position = a_Position * u_Matrix'. Incluso intenté cambiar el orden de multiplicación de vista y proyección (para calcular 'u_Matrix') en vano. ¿Algunas ideas? ¿Funcionó el tuyo inmediatamente cuando intercambiaste V y M o primero tenías que hacer otra cosa? – Navigateur

+0

Sí funcionó de inmediato si no recuerdo mal. Quizás hay algo más que está mal con tu sombreador, pero solo en los casos en que haces las cosas bien. Mi experiencia con OpenGL es muy limitada. Sugiero publicar una nueva pregunta sobre SO. – MeanEYE

Cuestiones relacionadas