How do you add rotation to particles?
Today I was working on a particle system and I can't figure out how to give the particle billboards a rotation (so to have them spinning clockwise or counter-clockwise while facing the player). I assume the core of the problem is my complete lack of understanding of trigonometry.
So, first of all, here is my geometry shader that will produce quads that rotate around their center:
[maxvertexcount(4)]
void GeometryShaderProc( point VertexShaderInput particle[1], inout TriangleStream<PixelShaderInput> triStream ) {
PixelShaderInput vertex = (PixelShaderInput)0;
vertex.Color = particle[ 0 ].Color;
vertex.Texture = particle[ 0 ].Texture;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
float QuadSizeX = particle[ 0 ].Size.x / ViewportDimensions.x * 0.5;
float QuadSizeY = particle[ 0 ].Size.y / ViewportDimensions.y * 0.5;
float a = sin( particle[ 0 ].Position.w ) * QuadSizeX;
float b = cos( particle[ 0 ].Position.w ) * QuadSizeY;
float c = cos( particle[ 0 ].Position.w ) * QuadSizeX;
float d = sin( particle[ 0 ].Position.w ) * QuadSizeY;
// Left Top
vertex.Position.x = particle[ 0 ].Position.x - c;
vertex.Position.y = particle[ 0 ].Position.y - d;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 0, 0 );
triStream.Append( vertex );
// Left Bottom
vertex.Position.x = particle[ 0 ].Position.x - a;
vertex.Position.y = particle[ 0 ].Position.y + b;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 0, 1 );
triStream.Append( vertex );
// Right Top
vertex.Position.x = particle[ 0 ].Position.x + a;
vertex.Position.y = particle[ 0 ].Position.y - b;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 1, 0 );
triStream.Append( vertex );
// Right Bottom
vertex.Position.x = particle[ 0 ].Position.x + c;
vertex.Position.y = particle[ 0 ].Position.y + d;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 1, 1 );
triStream.Append( vertex );
}
In case it isn't obvious, I'm using the w component of the input vector as the input value for the rotation.
So far so great, until I move the camera and the quads aren't facing the camera any more. So, obviously I need to rotate them.
An approach to solving that was quickly found online, so I adjusted the shader:
[maxvertexcount(4)]
void GeometryShaderProc( point VertexShaderInput particle[1], inout TriangleStream<PixelShaderInput> triStream ) {
PixelShaderInput vertex = (PixelShaderInput)0;
vertex.Color = particle[ 0 ].Color;
vertex.Texture = particle[ 0 ].Texture;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
float3 planeNormal = particle[ 0 ].Position.xyz - CameraPosition;
planeNormal.y = 0.0f;
Today I was working on a particle system and I can't figure out how to give the particle billboards a rotation (so to have them spinning clockwise or counter-clockwise while facing the player). I assume the core of the problem is my complete lack of understanding of trigonometry.
So, first of all, here is my geometry shader that will produce quads that rotate around their center:
[maxvertexcount(4)]
void GeometryShaderProc( point VertexShaderInput particle[1], inout TriangleStream<PixelShaderInput> triStream ) {
PixelShaderInput vertex = (PixelShaderInput)0;
vertex.Color = particle[ 0 ].Color;
vertex.Texture = particle[ 0 ].Texture;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
float QuadSizeX = particle[ 0 ].Size.x / ViewportDimensions.x * 0.5;
float QuadSizeY = particle[ 0 ].Size.y / ViewportDimensions.y * 0.5;
float a = sin( particle[ 0 ].Position.w ) * QuadSizeX;
float b = cos( particle[ 0 ].Position.w ) * QuadSizeY;
float c = cos( particle[ 0 ].Position.w ) * QuadSizeX;
float d = sin( particle[ 0 ].Position.w ) * QuadSizeY;
// Left Top
vertex.Position.x = particle[ 0 ].Position.x - c;
vertex.Position.y = particle[ 0 ].Position.y - d;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 0, 0 );
triStream.Append( vertex );
// Left Bottom
vertex.Position.x = particle[ 0 ].Position.x - a;
vertex.Position.y = particle[ 0 ].Position.y + b;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 0, 1 );
triStream.Append( vertex );
// Right Top
vertex.Position.x = particle[ 0 ].Position.x + a;
vertex.Position.y = particle[ 0 ].Position.y - b;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 1, 0 );
triStream.Append( vertex );
// Right Bottom
vertex.Position.x = particle[ 0 ].Position.x + c;
vertex.Position.y = particle[ 0 ].Position.y + d;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
vertex.Position = mul( float4( vertex.Position.xyz, 1.0 ), ViewProjection );
vertex.TextureCoordinate = float2( 1, 1 );
triStream.Append( vertex );
}
In case it isn't obvious, I'm using the w component of the input vector as the input value for the rotation.
So far so great, until I move the camera and the quads aren't facing the camera any more. So, obviously I need to rotate them.
An approach to solving that was quickly found online, so I adjusted the shader:
[maxvertexcount(4)]
void GeometryShaderProc( point VertexShaderInput particle[1], inout TriangleStream<PixelShaderInput> triStream ) {
PixelShaderInput vertex = (PixelShaderInput)0;
vertex.Color = particle[ 0 ].Color;
vertex.Texture = particle[ 0 ].Texture;
vertex.Position.z = particle[ 0 ].Position.z;
vertex.Position.w = 1;
float3 planeNormal = particle[ 0 ].Position.xyz - CameraPosition;
planeNormal.y = 0.0f;
No comments:
Post a Comment