Dx11 particles custom sprite rotation


#1

Hi,

next step…I want to rotate the particle.dx11 sprites individually. Either by a random noise texture or maybe spawn them with individual rotation offsets and have them rotating with the same speed. I had a look at the selfalign shader within point(dx11.3d) that has exactly this functionality, but it rotates the geometry within the vertex shader - the particle.dx11 sprites does it in a geometry shader, and I can’t figure out where to implement it so that it affects the individual quads.

TextureArrayExample.zip (331.8 KB)


#2

you should add rotation as a new attribute to your particle, and manipulate that new attribute with your own custom modifier.
because such is the proper way, how flexibility and customizability is designed into the dx11.Particles framework.

for starters, clone the modifier template, and try to add float3 rotation to the particle definition (instead of float4 color), and in the compute routine you can add some kind of change to it.

 /* The following includes are mandatory! */
#include <packs\dx11.particles\nodes\modules\Core\fxh\Core.fxh>
#include <packs\dx11.particles\nodes\modules\Core\fxh\IndexFunctions_Particles.fxh>
#include <packs\dx11.particles\nodes\modules\Core\fxh\IndexFunctions_DynBuffer.fxh>
/* Have a look at the packs\dx11.particles\nodes\modules\Core\ directory for more helper functions */

/* Like described in the template patch, the attribute(s) for the particlesystem is registered here*/ 
struct Particle {
	#if defined(COMPOSITESTRUCT)
  		COMPOSITESTRUCT
 	#else
		float3 rotation;
	#endif
};

/* The ParticleBuffer and the UseSelectionIndex variable are mandatory*/
RWStructuredBuffer<Particle> ParticleBuffer : PARTICLEBUFFER;

/* Add all pins to edit your attribute here. In this case it is a StructuredBuffer
that provides colors */
StructuredBuffer<float3> RotateBuffer <string uiname="Rotate Buffer";>;

struct csin
{
	uint3 DTID : SV_DispatchThreadID;
	uint3 GTID : SV_GroupThreadID;
	uint3 GID : SV_GroupID;
};

[numthreads(XTHREADS, YTHREADS, ZTHREADS)]
void CSSet(csin input)
{
	/* Always use these lines to get the particleIndex! */
	uint particleIndex = GetParticleIndex( input.DTID.x );
	if (particleIndex == -1 ) return;
	
	/* There are different ways to access the data in your DynamicBuffer:
		a) Apply modifier to ALL particles
		b) Apply modifier to SELECTED particles (wrt. selectionIndex)
	   The following code shows, how you should access your bufferdata. You should
	   always do it like that:
	*/
	// 1) Get size of the buffer
	uint size, stride;
	ColorBuffer.GetDimensions(size,stride);
	// 2) Get the index into your buffer
	uint bufferIndex = GetDynamicBufferIndex( particleIndex, input.DTID.x , size);
	
	// Now we can set the attribute:
	ParticleBuffer[particleIndex].rotation += RotateBuffer[bufferIndex];
	
	// That's it! Have a look into existing modifiers for more complex examples (f.e. SelfRepulsion)
}

technique11 Set { pass P0{SetComputeShader( CompileShader( cs_5_0, CSSet() ) );} }

With this, you can now rotate your particle in 3d.

Once that is done, you would have to also provide a particle Effect to render the particle with regard to your new attribute. However, Rotation is actually a “special” attribute, because it is used quite often (for example in Heading). That is why you don’t necessarily need to write a custom effect shader, and instead simply set a flag called KNOW_ROTATION in your flashy new modifier module, like this:

image

With this little flag, most particle effect shaders will already pick up the particle’s rotation. Unfortunately, the sprite shader will not pick up on it, so you will have to clone and modify that shader. Have a look at e.g. Constant how rotation is being looked up, depending on the KNOW_ROTATION flag.


#3

Ah, so I can use those arbitrary constants, or fallback to some direct shaderInput if my particles don’t carry those values. Thx for the info!

Within the sprite shader I generate a “float3x3 newMatrix” for roation around Z, and multiply it with the inverse view (=billboard).

float sinX = sin (rotation);
float cosX = cos (rotation);
    
	//GENERATE ROTATION AROUND Z AXIS
    float3x3 rotationMatrix = float3x3( cosX, -sinX ,0 ,
								sinX, cosX  ,0 , 
								0   , 0     ,1);    	
	
	float3x3 newMatrix = mul(rotationMatrix, (float3x3)tVI) ;