Masking Alpha with two 2D textures LWJGL?

Hello guys
I read a lot of guides but I didnt found one who work for me … or Im just too dumb to “translate them” to my code :yawn: …

I rendering my textures in this way:


public void render() {

		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sprite.getT());

		if (isLinealScale()) {
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
					GL_LINEAR);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
					GL_LINEAR);
		}

		float x = getPosX() + getModPosX() - getBindX();
		float y = getPosY() + getModPosY() - getBindY();
		float w = getPosX() + getModPosX() + getCurrentWidth() - getBindX();
		float h = getPosY() + getModPosY() + getCurrentHeight() - getBindY();

		float sprX = sprite.getX();
		float sprY = sprite.getY();
		float sprW = sprX + sprite.getW();
		float sprH = sprY + sprite.getH();

		// switch (blend) {
		// case MULTIPLY:
		// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		// break;
		// case SCREEN:
		// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		// break;
		//
		// default:
		// break;
		// }

		glPushMatrix();

		glTranslatef(x + getBindX(), y + getBindY(), 0);
		glRotatef(getAngle(), 0, 0, 1);
		glTranslatef(-x - getBindX(), -y - getBindY(), 0);

		glBegin(GL_QUADS);
		glColor4f(1.0f, 1.0f, 1.0f, getOpasity());
		if (flip) {
			glTexCoord2f(sprW, sprY);
			glVertex2f(x, y);
			glTexCoord2f(sprX, sprY);
			glVertex2f(w, y);
			glTexCoord2f(sprX, sprH);
			glVertex2f(w, h);
			glTexCoord2f(sprW, sprH);
			glVertex2f(x, h);

		} else {
			glTexCoord2f(sprX, sprY);
			glVertex2f(x, y);
			glTexCoord2f(sprW, sprY);
			glVertex2f(w, y);
			glTexCoord2f(sprW, sprH);
			glVertex2f(w, h);
			glTexCoord2f(sprX, sprH);
			glVertex2f(x, h);
		}
		glColor4f(1.0f, 1.0f, 1.0f, 1f);
		glEnd();

		glPopMatrix();

		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
		// glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		if (isLinealScale()) {
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
					GL_NEAREST);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
					GL_NEAREST);
		}

	}

as you can see I dont use “GL_TEXTURE_2D” when I bind a texture, instep i use “GL_TEXTURE_RECTANGLE_ARB”, this might be one of the reasons I cant accomplish the masking … but when I bind my texture id with GL_TEXTURE_2D I only get a white square :expressionless: (and Im using glEnable(GL_TEXTURE_2D) by default in my Display and even with that it doesnt work for me)

Any way … I create a new texture object extending my normal texture who work fine with png textures with alpha and with glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA) as the default blend.
This new object just add another sprite named mask who may or not has a different size, and may or not to be in the same png.

The type of masking i whant is this one …
having this texture (this texture may have Alpha channel):

and this mask (just white and black texture without Alpha channel??? ??? really want this one have alpha channel too :clue:)

and with some combination of glBlendFunc in the texture and the mask … get this

(without the background texture :expressionless: …just transparency)

By the moment I have this code


public void render() {

		glDisable(GL_DEPTH_TEST);

		float x = getPosX() + getModPosX() - getBindX();
		float y = getPosY() + getModPosY() - getBindY();

		glPushMatrix();

		glTranslatef(x + getBindX(), y + getBindY(), 0);
		glRotatef(getAngle(), 0, 0, 1);
		glTranslatef(-x - getBindX(), -y - getBindY(), 0);

		// ============ First Render ==============

		// glColor4f(1.0f, 1.0f, 1.0f, 1f);
		// glColor4f(1.0f, 1.0f, 1.0f, 0f);
		// glColor4f(0f, 0f, 0f, 1f);

		// glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		// GL14.glBlendEquation(GL14.GL_FUNC_ADD);
		// GL14.glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA,
		// GL_ZERO, GL_ONE);

		// glBlendFunc(GL_ONE, GL_ZERO);

		// glBlendFunc(GL_ONE, GL_SRC_COLOR);
		// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
		// glBlendFunc(GL_ONE, GL_DST_COLOR);
		// glBlendFunc(GL_ONE, GL_ONE_MINUS_DST_COLOR);
		// glBlendFunc(GL_ONE, GL_SRC_ALPHA);
		// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		// glBlendFunc(GL_ONE, GL_DST_ALPHA);
		// glBlendFunc(GL_ONE, GL_ONE_MINUS_DST_ALPHA);
		// glBlendFunc(GL_ONE, GL_SRC_ALPHA_SATURATE);
		// glBlendFunc(GL_ONE, GL_CONSTANT_COLOR);
		// glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_COLOR);
		// glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA);
		// glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA);

		// glBlendFunc(GL_ONE_MINUS_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);

		glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		renderMask();

		// ============== End First Render ==============

		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);

		// ============== Second Render ==============

		glColor4f(1.0f, 1.0f, 1.0f, getOpasity());
