Created
April 1, 2022 09:13
-
-
Save WiggleWizard/72aab8be3f6c0b18a7c9bbcb8adcd1fa to your computer and use it in GitHub Desktop.
Bendy Shader for Bendy Boyes
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
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