Created
October 9, 2021 15:10
-
-
Save AlecTroemel/1ea22c451363334bc4ee3e8e6f85527c to your computer and use it in GitHub Desktop.
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; | |
render_mode cull_disabled,diffuse_toon,specular_toon; | |
uniform vec4 color_top: hint_color = vec4(1,1,1,1); | |
uniform vec4 color_bottom: hint_color = vec4(0,0,0,1); | |
uniform vec4 color_highlight: hint_color = vec4(0,0,0,1); | |
const vec3 UP = vec3(0,1,0); | |
const vec3 RIGHT = vec3(1,0,0); | |
const float PI = 3.14159; | |
const float DEG2RAD = (PI / 180.0); | |
varying float wind; | |
uniform float wind_scale = 4.0; | |
uniform float wind_speed = 1.0; | |
uniform vec3 wind_direction = vec3(0,0,-1); | |
uniform float deg_sway_pitch = 80.0; | |
uniform float deg_sway_yaw = 45.0; | |
// rotation override | |
uniform sampler2D wind_override; | |
varying mat3 rotation_factor; | |
// CUSTOM_DATA = vec4(x,y,z,w) | |
// Matrix is a representation of rotation | |
mat3 mat3_from_axis_angle(float angle, vec3 axis) { | |
float s = sin(angle); | |
float c = cos(angle); | |
float t = 1.0 - c; | |
float x = axis.x; | |
float y = axis.y; | |
float z = axis.z; | |
return mat3( | |
vec3(t*x*x+c, t*x*y-s*z, t*x*z+s*y), | |
vec3(t*x*y+s*z, t*y*y+c, t*y*z-s*x), | |
vec3(t*x*z-s*y, t*y*z+s*z, t*z*z+c) | |
); | |
} | |
vec2 random2(vec2 p) { | |
return fract(sin(vec2( | |
dot(p, vec2(127.32, 231.4)), | |
dot(p, vec2(12.3, 146.3)) | |
)) * 231.23); | |
} | |
float worley2(vec2 p) { | |
float dist = 1.0; | |
vec2 i_p = floor(p); | |
vec2 f_p = fract(p); | |
for(int y=-1; y<=1; y++) { | |
for(int x=-1; x<= 1; x++) { | |
vec2 n = vec2(float(x), float(y)); | |
vec2 diff = n + random2(i_p + n) - f_p; | |
dist = min(dist, length(diff)); | |
} | |
} | |
return dist; | |
} | |
mat3 wind_override_rot(float wind_override_axis, vec3 wind_override_axis_origin, mat3 to_model) { | |
float factor = 1.0; | |
float override = 0.0; | |
if (wind_override_axis > 0.51 || wind_override_axis < 0.49) { | |
override = PI * (wind_override_axis - 0.5) - 0.1; | |
if (wind_override_axis < 0.5) { | |
factor = -1.0; | |
} | |
} | |
return mat3_from_axis_angle(override, to_model * normalize(wind_override_axis_origin)); | |
} | |
void vertex() { | |
NORMAL = UP; | |
vec3 vertex = VERTEX; | |
vec3 wind_direction_normalized = normalize(wind_direction); | |
float time = TIME * wind_speed; | |
vec2 uv = (WORLD_MATRIX * vec4(vertex, -1.0)).xz * wind_scale; | |
uv += wind_direction_normalized.xz * time; | |
wind = pow(worley2(uv), 2.0) * UV2.y; | |
mat3 to_model = inverse(mat3(WORLD_MATRIX)); | |
vec3 wind_forward = to_model * wind_direction_normalized; | |
vec3 wind_right = normalize(cross(wind_forward, UP)); | |
float sway_pitch = ((deg_sway_pitch * DEG2RAD) * wind) + INSTANCE_CUSTOM.z; | |
float sway_yaw = ((deg_sway_yaw * DEG2RAD) * sin(time) * wind) + INSTANCE_CUSTOM.w; | |
mat3 rot_right = mat3_from_axis_angle(sway_pitch, wind_right); | |
mat3 rot_forward = mat3_from_axis_angle(sway_yaw, wind_forward); | |
rotation_factor = rot_right * rot_forward; | |
// Apply wind override texture | |
// X axis | |
float wind_override_x = texture(wind_override, COLOR.rb).r; | |
vec3 wind_override_x_origin = vec3(0.0,0.0, COLOR.b); | |
float x_factor = 1.0; | |
float x_override = 0.0; | |
if (wind_override_x > 0.51 || wind_override_x < 0.49) { | |
// override value | |
x_override = PI * (wind_override_x - 0.5) - 0.1; | |
if (wind_override_x < 0.5) { | |
x_factor = -1.0; | |
} | |
} | |
mat3 rot_x = mat3_from_axis_angle(x_override, to_model * normalize(wind_override_x_origin)); | |
// Z axis | |
float wind_override_z = texture(wind_override, COLOR.rb).b; | |
vec3 wind_override_z_origin = vec3(-COLOR.r, 0.0,0.0); | |
float z_factor = 1.0; | |
float z_override = 0.0; | |
if (wind_override_z > 0.51 || wind_override_z < 0.49) { | |
// override value | |
z_override = PI * (wind_override_z - 0.5) - 0.1; | |
if (wind_override_z < 0.5) { | |
z_factor = -1.0; | |
} | |
} | |
mat3 rot_z = mat3_from_axis_angle(z_override, to_model * normalize(wind_override_z_origin)); | |
// Depending on where we are in UV, the order of matrix multiplication changes. This depends on your script code later on. | |
if((x_factor * z_factor) > 0.0) { | |
rotation_factor = rot_z * rot_x * rotation_factor; | |
} else { | |
rotation_factor = rot_x * rot_z * rotation_factor; | |
} | |
vertex.xz *= INSTANCE_CUSTOM.x; | |
vertex.y *= INSTANCE_CUSTOM.y; | |
// vertex *= mat3_from_axis_angle(TIME, UP); // rotates blades | |
VERTEX = rotation_factor * vertex; | |
COLOR = mix(color_bottom, color_top, UV2.y); | |
} | |
void fragment() { | |
// half the blades need their normal flipped because they're rotated > 180 degrees | |
float side = FRONT_FACING ? 1.0 : -1.0; | |
NORMAL = NORMAL * side; | |
// Split the smooth gradient of color into just 3, depending on distances frop top/bottom | |
float c_dist_to_top = distance(COLOR.rgb, color_top.rgb); | |
float c_dist_to_bottom = distance(COLOR.rgb, color_bottom.rgb); | |
float dist_diff = abs(c_dist_to_bottom - c_dist_to_top); | |
if (dist_diff < 0.05) { | |
ALBEDO = mix(color_bottom, color_top, 0.5).rgb; | |
} else if (c_dist_to_bottom < c_dist_to_top) { | |
ALBEDO = color_bottom.rgb; | |
} else { | |
ALBEDO = color_top.rgb; | |
} | |
ALBEDO = COLOR.rgb; // for smooth gradient | |
SPECULAR = 0.5; | |
ROUGHNESS = clamp(1.0 - (wind * 2.0), 0.0, 1.1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment