diff options
Diffstat (limited to 'libs/moonshine/fog.lua')
-rw-r--r-- | libs/moonshine/fog.lua | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/libs/moonshine/fog.lua b/libs/moonshine/fog.lua new file mode 100644 index 0000000..9c90f9a --- /dev/null +++ b/libs/moonshine/fog.lua @@ -0,0 +1,129 @@ +--[[ +Animated 2D Fog (procedural) +Originally for Godot Engine by Gonkee https://www.youtube.com/watch?v=QEaTsz_0o44&t=6s + +Translated for löve by Brandon Blanker Lim-it @flamendless +]]-- + +--[[ +SAMPLE USAGE: +local moonshine = require("moonshine") +local effect + +local image, bg +local image_data +local shader_fog +local time = 0 + +function love.load() + image_data = love.image.newImageData(love.graphics.getWidth(), love.graphics.getHeight()) + image = love.graphics.newImage(image_data) + bg = love.graphics.newImage("bg.png") + effect = moonshine(moonshine.effects.fog) + effect.fog.fog_color = {0.1, 0.0, 0.0} + effect.fog.speed = {0.2, 0.9} +end + +function love.update(dt) + time = time + dt + effect.fog.time = time +end + +function love.draw() + love.graphics.draw(bg) + effect(function() + love.graphics.draw(image) + end) +end +]] + +return function(moonshine) + local fog_color + local octaves + local speed + local time + + local shader = love.graphics.newShader([[ + extern vec3 fog_color = vec3(0.35, 0.48, 0.95); + extern int octaves = 4; + extern vec2 speed = vec2(0.0, 1.0); + extern float time; + + float rand(vec2 coord) + { + return fract(sin(dot(coord, vec2(56, 78)) * 1000.0) * 1000.0); + } + + float noise(vec2 coord) + { + vec2 i = floor(coord); //get the whole number + vec2 f = fract(coord); //get the fraction number + float a = rand(i); //top-left + float b = rand(i + vec2(1.0, 0.0)); //top-right + float c = rand(i + vec2(0.0, 1.0)); //bottom-left + float d = rand(i + vec2(1.0, 1.0)); //bottom-right + vec2 cubic = f * f * (3.0 - 2.0 * f); + return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y; //interpolate + } + + float fbm(vec2 coord) //fractal brownian motion + { + float value = 0.0; + float scale = 0.5; + for (int i = 0; i < octaves; i++) + { + value += noise(coord) * scale; + coord *= 2.0; + scale *= 0.5; + } + return value; + } + + vec4 effect(vec4 color, Image texture, vec2 tc, vec2 sc) + { + vec2 coord = tc * 20.0; + vec2 motion = vec2(fbm(coord + vec2(time * speed.x, time * speed.y))); + float final = fbm(coord + motion); + return vec4(fog_color, final * 0.5); + } + ]]) + + local setters = {} + + setters.fog_color = function(t) + assert(type(t) == "table", "Passed argument to fog_color must be a table containing 3 color values") + fog_color = t + shader:send("fog_color", fog_color) + end + + setters.octaves = function(i) + assert(type(i) == "number", "Passed argument to octaves must be an integer") + octaves = i + shader:send("octaves", octaves) + end + + setters.speed = function(t) + assert(type(t) == "table", "Passed argument to speed must be a table containing 2 values") + speed = t + shader:send("speed", speed) + end + + setters.time = function(n) + assert(type(n) == "number", "Passed argument to time must be a number") + time = n + shader:send("time", time) + end + + local defaults = { + fog_color = {0.35, 0.48, 0.95}, + octaves = 4, + speed = {0.5, 0.5}, + } + + return moonshine.Effect({ + name = "fog", + shader = shader, + setters = setters, + defaults = defaults, + }) +end |