Page 1 of 2
Reaction diffusion (type of cellular automaton)
Posted: Sat Feb 19, 2022 5:45 pm
by darkfrei
Hi all!
I've found very nice video:
With such algorithm you can make nice (seamless) mazes, maps or unique puzzles.
You can see how nice it growing up:
For example the result and tiled 3x3 times:
- reaction-diffusion-05.png (14.82 KiB) Viewed 15961 times
- reaction-diffusion-05a.png (45.75 KiB) Viewed 15961 times
Re: Reaction diffusion
Posted: Sat Feb 19, 2022 5:47 pm
by darkfrei
If you have just two colors then it can be used as nonograms:
- reaction-diffusion-05b-5.png (553 Bytes) Viewed 15959 times
Code: Select all
------------------------- left bar
4 11 1
3 3 2
4 2 3
7 3 3
1 11 3
5 6 3
6 3 3
2 6 2 4
1 6 3 3
2 4 2 2
5 2 3 1
5 2 3 1
9 3 2
8 2
3 1 4 2
5 9
1 6 10
9 1
9
4 6
------------------------- top bar
1 7 3
2 3 3 2 1
3 2 2 3 1
8 3 5
7 3 5
3 3 3 3
1 2 2 2 3
1 2 3 3 3
1 3 3 2 2
1 3 6 2
1 2 6 3
1 3 7
1 6 4
11 3 1
4 5 2 1
2 3 2 1
1 4 2 2 1
7 2 1
9 5 1
4 11
It has just one unique solution:
https://handsomeone.github.io/Nonogram/
- 2022-02-19T18_37_59-Nonogram.png (68.35 KiB) Viewed 15959 times
Re: Reaction diffusion
Posted: Sat Feb 19, 2022 5:57 pm
by darkfrei
The hardest (for me) was a "triangle function", for Laplace operator:
Code: Select all
function laplaceA (x, y)
local summ = 0
summ = getValue (x, y).a * -1 +
getValue (x-1, y).a * 0.2 +
getValue (x+1, y).a * 0.2 +
getValue (x, y-1).a * 0.2 +
getValue (x, y+1).a * 0.2 +
getValue (x+1, y+1).a * 0.05 +
getValue (x-1, y+1).a * 0.05 +
getValue (x+1, y-1).a * 0.05 +
getValue (x-1, y-1).a * 0.05
if summ < -1 then summ = -1 end
if summ > 1 then summ = 1 end
return summ
end
I've changed it to respect the 1/distance for all of near tiles:
Code: Select all
-- total weights:
-- 1 + 1 + 1 + 1 + 0.7071 + 0.7071 + 0.7071 + 0.7071 = 6.8284
-- weight for edge:
-- 0.7071/6.8284 = 0.10355
-- weight for side:
-- (1 - 4*0.10355)/4 = 0.14645
function laplaceA (x, y)
local summ = 0
summ = getValue (x, y).a * -1 +
getValue (x-1, y).a * 0.14645 +
getValue (x+1, y).a * 0.14645 +
getValue (x, y-1).a * 0.14645 +
getValue (x, y+1).a * 0.14645 +
getValue (x+1, y+1).a * 0.10355 +
getValue (x-1, y+1).a * 0.10355 +
getValue (x+1, y-1).a * 0.10355 +
getValue (x-1, y-1).a * 0.10355
if summ < -1 then summ = -1 end
if summ > 1 then summ = 1 end
return summ
end
Re: Reaction diffusion
Posted: Sat Feb 19, 2022 8:45 pm
by glitchapp
Amazing, it looks like abstract art. It could be use to make nice textures too.
Re: Reaction diffusion
Posted: Sun Feb 20, 2022 12:17 am
by ReFreezed
This is pretty cool!
Re: Reaction diffusion
Posted: Sun Feb 20, 2022 11:58 am
by pgimeno
This would be great as a GIMP plug-in.
Re: Reaction diffusion (type of cellular automaton)
Posted: Sun Mar 19, 2023 6:27 pm
by darkfrei
Is it possible to make a shader for it?
Re: Reaction diffusion (type of cellular automaton)
Posted: Wed Mar 22, 2023 5:42 pm
by tourgen
darkfrei wrote: ↑Sun Mar 19, 2023 6:27 pm
Is it possible to make a shader for it?
Absolutely. This guy has excellent shader videos, and in fact did Game of Life in a shader. It uses a buffer texture to record state (of the previous evolution step). Game of Life is one of the original cellular automata algorithms. Apply different rules to produce different results: for instance, modelling the slime mold behavior.
https://www.youtube.com/watch?v=xh61Ol2X4GA
Re: Reaction diffusion (type of cellular automaton)
Posted: Wed Mar 22, 2023 5:47 pm
by tourgen
Also, you might be interested in these papers/references:
Reaction-Diffusion by the Gray-Scott Model: Pearson's Parametrization
https://mrob.com/pub/comp/xmorphia/
simulating slime mold
https://cargocollective.com/sagejenson/physarum
you might also be interested in Voronoi in glsl:
https://www.youtube.com/watch?v=l-07BXzNdPw
Re: Reaction diffusion (type of cellular automaton)
Posted: Tue Sep 05, 2023 8:06 pm
by darkfrei
tourgen wrote: ↑Wed Mar 22, 2023 5:42 pm
darkfrei wrote: ↑Sun Mar 19, 2023 6:27 pm
Is it possible to make a shader for it?
Absolutely. This guy has excellent shader videos, and in fact did Game of Life in a shader. It uses a buffer texture to record state (of the previous evolution step). Game of Life is one of the original cellular automata algorithms. Apply different rules to produce different results: for instance, modelling the slime mold behavior.
https://www.youtube.com/watch?v=xh61Ol2X4GA
Is it rigth?
Code: Select all
local shader = love.graphics.newShader
[[
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
// Calculate the texture coordinate offsets for neighboring pixels
vec2 offsetH = vec2(1.0 / love_ScreenSize.x, 0.0);
vec2 offsetV = vec2(0.0, 1.0 / love_ScreenSize.y);
// Sample the colors of neighboring pixels
vec4 colorCenter = Texel(texture, texture_coords);
vec4 colorLeft = Texel(texture, texture_coords - offsetH);
vec4 colorRight = Texel(texture, texture_coords + offsetH);
vec4 colorUp = Texel(texture, texture_coords - offsetV);
vec4 colorDown = Texel(texture, texture_coords + offsetV);
vec4 colorUpLeft = Texel(texture, texture_coords - offsetV - offsetH);
vec4 colorUpRight = Texel(texture, texture_coords - offsetV + offsetH);
vec4 colorDownLeft = Texel(texture, texture_coords + offsetV - offsetH);
vec4 colorDownRight = Texel(texture, texture_coords + offsetV + offsetH);
// Laplace sum the colors of all neighboring pixels, including diagonals
vec4 sumColor = - 1.0 * colorCenter +
0.14645 * (colorLeft + colorRight + colorUp + colorDown) +
0.10355 * (colorUpLeft + colorUpRight + colorDownLeft + colorDownRight);
sumColor.a = 1.0;
return sumColor;
}
]]
The main.lua (it works wrong, please help me):
Code: Select all
local canvasWidth, canvasHeight = 600, 600
local shader = love.graphics.newShader
[[
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
// Calculate the texture coordinate offsets for neighboring pixels
vec2 offsetH = vec2(1.0 / love_ScreenSize.x, 0.0);
vec2 offsetV = vec2(0.0, 1.0 / love_ScreenSize.y);
// Sample the colors of neighboring pixels
vec4 colorCenter = Texel(texture, texture_coords);
vec4 colorLeft = Texel(texture, texture_coords - offsetH);
vec4 colorRight = Texel(texture, texture_coords + offsetH);
vec4 colorUp = Texel(texture, texture_coords - offsetV);
vec4 colorDown = Texel(texture, texture_coords + offsetV);
vec4 colorUpLeft = Texel(texture, texture_coords - offsetV - offsetH);
vec4 colorUpRight = Texel(texture, texture_coords - offsetV + offsetH);
vec4 colorDownLeft = Texel(texture, texture_coords + offsetV - offsetH);
vec4 colorDownRight = Texel(texture, texture_coords + offsetV + offsetH);
// Laplace sum the colors of all neighboring pixels, including diagonals
vec4 sumColor = - 1.0 * colorCenter +
0.14645 * (colorLeft + colorRight + colorUp + colorDown) +
0.10355 * (colorUpLeft + colorUpRight + colorDownLeft + colorDownRight);
sumColor.a = 1.0;
return sumColor;
}
]]
local canvases = {
love.graphics.newCanvas(canvasWidth, canvasHeight),
love.graphics.newCanvas(canvasWidth, canvasHeight)
}
local iCanvas = 1
function love.load()
love.window.setTitle("Reaction Diffusion Simulation")
love.window.setMode(canvasWidth, canvasHeight)
love.graphics.setCanvas(canvases[1])
love.graphics.setColor (1,1,0)
for i = 1, 10 do
love.graphics.rectangle ('fill', math.random (canvasWidth-10), math.random (canvasHeight-10), 10, 10)
end
love.graphics.setCanvas(canvases[2])
love.graphics.setColor (0,1,1)
for i = 1, 10 do
love.graphics.rectangle ('fill', math.random (canvasWidth-10), math.random (canvasHeight-10), 10, 10)
end
love.graphics.setCanvas()
end
function love.update(dt)
local iPrevCanvas = iCanvas
iCanvas = iCanvas %2 +1
love.window.setTitle (iCanvas)
love.graphics.setCanvas(canvases[iCanvas])
love.graphics.setShader(shader)
love.graphics.draw (canvases[iPrevCanvas])
love.graphics.setShader()
love.graphics.setCanvas()
end
function love.draw()
love.graphics.draw (canvases[iCanvas])
end
function love.keypressed (k, s)
if k == 'escape' then
love.event.quit ()
end
print (k)
end