Last active
June 1, 2018 18:38
-
-
Save ducklin5/c3a13bc0b852be34db9c4e66e2a23007 to your computer and use it in GitHub Desktop.
Godot 2D remake of LuggLD's and cjacobwade's SmearFrame Effect
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 canvas_item; | |
uniform float texSizeLength = 1.0 ; | |
uniform vec2 prev_pos = vec2(1.0,1.0) ; | |
uniform vec2 current_pos = vec2(1.0,1.0); | |
uniform float prev_rot = 0.0; | |
uniform float current_rot = 10.0; | |
uniform float _NoiseHeight = 64; | |
uniform float _NoiseScale = 5.0; | |
float rand(vec2 n) { | |
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); | |
} | |
float noise(vec2 p){ | |
vec2 ip = floor(p); | |
vec2 u = fract(p); | |
u = u*u*(3.0-2.0*u); | |
float res = mix( | |
mix(rand(ip),rand(ip+vec2(1.0,0.0)),u.x), | |
mix(rand(ip+vec2(0.0,1.0)),rand(ip+vec2(1.0,1.0)),u.x),u.y); | |
return res*res; | |
} | |
mat2 rotate2d(float _angle){ | |
return mat2(vec2(cos(_angle),-sin(_angle)), | |
vec2(sin(_angle),cos(_angle))); | |
} | |
void vertex(){ | |
// global position of the current vertext in a previous frame | |
vec2 prevVertexWorldPos = prev_pos + rotate2d(-prev_rot) * VERTEX; | |
// global position of the current vertext now | |
vec2 vertexWorldPos = current_pos + rotate2d(-current_rot) * VERTEX; | |
//displacement of the unshaded vertex from previous frame | |
vec2 displacement = vertexWorldPos - prevVertexWorldPos; | |
// dirDot = cos(theta) | |
// where theta is the angle between the displacment vector and the position of this vertex from the object center | |
float dirDot = dot(normalize(displacement), normalize(VERTEX)); | |
//determin the max smear length | |
vec2 unitVec = vec2(1, 1) * _NoiseHeight; | |
//smearVector is proportional to displacement vector | |
// and the magnitude of the fractional distance of the vertex from the center | |
// clamp that the between this maximum ( and minimum) | |
float fractionalVertexDistance = length(vertexWorldPos-current_pos)/texSizeLength; | |
vec2 smearVector = clamp(displacement * fractionalVertexDistance , -unitVec, unitVec); | |
float temp = 1.0; | |
if(length(displacement) < 0.0){ | |
temp = 0.0; | |
} | |
//THE MAGIC | |
//smearOffset is proportional to smearVector | |
//smearOffset is negative if the vertex is on opposite side of prev_pos otherwise 0 | |
vec2 smearOffset = smearVector * clamp((step(0,cos(current_rot))*2.0-1.0)*sign(dirDot), -1, 0) * temp; | |
// Calculate a noise float | |
temp = 1.0; | |
if(_NoiseScale > 0.0){ | |
temp = noise(vertexWorldPos * _NoiseScale); | |
} | |
// multiply the smearOffset by the float | |
smearOffset *= temp; | |
VERTEX += smearOffset * rotate2d(-current_rot); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: You have to set the current and previous position of the node every frame manually, like so: