Textures with transparency

Started by pea2nuts, January 09, 2015, 00:26:56

Previous topic - Next topic

pea2nuts

I am having a problem where the transparent part of textures is rendered as black without blending, but with blending you cannot see the face under the texture. Another issue is you cannot see other textures through the transparent part of textures.

Here is an example of the face under textures

Without blending:


with blending:


Here is an example of textures unable to be seen through the transparent part of other textures

without blending:


with blending:

Cornix

Perhaps something is wrong with the way you set up the blend functions. It would be useful if you show the code for that and perhaps other parts of the code as well like how you render everything.

pea2nuts

Quote from: Cornix on January 09, 2015, 08:42:14
Perhaps something is wrong with the way you set up the blend functions. It would be useful if you show the code for that and perhaps other parts of the code as well like how you render everything.

for blending, i called this at startup:
glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);




code to render(in a loop of the models triangles):
boolean textured = texture != null;
			glBegin(GL_TRIANGLES);
			glColor4ub((byte) (color >>> 16), (byte) (color >>> 8),
					(byte) color, (byte) (faceAlpha == null ? 0xff : ~faceAlpha[triangle]));
            if (textured)
            	glTexCoord2f(u0, v0);
			glVertex3f(verticesX[pointA] / scale,
					verticesY[pointA] / scale,
					verticesZ[pointA] / scale);
            if (textured)
            	glTexCoord2f(u1, v1);
			glVertex3f(verticesX[pointB] / scale,
					verticesY[pointB] / scale,
					verticesZ[pointB] / scale);
            if (textured)
            	glTexCoord2f(u2, v2);
			glVertex3f(verticesX[pointC] / scale,
					verticesY[pointC] / scale,
					verticesZ[pointC] / scale);

Kai

You need to enable alpha testing or disable depth-write for translucent primites.
The effect that you see on your last image is that depth is written for even the completely translucent pixels.
The result is that anything rendered "behind" it is depth-tested and rejected and not even blended (which happens afterwards).

Have a look at: http://stackoverflow.com/questions/9267414/opengl-transparency-and-depth-test-problems
Another post that explains all of this extremely well, though using a background color that gives me eye-cancer, is:
http://www.sjbaker.org/steve/omniv/alpha_sorting.html

pea2nuts

Quote from: Kai on January 09, 2015, 10:06:42
You need to enable alpha testing or disable depth-write for translucent primites.
The effect that you see on your last image is that depth is written for even the completely translucent pixels.
The result is that anything rendered "behind" it is depth-tested and rejected and not even blended (which happens afterwards).

Have a look at: http://stackoverflow.com/questions/9267414/opengl-transparency-and-depth-test-problems
Another post that explains all of this extremely well, though using a background color that gives me eye-cancer, is:
http://www.sjbaker.org/steve/omniv/alpha_sorting.html
How would i do this? enabling alpha testing did nothing and i tried
if(alpha == 0)
				glDepthMask(false);
			else
				glDepthMask(true);

but i got an error "Invalid operation (1282)" on glEnd()

and this would not even work anyway because those faces are not completely transparent when there are no textures on them so how would i check that?

Kai

It will work with alpha testing, believe me. :)
Please do read the articles, especially the last one. It explains everything you need.

pea2nuts

Quote from: Kai on January 09, 2015, 11:17:36
It will work with alpha testing, believe me. :)
Please do read the articles, especially the last one. It explains everything you need.

I have read that one but im not sure how to sort the triangles..

i have enabled alpha testing with
glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0.0f);


and here is the chains with and without blending

with(for some reason you cannot see through the ring of the chain?):


without:


and the dragon leg with and without blending

with:


without:


i tried that before i came here or tried blending and it doesnt help because it fades into total transparency so the part that is not completely transparent still shows black


Kai

Well then either the "inner" of your chain's links have no alpha (i.e. alpha channel is 1.0) or they have alpha that is not exactly 0.0.
Look at the documentation of glAphaFunc.
If you want alpha values a little bit greater than 0.0 also to not pass the alpha test, you would be using a reference value that is greater than 0.0.

