Skip to content

Instantly share code, notes, and snippets.

@WiggleWizard
Created April 1, 2022 09:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WiggleWizard/72aab8be3f6c0b18a7c9bbcb8adcd1fa to your computer and use it in GitHub Desktop.
Save WiggleWizard/72aab8be3f6c0b18a7c9bbcb8adcd1fa to your computer and use it in GitHub Desktop.
Bendy Shader for Bendy Boyes
shader_type spatial;
const float PI = 3.14159265358979323846;
uniform vec4 color: hint_color;
uniform vec4 mesh_data;
uniform float curve_angle = 0;
uniform float curve_amount = 0;
uniform vec3 curve_direction = vec3(0);
// Evaluate quadratic Bezier curve
vec3 quad_bezier(vec3 a, vec3 b, vec3 c, float t)
{
float r = 1.0 - t;
return r * r * a + 2.0 * r * t * b + t * t * c;
}
// Evaluate the derivative of the quadratic Bezier curve
vec3 quad_bezier_tangent(vec3 a, vec3 b, vec3 c, float t)
{
return 2.0 * ((1.0 - t) * (b - a) + t * (c - b));
}
vec3 curve_end(vec3 base, vec3 dir, float height, float angle)
{
return base + height * (sin(angle) * dir + cos(angle) * vec3(0, 1, 0));
}
vec3 rodr_rot(vec3 k, float cosangle, vec3 v)
{
float sinangle = sqrt(1.0 - cosangle * cosangle);
return cosangle * v + sinangle * cross(k, v) + dot(k, v) * (1.0 - cosangle) * k;
}
void vertex()
{
const float deg2rad = PI / 180.0;
// Compute curve data
vec3 mesh_base = mesh_data.xyz;
float mesh_height = mesh_data.w;
vec3 mesh_up = vec3(0, mesh_height, 0);
vec3 mesh_top = mesh_base + mesh_up;
vec3 curve_dir = normalize(curve_direction);
vec3 curve_target = mesh_base + mesh_up * curve_amount;
vec3 curve_end = curve_end(mesh_base, curve_dir, mesh_height, curve_angle * deg2rad);
// Compute this vertex position and Bezier tangent
float height = clamp(VERTEX.y / mesh_height, 0, 1); // Compute relative height of vertex
vec3 bPoint = quad_bezier(mesh_base, curve_target, curve_end, height);
vec3 bTangent = quad_bezier_tangent(mesh_base, curve_target, curve_end, height);
vec3 rot_axis = cross(curve_dir, vec3(0, -sign(curve_angle), 0));
float cos_angle = bTangent.y / length(bTangent);
vec3 rot_offset = rodr_rot(rot_axis, cos_angle, vec3(VERTEX.x, 0, VERTEX.z));
// Update the vertex position
vec4 new_pos = vec4(rot_offset, 1);
new_pos.xyz += bPoint - mesh_base;
VERTEX = new_pos.xyz;
// Correct normals and tangents
NORMAL = NORMAL = rodr_rot(rot_axis, cos_angle, NORMAL);
TANGENT = rodr_rot(rot_axis, cos_angle, TANGENT);
}
void fragment()
{
ALBEDO = color.xyz;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment