Volevo provare a fare una specie di platform 2D per android con opengl, ma mi sono bloccato praticamente all'inizio.
Non riesco infatti ad applicare texture che contengano trasparenze. Finché devo disegnare quadrati o rettangoli completamente texturizzati va bene (guardare la scatola o il terreno verde nell'immagine sotto), invece quando devo disegnare altre forme, se cerco di texturizzarle su una superficie quadrata mi viene una cosa strana (i tre rettangoli texturizzati male).
Come si fa quindi per disegnare cose che non siano quadrati?

Questa è la classe Rectangle che uso. Per caricarci una texture chiamo Rectangle.loadGLTexture(), per disegnarlo chiamo Rectangle.draw() da Renderer.onDrawFrame().
public class Rectangle extends Platform{
/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;
/** The buffer holding the indices */
private ByteBuffer indexBuffer;
private int[] textures = new int[1];
/**
* Ordine: bottom left, bottom right, top left, top right. 3 coordinate per vertice (x,y,z)
*/
private final float [] vertices=new float[12];
private float texture[] = {
//Mapping coordinates for the vertices
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
private byte indices[] = {
//Faces definition
0,1,2, 1,2,3
};
/**
* The Square constructor.
*
* Initiate the buffers.
*
* @param width
* @param height
*/
public Rectangle(float width, float height) {
vertices[0]=0; vertices[3]=width; vertices[6]=0; vertices[9]=width;
vertices[1]=0; vertices[4]=0; vertices[7]=height; vertices[10]=height;
this.width=width;
this.height=height;
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
}
/**
* The object own drawing function.
* Called from the renderer to redraw this instance
* with possible changes in values.
*
* @param gl - The GL Context
*/
public void draw(GL10 gl) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Set the face rotation
gl.glFrontFace(GL10.GL_CW);
//Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//Enable vertex buffer
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//Draw the vertices as triangle strip
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
/**
* Loads a texture for this object.
*
* @param gl GL10 surface
* @param context Application context
* @param id Resource id of the texture to load
*/
public void loadGLTexture(GL10 gl, Context context, int id) {
InputStream is = context.getResources().openRawResource(id);
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(is);
bitmap = bitmap.extractAlpha();
} finally {
try {
is.close();
is = null;
} catch (IOException e) {
}
}
//Generate one texture pointer... and bind it to our array
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Create Nearest Filtered Texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
//Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, bitmap, 0);
//Clean up
bitmap.recycle();
}
}Vi posto anche queste:
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) { //Prevent A Divide By Zero By
height = 1; //Making Height Equal One
}
gl.glViewport(0, 0, width, height); //Reset The Current Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
gl.glLoadIdentity(); //Reset The Projection Matrix
gl.glOrthof(0, width, 0, height, -1, 1);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
//carico le texture di ogni oggetto da disegnare
square.loadGLTexture(gl, context, R.drawable.crate);
//altre chiamate a loadGLTexture qui..
}