I'm taking my first venture in to writing a shader and what I really need to do is create a billboarding effect. A thorough Google search turns up a number of threads on the topic and they always end with
A) Figured it out. Thread closed.
B) Anyone?
C) "long language/system-specific answer without explanation"
Most commonly, people are directed to Riemers which is fine, except his code isn't compatible with XNA 4.0 (what I'm using) and he doesn't explain the shader itself.
Can anyone explain/direct-me-to a language/system agnostic answer of how quad billboarding works?
EDIT: For others so they don't need to dig through the comments: NtscCobalt pointed out that I was attempting to use an orthographic camera when applying the shader. This essentially voided some of the effects of the shader. After changing to a perspective-based cam, the shader worked as it should have.
Answer
Here is a simple solution that doesn't require any changes in code to change an object from 3d to billboard. It is probably a hack and might not work in every situation.
Set the constant 'WorldView' to the WorldMatrix*ViewMatrix and 'Projection' to your Projection Matrix. No additional code required. This shader doesn't include lighting but you could use the same lighting code from per-pixel lighting pretty easily. This correctly works with textures by the way.
float4x4 WorldView : WorldView;
float4x4 Projection : Projection;
texture texture0 : DIFFUSE <
string ResourceName = "default_color.dds";
string UIName = "Diffuse Texture";
string ResourceType = "2D";
>;
sampler2D colorMap = sampler_state
{
Texture = ;
MagFilter = Linear;
MinFilter = Anisotropic;
MipFilter = Linear;
MaxAnisotropy = 16;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float2 TextureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TextureCoordinate : TEXCOORD0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput IN)
{
VertexShaderOutput OUT;
OUT.Position = mul(IN.Position + float4(WorldView[3].xyz, 0), Projection);
OUT.TextureCoordinate = IN.TextureCoordinate;
return OUT;
}
float4 PixelShaderFunction(VertexShaderOutput IN) : COLOR0
{
return tex2D(colorMap, IN.TextureCoordinate);
}
technique BasicShader
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
Edit: To clarify the way this works is by multiplying the vertices position by the worldview matrix position but ignoring either's rotation and scale. That result is then multiplied by the projection matrix. In short: any object that faces the camera in model space that then uses this shader will face the camera.
No comments:
Post a Comment