Reaction diffusion (type of cellular automaton)

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Reaction diffusion (type of cellular automaton)

Post 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
reaction-diffusion-05.png (14.82 KiB) Viewed 16119 times
reaction-diffusion-05a.png
reaction-diffusion-05a.png (45.75 KiB) Viewed 16119 times
reaction-diffusion-05.love
CC0 (Creative Commons license)
(1.63 KiB) Downloaded 408 times
Last edited by darkfrei on Thu Mar 09, 2023 8:20 am, edited 1 time in total.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Reaction diffusion

Post by darkfrei »

If you have just two colors then it can be used as nonograms:
reaction-diffusion-05b-5.png
reaction-diffusion-05b-5.png (553 Bytes) Viewed 16117 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
2022-02-19T18_37_59-Nonogram.png (68.35 KiB) Viewed 16117 times
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Reaction diffusion

Post 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
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
glitchapp
Party member
Posts: 264
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: Reaction diffusion

Post by glitchapp »

Amazing, it looks like abstract art. It could be use to make nice textures too.
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: Reaction diffusion

Post by ReFreezed »

This is pretty cool!
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
User avatar
pgimeno
Party member
Posts: 3672
Joined: Sun Oct 18, 2015 2:58 pm

Re: Reaction diffusion

Post by pgimeno »

This would be great as a GIMP plug-in.
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Reaction diffusion (type of cellular automaton)

Post by darkfrei »

Is it possible to make a shader for it?
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
tourgen
Citizen
Posts: 53
Joined: Sat Mar 18, 2023 12:45 am

Re: Reaction diffusion (type of cellular automaton)

Post 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
tourgen
Citizen
Posts: 53
Joined: Sat Mar 18, 2023 12:45 am

Re: Reaction diffusion (type of cellular automaton)

Post 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
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Reaction diffusion (type of cellular automaton)

Post 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
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests