Transparent but no alpha?

Hi,

I’m working on a game with pixelart. I would need a shader that just doesn’t display a certain color. A full aplha channel would be overkill, and would result in files that are way bigger than necessary. Sort of like gif files.

Is such a shader available, or would it be possible to make one? If anyone could help it would really be appreciated. Thanks!

You would likely work with a shader that works like the transparency - cutout

Like dreamora said, if you want to use one quad for each sprite, you’ll need an alpha channel (unless your background is a solid color). But it’s to your advantage to use alpha blending, rather than alpha testing, on the iPhone.

Depending on how complex your art is, what you may want to consider, instead of using texture maps, is creating the “pixels” with quads, and coloring them with vertex colors. If you only need 8 or fewer frames per piece of art, you can just use object-level rotation to get animations. (You won’t see a side of a cube if it is pointed at least 90 degrees away from the camera.)

Okay, I just noticed that RGBA 16 bit and RGB 16 bit take the same amount of bytes. That makes sense off course since it’s as much bits. Since my palette is limited, I can just use RGBA 16 bit, with a cutout shader, like dreamora suggested. (if I needed more bits, there would have been a difference, because the only other options are RGB24 and RGBA32, which makes quite some difference).

Why is that?

Not sure what you’re talking about. My main sprite would be 2508 quads that way, instead of 1.

Unlike most GPUs, the iPhone’s hardware is poor for alpha testing. You’ll find this information in the Unity documentation, Apple’s documentation, threads on these boards, and elsewhere.

That sounds like a number I wouldn’t want to use that approach for, then.

Thanks for the info, but I tested with the alpha blended shader instead of cutout, and my framerate went down considerably. So which shader would you recommend?

Sounds like a complex approach anyway :slight_smile: My sprite is a 38x66 pixel character, which isn’t that big.

Thanks for the suggestions!

This is what I use, to get the result seen here:

I’d actually be interested to hear if a cutout (alpha test) shader is faster than this. I simply never tried one, because every source told me not to.

Shader "2D Art for iPhone" {
	
Properties {_MainTex ("Texture  (A = Transparency)", 2D) = ""}

SubShader
{	
	Tags {Queue = Transparent}
	Ztest Always
	Zwrite Off
	Blend SrcAlpha OneMinusSrcAlpha
	Pass {SetTexture[_MainTex]}
}

}

Okay, thanks, I’ll give it a try and let you know. I won’t be home today, but I’ll try to have a look tomorrow.

Hey, I finally got round to trying your shader. I couldn’t test it in my game before because the framerate was almost 60 all the time, but recently it had dropped to about 40 in one section with a lot of tiles - and your shader definately helped., it’s now about 50 in that section. So thanks!

Darn, I now noticed the z-sorting is kaput, things overlap that shouldn’t overlap… Do you know how to change it so this still works?

That shader only works if every material in your project is using the Transparent rendering queue. Sorry, forgot to mention that.

I figured you were making a “2D” game when you said “pixel art”. Is that true? Properly layering transparency in 3D space isn’t a problem that has been solved yet in computer graphics; most games that I play just use alpha testing, not bothering with antialiasing of edges, but those are all on consoles.

Also, as you can find on the forums, Unity sorts the rendering of objects based on the center of their axis-alighend bounding box, not by pixel or even triangle, so even if your meshes are just quads, problems with depth sorting can arise if you rotate them, requiring weird translation and scaling solutions that don’t work from all camera angles.

Cutting out the line that removes depth sorting will hopefully be all you need. If not, we’ll probably need screenshots or a video to offer something better.

Shader "2D Art for iPhone" {
	
Properties {_MainTex ("Texture  (A = Transparency)", 2D) = ""}

SubShader
{	
	Tags {Queue = Transparent}
	Zwrite Off
	Blend SrcAlpha OneMinusSrcAlpha
	Pass {SetTexture[_MainTex]}
}

}

That didn’t do the trick. Thanks for trying though :slight_smile:

Here is a web build of my project which I did yesterday : http://mudloop.com/locksandloaded
It is with one of the cutout shaders, so the z ordering works properly here. See that you walk behind some mushrooms? With your shader, that doesn’t work anymore.

Note that I put multiple “layers” into one mesh. So the mushrooms and the grass tiles are all in one mesh (in blocks of 15x15 tiles). But it still works with the cutout shaders…

Thanks!

alpha is sorted basing on the 0,0,0 position of the mesh, its impossible to depth sort alpha pixels.
Due to that, ensure you don’t overdo the size of an alpha using object and that it especially does not span too far into the depth or the alpha will fail.

Thats a common rule to keep in mind with alpha blending.
On the iphone you should restrict cutout to as little as you really need as the iphone gpu is opted for alpha blend, not for cutout.

In your case though it should be simple as all is coplanar. You just have to ensure that the different “layers” of coplanar objects are far enough away depth distance wise and they should work all fine.

Maybe, given that wouldn’t work, you could share a bit more about the setup of the scene so potential problems can be found? (including cam ranges though I assume you cut them down to what you really need)

This doesn’t work, but I guess it’s because I group my tiles into big meshes. Guess I’ll have to seperate my top layer from the rest, and hope that doesn’t impact speed too much.

Thanks!

If you do that, you need to take Zwrite Off out.

Shader "2D Art for iPhone" { 
    
Properties {_MainTex ("Texture  (A = Transparency)", 2D) = ""} 

SubShader 
{    
   Tags {Queue = Transparent} 
   Blend SrcAlpha OneMinusSrcAlpha 
   Pass {SetTexture[_MainTex]} 
} 

}

As long as your mushrooms never overlap, you can make this work. Like I said, it’s not enough to just put the mesh between two other meshes. Dreamora suggested that it’s the pivot point of the mesh that counts. But no, as I said, it’s the center of the AABB. It’s possible that your character will be rendered first, leading to a rectangle of nonsense around her. To avoid that, her AABB’s center must be in front of that of the mushrooms.

However, if you need overlap of the mushrooms, there’s no way that this will work, with alpha blending. That’s when you’d need to use a different mesh.

I already tried without the Zwrite Off, but then when there is something in front of her, the stuff that should be behind her also gets drawn in front of her.

So I guess the only way to solve this would still be to create a seperate mesh for the top stuff…

Thanks!

That doesn’t make any sense. I’m assuming you’re using an orthographic camera, and positioning things in the Z axis, correct?

If so, what you do, is put the character in a Z level that is between the foreground and background. Her center must be closer to the camera than the center of the axis-aligned bounding box of the combined mesh.

Nevermind. I’m completely insane. :x

Yeah, you need separate meshes.

In addition, there’s no way to batch the foreground and the background, unless the girl is using the same material as the mushrooms. Is she?

If not such, I wouldn’t even waste my time with actually moving things in Z (it just looks weird in the Editor), and instead, I’d change the queue of the shaders.

Shader "Background" { 
    
Properties {_MainTex ("Girl Texture  (A = Transparency)", 2D) = ""} 

SubShader 
{    
   Tags {Queue = Transparent}
   Ztest Always
   Zwrite Off
   Blend SrcAlpha OneMinusSrcAlpha
   Pass {SetTexture[_MainTex]} 
} 

}

Shader "Girl" { 
    
Properties {_MainTex ("Girl Texture  (A = Transparency)", 2D) = ""} 

SubShader 
{    
   Tags {"Queue" = "Transparent+1"}
   Ztest Always
   Zwrite Off
   Blend SrcAlpha OneMinusSrcAlpha
   Pass {SetTexture[_MainTex]} 
} 

}

Shader "Foreground" { 
    
Properties {_MainTex ("Girl Texture  (A = Transparency)", 2D) = ""} 

SubShader 
{    
   Tags {"Queue" = "Transparent+2"}
   Ztest Always
   Zwrite Off
   Blend SrcAlpha OneMinusSrcAlpha
   Pass {SetTexture[_MainTex]} 
} 

}

Yeah, but the mushrooms do share the same texture as the other tiles, so they should use the same material for batching purposes, and so they can not have different places in the rendering queue (AFAIK)…

I am now thinking of just leaving everything behind her. It looks more dynamic when she can walk behind stuff, but you have a lot more visibility when everything is in the back - no enemies hiding behind mushrooms etc. But I haven’t decided yet.

Thanks for your suggestions!