Dear All,
In return for answering my occasional dumb questions here is a shader that gives full control of object transparency using an alphamap. This gets around the annoying aspect of ghosting where black is always completely transparent, and the annoying aspect of transparency with png images with an alpha channel that have sharp edges. The object to which the shader is applied does not have ghost on or transparency set.
Shader code
//This shader generates variable transparency similar to ghosting but where alpha (the transparency)
//is given by the R bit in an alpha map. This allows textures to be blended with background independent of colour
// and generates smooth blended edges unlike alpha masks.
//The model texture is loaded in stage 0, the alpha map in stage 1.
//Written by Mr Grumpy, 2010
float4x4 wvp : WorldViewProjection;
float4x4 mw : World;
float4 AmbientColor = {0.2f, 0.2f, 0.2f, 1.0f};
//float AmbientIntensity = 0.1;
float4x4 wit : WorldInverseTranspose;
float3 DiffuseLightDirection = {0.707107f, 0.707107f, 0.0f}; // {0.707107f, 0.0f, 0.707107f, 1.0f};
float4 DiffuseColor = float4(1, 1, 1, 1);
float4 fogColor = {0.75f, 0.75f, 0.75f, 1.0};
float3 eyePos : CameraPosition;
float DiffuseIntensity = 1.0;
float FogEnd = 1000.0;
float FogStart = 256.0;
texture ModelTexture < string ResourceName = ""; >;
sampler2D textureSampler = sampler_state {
Texture = <ModelTexture>; //Get the texture from the 0 stage of the model
MagFilter = Linear;
MinFilter = Linear;
AddressU = Wrap; //Use repeating boundary for UV coordinates
AddressV = Wrap;
};
texture AlphaMap < string ResourceName = ""; >;
sampler2D textureSamplerA = sampler_state {
Texture = <AlphaMap>; //Get the texture from the 1 stage of the model
MagFilter = Linear;
MinFilter = Linear;
AddressU = Wrap; //Use repeating boundary for UV coordinates
AddressV = Wrap;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float4 Normal : NORMAL0;
float2 TextureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float3 View : TEXCOORD0;
float2 TextureCoordinate : TEXCOORD1;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
//Fog
float4 tempPos = mul(input.Position, mw);
output.View = (tempPos.xyz - eyePos);
//simply pass the input texture to the output
output.TextureCoordinate = input.TextureCoordinate;
//transform to view position
output.Position = mul(input.Position, wvp);
//transform normals to object centred
float4 normal = mul(input.Normal, wit);
//get angle between light direction and normal
float lightIntensity = dot(normal, DiffuseLightDirection);
//calculate diffuse colour from light intensity
output.Color = saturate(DiffuseColor * DiffuseIntensity * lightIntensity);
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
//Get the texture colours for each pixel
float4 textureColor = tex2D(textureSampler, input.TextureCoordinate);
float4 alphamap = tex2D(textureSamplerA, input.TextureCoordinate);
//Fog
float fog = saturate((FogStart - length(input.View))/(FogStart - FogEnd));
//combine diffuse and ambient light
float4 color = fog*fogColor + (1.0-fog)*saturate(textureColor*(input.Color + AmbientColor));
color.a = alphamap.x;
return color;
}
technique Diffuse
{
pass Pass1
{
AlphaBlendEnable = TRUE;
//CullMode = CW;
DestBlend = INVSRCALPHA;
SrcBlend = SRCALPHA;
VertexShader = compile vs_1_1 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
DBP Code
Rem Texture object stages
texture object obj, 0, itexture
texture object obj, 1, ialphamap
Rem Set-up the shader
convert object fvf obj, 530 ` XYZ+NORMAL+TEX2
if effect exist(effectno)=0 then load effect "shaders\alphatransparency.fx", effectno, 0
set object effect obj, effectno
For those who are interested in the details this shader also facilitates coloured distance fog and generates diffuse lighting depending on a light vector. The global light is specified in the shader as a default but can be overridden by passing as effect variables. The transparency is very simply controlled by setting the alpha of the color output from the pixel shader to the R bit of the alphamap texture, then setting alpha blending in the technique.
The attached screen shot shows one application, a ground texture around an RTS building generated on an object just above the terrain. I've got around 1000 of these objects on which the shader is running with no noticeable slow down. Notice that DBP's stencil shadows cast nicely on the object.
If you wanted to have transparency that changes with time (e.g. an object that fades away) you could always pass a float variable for the current total transparency and multiply it to the alphamap.x in the pixel shader.
Best,
Mr Grumpy
GrumpyOne - the natural state of the programmer