TransWikia.com

Combining cylindrical Billboarding and aligning with velocity (unity)

Game Development Asked by JingleSpell on November 2, 2021

I’m trying to make a custom GPU particle solution on Unity to fullfill some needs on my project, using compute shaders and custom shader + Graphics.DrawProceduralNow() to draw them.

While I managed to make the system, I’m struggling making the particles cylindrical billboards and align them to their velocity axis as I’m not really used to work with matrices.

I achieved to make both effect working individually (using usefull ressources on the forum) but I can’t manage to combine the two rotations without obtaining wrong results

enter image description here
enter image description here

v2f vert(uint id : SV_VertexID, uint inst : SV_InstanceID)
{
    v2f o;

    //Vertex position
    float3 q = quad[id];

    float3 newPos = q * particles[inst].size * _SizeMul;


    //PARTICLE DIRECTION

    float3 particleDirection = normalize(particles[inst].velocity);

    float3x3 rotMatrix;

    float3 xaxis = cross(float3(0,0,1), particleDirection);
    xaxis = normalize(xaxis);

    float3 zaxis = cross(xaxis, particleDirection);
    zaxis = normalize(zaxis);

    //Matrix for particle direction
    rotMatrix[0].xyz = float3(xaxis.x, particleDirection.x, zaxis.x);
    rotMatrix[1].xyz = float3(xaxis.y, particleDirection.y, zaxis.y);
    rotMatrix[2].xyz = float3(xaxis.z, particleDirection.z, zaxis.z);

    newPos = mul(rotMatrix, newPos);




    //CYLINDRICAL BILLBOARDING

    // Distance between the camera and the center
    float3 dist = _WorldSpaceCameraPos - particles[inst].position;

    // With atan the tree inverts when the camera has the same z position
    float angle = atan2(dist.x, dist.z);

    float cosinus = cos(angle);
    float sinus = sin(angle);

    // Matrix for billboarding
    rotMatrix[0].xyz = float3(cosinus, 0, sinus);
    rotMatrix[1].xyz = float3(0, 1, 0);
    rotMatrix[2].xyz = float3(- sinus, 0, cosinus);

    newPos = mul(rotMatrix, newPos);



    newPos += particles[inst].position;

    o.pos = mul(UNITY_MATRIX_VP, float4(newPos.xyz,1));

    o.uv = q + 0.5f;

    o.col = particles[inst].alive * particles[inst].color;

    return o;

}

Another way to say it is i would like Y to point toward the velocity direction and then rotate the quad around it’s new Y axis to make the billboard point at best toward camera.

Any help would be much appreciated and any other approach for cylindrical billboarding that would work once quad is aligned to velocity vector would be welcomed too. Have a good day!

One Answer

Finally got it right ! Got it by trying to learn more about those matrices. I needed to use the direction vector between particle position and camera as a forward vector

Here's the code for those who need it.

float3 q = quad[id];

float3 newPos = q * particles[inst].size * _SizeMul;

float3 particleDirection = normalize(particles[inst].velocity);

float3 cameraDir = normalize(particles[inst].position - _WorldSpaceCameraPos);


float3x3 rotMatrix;

float3 xaxis = cross(cameraDir, particleDirection);
xaxis = normalize(xaxis);

float3 zaxis = cross(xaxis, particleDirection);
zaxis = normalize(zaxis);


rotMatrix[0].xyz = float3(xaxis.x, particleDirection.x, zaxis.x);
rotMatrix[1].xyz = float3(xaxis.y, particleDirection.y, zaxis.y);
rotMatrix[2].xyz = float3(xaxis.z, particleDirection.z, zaxis.z);

newPos = mul(rotMatrix, newPos);      

newPos += particles[inst].position;

o.pos = mul(UNITY_MATRIX_VP, float4(newPos.xyz,1));

o.uv = q + 0.5f;

o.col = particles[inst].alive * particles[inst].color;

return o;

Answered by JingleSpell on November 2, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP