Skip to content

Instantly share code, notes, and snippets.

@AlecTroemel
Created October 9, 2021 15:10
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 AlecTroemel/1ea22c451363334bc4ee3e8e6f85527c to your computer and use it in GitHub Desktop.
Save AlecTroemel/1ea22c451363334bc4ee3e8e6f85527c to your computer and use it in GitHub Desktop.
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