pea2nuts

Quote from: Kai on January 09, 2015, 11:51:39
Well then either the "inner" of your chain's links have no alpha (i.e. alpha channel is 1.0) or they have alpha that is not exactly 0.0.
Look at the documentation of glAphaFunc.
If you want alpha values a little bit greater than 0.0 also to not pass the alpha test, you would be using a reference value that is greater than 0.0.

ok but that doesnt solve the problem about the alpha values that gradually get more transparent in the textures.. and what about when i do alpha testing and i cant see the face underneath still(dragon leg)?  how would i do depth peeling with a glsl shader as it says in the stackoverflow answer? i dont really know anything about shaders but i have added the ability to load them.

Kai

I really do not know how that drawgon leg should look like and why it is all white with alpha.
It occurs to me that the "solid" leg of a dragon should not have alpha anywhere, unless of course that animal has some serious wounds there. :)

As the second article says rightly, correctly doing alpha blending with a Z-buffer rendering algorithms is not possible.
The best thing you can do is to first render your completely solid objects without alpha testing and blending, and then render only your transparent (or partly transparent, or gradually transparent) objects with alpha-testing and optimally sort and render them in back to front order.

I would not have a look at depth peeling, it is complicated and involves quite some very sophisticated shader and knowledge about multisampled textures and stencil-routing and whatnot!

EDIT: The reason why you cannot see through the ring at certain spots is because of depth-writing. Whenever you render a transparent object which is closer to the viewer first and then another object that is behind it but should still be seen-through that first transparent object, the depth buffer gets in the way, as it prevents the fragments for the second object to be generated and blended.
Really the only way to get around that is to sort your primitives from back to front OR use alpha-testing and ensure that its reference value is greater than the alpha channel's value of your textures. But anyway, half-transparent objects will only work if you sort your primitives from back to front.

Vapalus

Own experience:
Translucent colors are hard, very hard to implement due to the fact that they will have to be pre-z-sorted by the cpu. That is power intensive. Every time your camera rotates or moves, you have to re-sort every single polygon. Maybe you can optimize that a little bit to sort every tenth ot twentieth polygon (edit: depending on your model, of course). But: Have I ever told you what the definition of insanity is?

Fact is, if you want alpha to be applied "correctly" you may be interested in using a fragment shader:

if(color_calcd.a < 1)
    	discard;

What this does is it simply stops rendering if there is an alpha value, in other words, it "does nothing" which means it also does not overwrite whats already there, and it does not get overridden (because - you guessed right - its not there).

if you are interested in using shaders, that is. They can be annoying, complicated, and they will kill you in your sleep. Just like cats.
After creating the correct othogonal matrices for the GUI and optimizing the RAM usage with a streaming engine, I usually fail to call the initialization function; As soon as that happens, you know I will search that stupid error for ten hours.

Kai

Quote
    if(color_calcd.a < 1)
      discard;

That's exactly what alpha-testing is doing. So you would not need a fragment shader for that.

Vapalus

My apologies for that, but after looking at his chains I thought it would do something different after all.
Maybe the function should be glAlphaFunc(GL_GREATER, 0.9f);?
I'm just asking because I am courious; being able to set values OUTSIDE of shaders can make a huge speed difference I think.
After creating the correct othogonal matrices for the GUI and optimizing the RAM usage with a streaming engine, I usually fail to call the initialization function; As soon as that happens, you know I will search that stupid error for ten hours.

Kai

No need to apologize, really, ever. :)

Just for your info:
if(color.a < 1.0)
  discard;


is equivalent to:
glAlphaFunc(GL_GEQUAL, 1.0f);


Because alpha func says when some fragment passes the test instead of being discarded.

Cheers,
Kai

pea2nuts

the problem is the texture is transparent and blending it makes the face transparent too.

Here is one texture (might be hard to see)

Another one thats easier to see



by using gl env mode GL_DECAL, i can see the actual face color but the texture of course is white instead of blended with the face...

here is what i mean:


what i want to achieve is a combination of both of these.
texture color blended but then placed on the original face like a decal

still really need to fix this