Problem with transparent textures covering other textures

Hello, I’m making a Quake 3 map with custom textures and models.

On my map there are anime figures, which are made out of a model for the stand, and a brush with a texture on it for the figure itself (using deformvertexes autosprite2 to turn it into a billboard, all other faces have caulk applied to them).

Both of these objects have transparent textures, and the issue I’m having is that the figure texture is covering up the figure’s stand for some reason:

Taking out depthwrite kinda fixes it, but introduces a bunch of other issues with other transparent textures:

Here’s the shader file code for these:


//Figures

textures/reb/brush_props/lily
{
	cull none
	deformvertexes autosprite2
	surfaceparm nonsolid
	surfaceparm trans

	{
		map textures/reb/brush_props/lily.tga
		blendfunc blend
		depthwrite
	}
}

textures/reb/brush_props/miku
{
	cull none
	deformvertexes autosprite2
	surfaceparm nonsolid
	surfaceparm trans

	{
		map textures/reb/brush_props/miku.tga
		blendfunc blend
		depthwrite
	}
}

textures/reb/brush_props/sakura
{
	cull none
	deformvertexes autosprite2
	surfaceparm nonsolid
	surfaceparm trans

	{
		map textures/reb/brush_props/sakura.tga
		blendfunc blend
		depthwrite
	}
}

// Figure stands

models/mapobjects/reb/figbase_lily
{
	surfaceparm trans
	cull none
	{
		map textures/reb/mapobjects/figbase_lily.tga
		rgbgen exactvertex
		blendfunc blend
		depthWrite
	}
}

models/mapobjects/reb/figbase_sakura
{
	surfaceparm trans
	cull none
	// copied from glass01
	{
		map textures/effects/tinfx.tga
		tcgen environment
		blendfunc GL_ONE GL_ONE
		rgbgen identity
	}
	{
		map $lightmap
		rgbgen identity
		blendfunc filter
		depthWrite
	}

}

models/mapobjects/reb/figbase_miku
{
	surfaceparm trans
	cull none
	{
		map textures/reb/mapobjects/figbase_miku.tga
		rgbgen exactVertex
		blendfunc blend
		depthWrite
	}
}

What am I doing wrong?

1 Like

You could try “sort seethrough” on the base shaders and “sort banner” on figure shaders so figures are always drawn after the bases.

You could try “alphafunc GE80” instead of blendfunc+depthwrite on figure shaders so it only writes depth for visible parts of the figure image. So transparent shaders behind it are (only) visible in the transparent part of the figure image.

base
{
	sort seethrough

	...
}

figure
{
	sort banner
	...

	{
		map ...
		alphafunc GE80
		...
	}
}

Quake 3 doesn’t have distance sorting or order-independent transparency so overlapping blended alpha that can be viewed in different orders is usually best avoided.

Things are drawn in order based on a sort value for opaque, decal (against wall), seethrough (grate to view opaque lava or something), banner (close to wall), and various blend modes. There is no guarantee what order things draw with the same sort value but it’s consistent.

Transparent effects in Quake 3 usually use “blendfunc add” (aka blendfunc GL_ONE GL_ONE) without depthwrite. The color is added to the framebuffer and it doesn’t matter what order it’s draw or it they overlap; the final color is the same.

blendfunc blend + depthwrite will prevent seeing transparent shaders behind it (that have a higher sort value so it’s drawn later) but the problem is depthwrite effects the whole image, including the transparent part. So shaders that are opaque with some transparency (such as a grate or fence) usually use alpha test (“alphafunc GE80”) instead of blendfunc so color/depth is only written if the image’s alpha is greater-or-equal to hex 0x80 (decimal 128). This makes it so transparent parts of the image do not write depth and thus do not block other (transparent) shaders with a higher sort value that are drawn later. (depthwrite is the default behavior unless blendfunc is used.)

Some other issues can be fixed by using explicit “sort [order]” which forces things to be drawn in front / behind from all view positions.

2 Likes

Wow, thank you for such a detailed answer! The sort instructions kind of fixed it, I’ll try to experiment with alphafunc GE80 later, it didn’t seem to be working but I probably have to edit the figure textures.
Thanks again for your very informative reply!

Okay, I got it to work with alphafunc GE128. Looks it uses the decimal value instead of hex so it should work like you mentioned? The figures do look a bit jagged up close, but I assume this is because of the binary nature of alphafunc and there’s not much I can do about it.

2 Likes

Ah yeah, you’re correct it’s alphafunc GE128. The code calls it GLS_ATEST_GE_80 and I mixed them up.

Yeah, unfortunately the alpha test makes the edges have blurry artifacts. I think the rendering concept “alpha to coverage” improves it but Quake 3 doesn’t support it.

1 Like