//		glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		 glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		renderSprite();

		// ============== End Second Render ==============

		glPopMatrix();

		glColor4f(1.0f, 1.0f, 1.0f, 1f);

		glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glEnable(GL_DEPTH_TEST);

	}

	private void renderMask() {

		float x = getPosX() + getModPosX() - getBindX();
		float y = getPosY() + getModPosY() - getBindY();
		float w = getPosX() + getModPosX() + getCurrentWidth() - getBindX();
		float h = getPosY() + getModPosY() + getCurrentHeight() - getBindY();

		float maskSprX = mask.getX();
		float maskSprY = mask.getY();
		float maskSprW = maskSprX + mask.getW();
		float maskSprH = maskSprY + mask.getH();

		if (linearMask) {
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
					GL_LINEAR);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
					GL_LINEAR);
		}

		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mask.getT());

		glBegin(GL_QUADS);
		if (isFlip()) {
			glTexCoord2f(maskSprW, maskSprY);
			glVertex2f(x, y);
			glTexCoord2f(maskSprX, maskSprY);
			glVertex2f(w, y);
			glTexCoord2f(maskSprX, maskSprH);
			glVertex2f(w, h);
			glTexCoord2f(maskSprW, maskSprH);
			glVertex2f(x, h);

		} else {
			glTexCoord2f(maskSprX, maskSprY);
			glVertex2f(x, y);
			glTexCoord2f(maskSprW, maskSprY);
			glVertex2f(w, y);
			glTexCoord2f(maskSprW, maskSprH);
			glVertex2f(w, h);
			glTexCoord2f(maskSprX, maskSprH);
			glVertex2f(x, h);
		}

		glEnd();

		if (linearMask) {
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
					GL_NEAREST);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
					GL_NEAREST);
		}
	}

	private void renderSprite() {

		float x = getPosX() + getModPosX() - getBindX();
		float y = getPosY() + getModPosY() - getBindY();
		float w = getPosX() + getModPosX() + getCurrentWidth() - getBindX();
		float h = getPosY() + getModPosY() + getCurrentHeight() - getBindY();

		float sprX = getSprite().getX();
		float sprY = getSprite().getY();
		float sprW = sprX + getSprite().getW();
		float sprH = sprY + getSprite().getH();

		if (isLinealScale()) {
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
					GL_LINEAR);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
					GL_LINEAR);
		}

		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, getSprite().getT());

		glBegin(GL_QUADS);

		if (isFlip()) {
			glTexCoord2f(sprW, sprY);
			glVertex2f(x, y);
			glTexCoord2f(sprX, sprY);
			glVertex2f(w, y);
			glTexCoord2f(sprX, sprH);
			glVertex2f(w, h);
			glTexCoord2f(sprW, sprH);
			glVertex2f(x, h);

		} else {
			glTexCoord2f(sprX, sprY);
			glVertex2f(x, y);
			glTexCoord2f(sprW, sprY);
			glVertex2f(w, y);
			glTexCoord2f(sprW, sprH);
			glVertex2f(w, h);
			glTexCoord2f(sprX, sprH);
			glVertex2f(x, h);
		}

		glEnd();

		if (isLinealScale()) {
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
					GL_NEAREST);
			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
					GL_NEAREST);
		}

	}


But to be honest with you … I dont have any idea what i am doing :expressionless:
I dont know if i have to render the texture before the mask
I dont know if what Im trying to do is even possible
I dont know witch glBlendFunc add before the mask rendering and witch one before the normal texture
I dont know if i HAVE to use GL_TEXTURE_2D in the glBindTexture method

In other words Im totally lost :expressionless:

I really appreciate your attention and your suggestions :slight_smile:

  • Sorry for the ridiculous amount of comments … I try a lot of blend functions … concepts and guides … *

Learn to walk before you run… in other words, learn OpenGL basics before you start using it for 2D effects like masking.

Texturing Tutorial

I would recommend using GL_TEXTURE_2D instead of GL_TEXTURE_RECTANGLE_ARB. The latter is a bit outdated.

Also you don’t need to bind texture zero at the end of your rendering. Nor do you need to set the filtering every frame – you just set it once for the texture you want, and it will stay set until you change it.

[quote]with glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA) as the default blend.
[/quote]
GL_ALPHA is not a valid parameter to blendFunc. I think you mean GL_SRC_ALPHA.

The screenshots you have are from my blending tutorial, which uses shaders, and is probably the most efficient means of accomplishing that kind of a blend. It includes full source code for LWJGL or for LibGDX… So I’m not sure why you are trying to do this with blend functions instead.

There are some other masking techniques, including a working example with blend func, explained in the following (work in progress) article:

I’ve included LibGDX code. If you haven’t already considered it, I would suggest using LibGDX as your OpenGL wrapper rather than relying on deprecated GL code like glPushMatrix, glVertex, glRotate, etc.