2011-07-27 16 views
5

Estoy luchando con el salto en complejidad de OpenGL ES 1.xa 2.0. Intento aplicar una textura a un plano rectangular y luego poder escalar y traducir ese plano manteniendo la textura correctamente mapeada.La textura OpenGL no sigue la geometría

Mi pregunta es: ¿qué estoy haciendo mal y cómo voy a poder texturizar mis planos al traducirlos y escalarlos?

voy a publicar mi clase de procesador, la clase que objetos utilizar para dibujar a sí mismos, y mis vértices y sombreadores de fragmentos:

GL Renderer:

package com.detour.raw; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.Matrix; 

public class GameRenderer implements GLSurfaceView.Renderer{ 

private static final String TAG = "GameRenderer"; 
Context mContext; 
Bitmap bitmap; 

private float red = 0.5f; 
private float green = 0.5f; 
private float blue = 0.5f; 

Shader shader; 
int program; 
FPSCounter fps; 
Sprite sprite; 
Sprite sprite2; 
int x = 0; 

private int muMVPMatrixHandle; 

private float[] mMVPMatrix = new float[16]; 
private float[] mProjMatrix = new float[16]; 
private float[] mMVMatrix = new float[16]; 
//private float[] mVMatrix = new float[16]; 
//private float[] mMMatrix = new float[16]; 
//private float[] mVPMatrix = new float[16]; 
//private float[] mIMatrix = new float[16]; 



public GameRenderer(Context context){ 
    mContext = context; 

    //create objects/sprites 
    sprite = new Sprite(mContext); 
    sprite2 = new Sprite(mContext); 
    fps = new FPSCounter(); 
} 

@Override 
public void onDrawFrame(GL10 gl) { 

    GLES20.glClearColor(red, green, blue, 1.0f); 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 

    GLES20.glUseProgram(program); 
    //Matrix.setIdentityM(mIMatrix, 0); 

    //Matrix.multiplyMM(mMVMatrix, 0, mVMatrix, 0, mMMatrix, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVMatrix , 0); 

    GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 

    sprite.draw(); 
    /*if(x>3){ 
     x=0; 
    } 
    if(x%2==0){ 
     sprite.draw(); 
    }else{ 
     sprite2.draw(); 
    } 
    x++;*/ 

    //fps.calculate(); 
    //fps.draw(gl); 
} 

@Override 
public void onSurfaceChanged(GL10 gl, int width, int height) { 

    GLES20.glViewport(0, 0, width, height); 
    float ratio = ((float)(width))/((float)(height)); 
    Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 0.5f, 10); 
    Matrix.setLookAtM(mMVMatrix, 0, 0, 0, 1.0f, 0.0f, 0f, 0f, 0f, 1.0f, 0.0f); 
} 

@Override 
public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
    // TODO Auto-generated method stub 

    /*int error = GLES20.glGetError(); 
    Log.d(LOG_TAG, ""+error);*/ 

    shader = new Shader(R.raw.sprite_vs, R.raw.sprite_fs, mContext); 
    program = shader.getProgram(); 

    muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "u_MVPMatrix"); 

    GLES20.glEnable(GLES20.GL_TEXTURE_2D); 
    GLES20.glEnable(GLES20.GL_DEPTH_TEST); 
    GLES20.glClearDepthf(1.0f); 
    GLES20.glDepthFunc(GLES20.GL_LEQUAL); 
    GLES20.glDepthMask(true); 
    GLES20.glEnable(GLES20.GL_CULL_FACE); 
    GLES20.glCullFace(GLES20.GL_BACK); 
    GLES20.glClearColor(red, green, blue, 1.0f); 


    sprite.loadGLTexture(R.drawable.raw1a, program); 
    sprite2.loadGLTexture(R.drawable.raw2, program); 

    System.gc(); 
} 

} 

clase Disponibles:

package com.detour.raw; 

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

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

