2 hours ago, turanszkij said:
Hi, for this effect you should first calculate the view space particle velocity from the world space velocity:
float4x4 g_xCamera_View; // camera view matrix
// ...
float3 velocity = mul(particle.velocity, (float3x3)g_xCamera_View);
Then after the quad is already expanded/created (and rotated), for each vertex of the quad do this (before the quad vertices are projected):
float xParticleMotionBlurAmount; // particle system setting: how much motion blur affects the particles...
// ...
quadPos += dot(quadPos, velocity) * velocity * xParticleMotionBlurAmount;
This means that vertices which are aligned with the view space motion vector get extruded by the motion vector. This solution doesn't rotate according to the velocity, but I found that only extruding already gives the results what I needed. And this way I can still add rotational animation from the particle system settings.
Also, you most likely can avoid using the geometry shader and you should consider doing so. The quad expansion can be done entirely in the vertex shader. If you are interested, you can take a look at my particle quad vertex shader: https://github.com/turanszkij/WickedEngine/blob/master/WickedEngine/emittedparticleVS.hlsl
Good luck!
Thank you for the answer, this solution gave me kind of the stretching that I was looking for, but as you said it doesn't account for the rotation, which is one of the major things that I need for this effect.
2 hours ago, Hodgman said:
To define an orientation for each quad, you need three perpendicular unit vectors, for the local x, y, z axes.
You've set a few constraints: (1) one axis should be facing the camera, (2) one axis should be facing the direction of motion.
That leaves one free axis (sideways), which you can compute with the cross product of the above two vectors.
e.g. z = to_camera; y = normalize(velocity); x = cross(z, y);
At this point though, x is perpendicular to both y and z, but there's no guarantee that y and z are perpendicular to each other, which would result in skewing. Depending on which is more important (facing the camera, or stretching in the direction of motion), you can recompute the less important one (e.g. z = cross(x, y)).
x, y, z are then a 3x3 rotation matrix defining the orientation of your quad. You can stretch it in the y axis according to velocity if you want fast particles to be longer than slow ones.
I am a bit confused of the spaces that you would do these operations. Are you suggesting this in view-space?
When I tried this, it feels like I'm in the wrong space, and I've tried to convert both my velocity, positioning and to_camera vectors to both world & view space, but something is still wrong.
This is how I do the operations at the moment.
float3 z = normalize(mul(viewOnlyRot, cameraPosition - input[0].myWPosition.xyz));
float3 y = normalize(input[0].myVelocity);
float3 x = normalize(cross(z,y));
float3x3 rotMat =
{
x.x, x.y, x.z,
y.x, y.y, y.z,
z.x, z.y, z.z
};
vertex.myPosition.xyz = input[0].myPosition.xyz;
vertex.myPosition.xyz = mul(rotMat, vertex.myPosition.xyz);