Last active
October 19, 2016 09:55
-
-
Save Robadob/481a8a2b0dd3f74865b3ab7218dde7e0 to your computer and use it in GitHub Desktop.
3D Rotation inside a vertex shader, where the models remains upright
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 430 | |
//gl_InstanceID //attribute in uint agent_index; | |
in vec3 _vertex; | |
out vec3 u_normal; | |
uniform mat4 _modelViewMat; | |
uniform mat4 _projectionMat; | |
uniform samplerBuffer _texBuf; //Position | |
uniform samplerBuffer _texBuf2; //Direction | |
uniform vec3 _color; | |
out vec3 o_color; | |
void main(){ | |
//Grab model offset from textures | |
vec3 loc_data = texelFetch(_texBuf, gl_InstanceID).xyz;//vec3(gl_InstanceID,0,0);// | |
vec3 dir_data = texelFetch(_texBuf2, gl_InstanceID).xyz;//vec3(gl_InstanceID,0,0);// | |
float locLen = length(_vertex);//Calc distance from rotation pt, so we can use it later | |
//Init our axis | |
vec3 look = vec3(1,0,0);//Model looks down X axis to begin | |
vec3 up = vec3(0,1,0); | |
vec3 right = cross(look,up); | |
vec3 point = _vertex; | |
//Vector currently points (1,0,0) | |
//We want to rotate that to point to loc_data | |
//And then stabilise the Up vector (to remove roll) | |
//Calculate rotation angle | |
vec3 rotTarget = normalize(vec3(dir_data.x,0,dir_data.z)); | |
if(rotTarget!=vec3(0)&&rotTarget!=look&&rotTarget!=-look) | |
{ | |
float yaw = acos(dot(look,rotTarget)); | |
//Rotate about UP | |
float cosL = cos(yaw); | |
float sinL = sin(yaw); | |
vec3 u = normalize(cross(look,rotTarget));//vec3(0,1,0); | |
mat3 rm = mat3( | |
(cosL + (u.x*u.x*(1-cosL))), ((u.x*u.y*(1-cosL))-(u.z*sinL)), ((u.x*u.z*(1-cosL))+(u.y*sinL)), | |
((u.y*u.x*(1-cosL))+(u.z*sinL)), (cosL + (u.y*u.y*(1-cosL))), ((u.y*u.z*(1-cosL))-(u.x*sinL)), | |
((u.z*u.x*(1-cosL))-(u.y*sinL)), ((u.z*u.y*(1-cosL))+(u.x*sinL)), (cosL + (u.z*u.z*(1-cosL))) | |
); | |
right = rm*right; | |
//Apply rotation matrix | |
point = rm*point; | |
} | |
rotTarget = normalize(vec3(dir_data.x,dir_data.y,0)); | |
if(rotTarget!=vec3(0)&&rotTarget!=look&&rotTarget!=-look) | |
{ | |
//This is the angle | |
float pitch = acos(dot(look,rotTarget)); | |
float cosL = cos(pitch); | |
float sinL = sin(pitch); | |
vec3 u =normalize(right); | |
u=(dir_data.y>0)?u:-u; | |
mat3 rm = mat3( | |
(cosL + (u.x*u.x*(1-cosL))), ((u.x*u.y*(1-cosL))-(u.z*sinL)), ((u.x*u.z*(1-cosL))+(u.y*sinL)), | |
((u.y*u.x*(1-cosL))+(u.z*sinL)), (cosL + (u.y*u.y*(1-cosL))), ((u.y*u.z*(1-cosL))-(u.x*sinL)), | |
((u.z*u.x*(1-cosL))-(u.y*sinL)), ((u.z*u.y*(1-cosL))+(u.x*sinL)), (cosL + (u.z*u.z*(1-cosL))) | |
); | |
point = rm*point; | |
//If upside down (rotation if 90-270 degrees) | |
if(cosL<0) | |
{ | |
float roll=3.14159; | |
float cosL = cos(roll); | |
float sinL = sin(roll); | |
up=rm*up; | |
u =normalize(cross(right,up)); | |
rm = mat3( | |
(cosL + (u.x*u.x*(1-cosL))), ((u.x*u.y*(1-cosL))-(u.z*sinL)), ((u.x*u.z*(1-cosL))+(u.y*sinL)), | |
((u.y*u.x*(1-cosL))+(u.z*sinL)), (cosL + (u.y*u.y*(1-cosL))), ((u.y*u.z*(1-cosL))-(u.x*sinL)), | |
((u.z*u.x*(1-cosL))-(u.y*sinL)), ((u.z*u.y*(1-cosL))+(u.x*sinL)), (cosL + (u.z*u.z*(1-cosL))) | |
); | |
point = rm*point; | |
} | |
} | |
//Output vert loc to be interpolated for shader to calc norm | |
vec3 t_position = point + loc_data; | |
u_normal = vec4(_modelViewMat * vec4(t_position,1.0)).xyz; | |
gl_Position = _projectionMat * _modelViewMat * vec4(t_position,1.0); | |
o_color = _color; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment