I am animating the x,y,z coordinates of vertices in a sphere like manner with horizontal rings around the center as attributes on a THREE.Points() object. It uses a MeshStandardMaterial() and I have then tilted the Points object slightly along the z axis with points.rotation.z = 0.2. Everything is as expected :
When I swap the MeshStandardMaterial() for ShaderMaterial() and rewrite the animation part into a shader the z tilt has gone. I have checked with an axis helper on the Points object and indeed the object is still tilted but it seems the shader animation is now moving the vertices around the x, y, z coordinates of the scene rather than the tilted Points object.
As you can see in the picture the sphere and outer ring of particles are no longer tilted on the same angle as the axis helpers.
Is there a quick fix for this or do I have to change the shader animation and factor in an overall rotation there?
Thanks.
Here is the shader script as requested, however I have tested the principle on a few shader animations from various tutorials I have undertaken and they all behave in the same way, so I'm assuming this is an inherent problem or expected behaviour with shaders:
#define PI 3.1415926535897932384626433832795
uniform float uSize;
attribute float aScale;
attribute vec4 aParticle;
uniform float uTime;
varying vec3 vColor;
void main()
{
/**
* Position
*/
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
/**
* Particle
*/
float moveT = aParticle.g;
float moveS = aParticle.r + uTime * aParticle.b;
float fullRotate = step(360.0, moveS);
moveS = moveS - (fullRotate * 360.0);
float radMoveS = moveS * (PI / 180.0);
float radMoveT = moveT * (PI / 180.0);
modelPosition.x = aParticle.a * cos(radMoveS) * sin(radMoveT); //x
modelPosition.y = aParticle.a * cos(radMoveT); //y
modelPosition.z = aParticle.a * sin(radMoveS) * sin(radMoveT); //z
vec4 viewPosition = viewMatrix * modelPosition;
vec4 projectedPosition = projectionMatrix * viewPosition;
gl_Position = projectedPosition;
/**
* Size
*/
gl_PointSize = uSize * aScale;
//Attenuation
gl_PointSize *= ( 1.0 / - viewPosition.z );
/**
* Color
*/
vColor = color;
}
At the top of your vertex shader, you apply the modelMatrix
to your position
by multiplication:
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
But then you overwrite any results from that matrix multiplication when you assign each xyz
component a new value:
modelPosition.x = aParticle.a * cos(radMoveS) * sin(radMoveT);
This means that what you're seeing is a. Not using position
, and b. Not using modelMatrix
. You simply have to apply the matrix multpilication after you've assigned the local vertex positions.
vec4 newPosition = vec4(
aParticle.a * cos(radMoveS) * sin(radMoveT), // x
aParticle.a * cos(radMoveT), // y
aParticle.a * sin(radMoveS) * sin(radMoveT), // z
1.0 // w
);
Vec4 modelPosition = modelMatrix * newPosition;