Firemonkey does strange, bizarre things with Alpha

  

Working with Delphi / Firemonkey XE8. Had some decent luck with it recently, although you have to hack the heck out of it to get it to do what you want. My current project is to evaluate it’s Low-Level 3D capabilities to see if I can use them as a starting point for a Game Project. I also know Unity3D quite well, and am considering using Unity3D instead, but I figure that Delphi / Firemonkey might give me some added flexibility in my game design because it is so minimal.

So I decided to dig into an Embarcadero-supplied sample… specifically the LowLevel3D sample. This is the cross-platform sample that shows you how to do nothing other than draw a rotating square on the screen with some custom shaders of your choice and have it look the same on all platforms (although it actually doesn’t work AT ALL the same on all platforms… but we won’t get into that).

Embc does not supply the original uncompiled shaders for the project (which I might add is really lame), and requires you to supply your own compatible shaders (some compiled, some not) for the various platforms you’re targeting (also lame)…so my first job has been to create a shader that would work with their existing sample that does something OTHER than what the sample already does. Specifically, if I’m creating a 2D game, I wanted to make sure that I could do sprites with alpha transparency, basic stuff…. if I can get this working, I’ll probably never have to write another shader for the whole game.

After pulling my hair out for many hours, I came up with this little shader that works with the same parameters as the demo.

Texture2D mytex0: register(t0);
Texture2D mytex1: register(t1);
float4 cccc : register(v0) ;

struct PixelShaderInput
{
float4 Pos: COLOR;
float2 Tex: TEXCOORDS;

};

SamplerState g_samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};

RasterizerState MyCull {
FrontCounterClockwise = FALSE;
};

float4 main(PixelShaderInput pIn): SV_TARGET
{
float4 cc,c;
float4 ci = mytex1.Sample(g_samLinear, pIn.Tex.xy);
c = ci;
c.a = 0;//<—– DOES NOT actually SET ALPHA TO ZERO … THIS IS A PROBLEM
cc = c;
return cc;
}

Never-mind that it doesn’t actually do much with the parameters, but check out the line where I set the output’s ALPHA to 0. Well…. I found that this actually HAS NO EFFECT!

But it gets spookier than this. I found that turning on CULLING in the Delphi App FIXED this issue. So I figure… no big deal then, I’ll just manually draw both sides of the sprite… right? Nope! When I manually drew a double sided sprite.. the problem came back!

Check this image: shader is ignoring alpha=0 when double-sided

In the above picture, clearly alpha is SOMEWHAT obeyed because the clouds are not surrounded by a black box, however, the cloud itself is super saturated (I find that if I multiply rgb*a, then the colors come out approximately right, but I’m not going to do that in real-life for obvious reasons.

I’m new to the concept of writing custom shaders. Any insight is appreciated.

Comments are closed.