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:
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).
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?
¿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;) –
Obtengo el tamaño correcto cuadrado pero la textura no es visible/el cuadrado es completamente blanco. – Amplify91