public class RenderVisible implements Renderable{ 

Context mContext; 
Bitmap bitmap; 

private int vertexHandle; 
private int texCoordHandle; 
private int textureHandle; 

private int[] textures = new int[1]; 

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

private float vertices[] = { 
     -1.0f, 1.0f,// 0.0f, 
     -1.0f, -1.0f,// 0.0f, 
     1.0f, -1.0f,// 0.0f, 
     1.0f, 1.0f// 0.0f, 
     }; 

private short[] indices = { 
     0, 1, 2, 
     0, 2, 3}; 

private FloatBuffer vertexBuffer; 
private FloatBuffer textureBuffer; 
private ShortBuffer indexBuffer; 


public RenderVisible(Context context){ 

    mContext = context; 

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); 
    vbb.order(ByteOrder.nativeOrder()); 
    vertexBuffer = vbb.asFloatBuffer(); 
    vertexBuffer.put(vertices); 
    vertexBuffer.position(0); 

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoordinates.length * 4); 
    byteBuf.order(ByteOrder.nativeOrder()); 
    textureBuffer = byteBuf.asFloatBuffer(); 
    textureBuffer.put(textureCoordinates); 
    textureBuffer.position(0); 

    ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); 
    ibb.order(ByteOrder.nativeOrder()); 
    indexBuffer = ibb.asShortBuffer(); 
    indexBuffer.put(indices); 
    indexBuffer.position(0); 

} 

@Override 
public void draw() { 

    GLES20.glEnableVertexAttribArray(vertexHandle); 
    GLES20.glVertexAttribPointer(vertexHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer); 
    GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer); 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); 
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer); 

} 

@Override 
public void loadGLTexture(int id, int program) { 

    vertexHandle = GLES20.glGetAttribLocation(program, "a_position"); 
    texCoordHandle = GLES20.glGetAttribLocation(program, "a_texcoord"); 
    textureHandle = GLES20.glGetUniformLocation(program, "u_texture"); 

    bitmap = BitmapFactory.decodeResource(mContext.getResources(), id); 
    /*InputStream is = mContext.getResources().openRawResource(id); 
    try { 
     bitmap = BitmapFactory.decodeStream(is); 
    } finally { 
     try { 
      is.close(); 
      is = null; 
     } catch (IOException e) { 
     } 
    }*/ 

    GLES20.glGenTextures(1, textures, 0); 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); 
    GLES20.glUniform1i(textureHandle, 0); 

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); 
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); 

    //GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, FRAME_WIDTH, FRAME_HEIGHT, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuf);//(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

    bitmap.recycle(); 
} 

} 

Fragmento Shader:

precision mediump float; 

uniform sampler2D u_texture; 

varying vec2 v_texcoord; 

void main() 
{ 
    gl_FragColor = texture2D(u_texture, v_texcoord); 
} 

Vertex Shader:

attribute vec2 a_position; 
attribute vec2 a_texcoord; 

uniform mat4 u_MVPMatrix; 

varying vec2 v_texcoord; 

void main() 
{ 
    gl_Position = vec4(a_position, 0.0, 1.0) * u_MVPMatrix; 
    v_texcoord = a_position * vec2(0.5, -0.5) + vec2(0.5); 
} 

Cuando ejecuto el programa como este, me sale mi resultado esperado:

enter image description here

Cuando cambio los vértices de mi renderable (en este caso todo dividido cada uno valor por 2), la forma de mi avión cambia pero la textura no se mueve con ella de la manera que yo esperaría. No estoy seguro de por qué (una explicación sería agradable).

enter image description here

Cuando arreglo a los vértices de mi avión y cambiar el vertex shader para aceptar las coordenadas de textura se lo doy (v_texcoord = a_texcoord;), me sale el tamaño correcto cuadrado, pero la textura no es visible/cuadrado es completamente blanco

También estoy intentando hacer métodos para la clase renderable (RenderVisible) que haría que mover y escalar mis sprites sea simple. ¿Cómo podría hacer eso?

+0

¿Qué pasa si no calcular las coordenadas de textura en el programa de vértice, sino utilizar los que se especifican en el código java? (En el programa de vértices: v_texcoord = a_texcoord;) –

+0

Obtengo el tamaño correcto cuadrado pero la textura no es visible/el cuadrado es completamente blanco. – Amplify91

Respuesta

3

Sus coordenadas de textura son una función de las coordenadas de su vértice, es decir el por qué de este comportamiento, solucionarlo, basta con cambiar en su vertex shader:

v_texcoord = a_texcoord; 

por lo que utilizar sus coordenadas de textura constantes. Asimismo, recuerda que permita la textura coord vértice atributo:

GLES20.glEnableVertexAttribArray(texCoordHandle); 
+0

Mencioné esto al final de mi pregunta. Cuando intento eso, obtengo el rectángulo de tamaño correcto, pero es completamente blanco, sin textura. – Amplify91

+1

@ Amplify91 Vea la respuesta actualizada, no habilitó el texcoord attrib. –

+1

UGH! ¡Gracias! Sabía que tenía que ser un error minúsculo y estúpido. ¿Cuál es su sugerencia sobre cómo traducir y escalar los sprites? – Amplify91