Transparent Background Color Removed From Texture

Started by
1 comment, last by Psychopathetica 10 years, 1 month ago

I've been a DirectX guru for a long time now using various languages such as VB6, VB.Net, C# and C++, and have decided to dive in to game programming on the Android which uses OpenGL and Java. I found out after researching the matter that it works very differently than DirectX. All I'm trying to accomplish is drawing a 2D sprite with a specific background color removed so only the sprite is seen, but strangely enough there was no code to be found to do this, at least I don't think. I tried every method I saw off of Google and nothing seems to want to remove the background color off the texture. The image i'm using is a PNG, and this is some of my code. The MainActivity doesn't need displayed because the problem doesn't exist there. But here is where the problem may exist. Thanks in advance:

OpenGL_Renderer.java


package com.example.texturemap;

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

import android.content.Context;

import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;

public class OpenGL_Renderer implements Renderer 
{
	private Polygon polygon;
	private final Context context;
	
	public OpenGL_Renderer(final Context context)
	{
		this.context = context;
		polygon = new Polygon();
	}
	
	
	@Override
	public void onDrawFrame(GL10 gl) 
	{
	    
	    
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glTranslatef(100.0f, 100.0f, 0.0f);
		polygon.draw(gl);
		gl.glPopMatrix();
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) 
	{
		if(height == 0) height = 1;
		
	    gl.glDisable( GL10.GL_CULL_FACE );
	    gl.glDisable( GL10.GL_DEPTH_TEST );
		gl.glLoadIdentity();
		gl.glViewport(0, 0, width, height);
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		//GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
		GLU.gluOrtho2D(gl, (float)0, (float)width, (float)height, (float)0);
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) 
	{
		polygon.loadTexture(gl,this.context,R.drawable.link_stand_face_down2);
		gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		gl.glEnable(GL10.GL_BLEND);
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		
	}
}

Polygon.java


package com.example.texturemap;

//import java.io.IOException;
//import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

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

public class Polygon 
{
	
	private FloatBuffer vertexBuffer;	// buffer holding the vertices
	private FloatBuffer textureBuffer;
	public int[] textures = new int[1];
	
	public float texture[] =
	{
		0.0f, 0.0f,
		1.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f
	};
	
	public float vertices[] = 
	{
			0.0f, 0.0f,  0.0f,		// V1 - first vertex (x,y,z)
			90.0f, 0.0f,  0.0f,	// V2 - second vertex
			0.0f, 115.0f,  0.0f,	// V3 - third vertex
			90.0f, 115.0f,  0.0f	// V4 - forth vertex
	};
	
	public Polygon() 
	{
		// a float has 4 bytes so we allocate for each coordinate 4 bytes
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
		byteBuffer.order(ByteOrder.nativeOrder());
		
		// allocates the memory from the byte buffer
		vertexBuffer = byteBuffer.asFloatBuffer();
		
		// fill the vertexBuffer with the vertices
		vertexBuffer.put(vertices);
		
		// set the cursor position to the beginning of the buffer
		vertexBuffer.position(0);
		
		
		byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
		byteBuffer.order(ByteOrder.nativeOrder());
		textureBuffer = byteBuffer.asFloatBuffer();
		textureBuffer.put(texture);
		textureBuffer.position(0);
	}
	
	public void loadTexture(GL10 gl, final Context context, final int resourceId)
	{
		
		final Options options = new Options();
	    options.inScaled = false;
		
		// loading texture
		final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
		
		//InputStream is = context.getResources().openRawResource(R.drawable.jake);

	    //Bitmap bitmap = null;
	    //try {
	    //    bitmap = BitmapFactory.decodeStream(is);

	    //} finally {
	    //    //Always clear and close
	    //    try {
	    //        is.close();
	    //        is = null;
	    //    } catch (IOException e) {
	    //    }
	    //}
		
		// generate one texture pointer
		gl.glGenTextures(1, textures, 0);
		// ...and bind it to our array
		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_NEAREST);
		
		// Use Android GLUtils to specify a two-dimensional texture image from our bitmap 
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
		
		// Clean up
		bitmap.recycle();
	}
	
	public void draw(GL10 gl) 
	{

		gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
		gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
		
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
		// Point to our vertex buffer
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

		// Draw the vertices as triangle strip
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
		
		//Disable the client state before leaving
        gl.glDisableClientState (GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
	}
}

Advertisement

Ok, this probably works a bit different in GL than with DX.

I know what you're talking about, as I'm familiar with it through SDL... And I'm guessing probably most other 2D APIs also have something similar. It's called "color key transparency", where you specify a specific color to be used as transparent...

But, this is kind of a hangover from older methodolgy, and the way GL deals with alpha is more "real" . . .

Didn't muddle through your code, but I can explain the best routes to take...

Mainly two avenues, for example, if you're not using shaders...

You will have to explicitly "inject" the alpha value into RGBA data when you load the image. Depending on your knowledge of code, this may or may not be somewhat difficult. Essentially, after you have your image data in a buffer ... read through each RGB value, compare it to your color key, and replace the A value with something if it matches.

If you do use shaders, you can do it in the shader itself.. You'll probably have to pass a color key variable as a uniform that contains the RGB value you want to match. That way you can send something like -1 if you don't want color key alpha for a texture.

I figured it out!

The solution...Photoshop. I have to freaking use photoshop to add my own transparent backgrounds. Heres what I did. Before I do anything I make my image have a purple background using RGB(255, 0 255) so the transparency works fluently. Although I can do it in photoshop, I found Microsoft Paint to be easier to fill the background with a color. Now with photoshop after opening the image, I zoom in the image using the magnifying glass from the toolbar and click "Fit to Screen" shown below the menu bar so I can see what I'm doing, just in case I notice the transparency isn't the result I expect. Then I press the "W" key to access the Magic Wand Tool and click the area I want to be transparent. If its perfect, I press Ctrl-X to cut it out. The entire background has been removed, and I save the image as a PNG. Believe it or not, it went pretty quickly if anyone plans on doing this to multiple images.

Then after I put the image in my res/drawable folder found in the Package Explore of my android eclipse project (manually created btw), which creates a resource, I pressed play aaaaand....success! The image is finally transparent. Didn't have to add some stupid shading code or add a couple for loops to remove the color I wanted pixel by pixel, which for some stupid reason is the results everyone seems to be getting on Google. Photoshop ftw!!!

This topic is closed to new replies.

Advertisement