It looks like you're new here. If you want to get involved, click one of these buttons!
I am trying to get this working with Codea:
https://github.com/vincent23/love2d-experiments/blob/master/metaball/main.lua
I have recorded a video but the image is flipped, dont know why exactly xD
Here is the Main.lua for Codea
balls = {}
v = {}
x = 0
y = 0
radius = 66
width = WIDTH-radius
height = HEIGHT-radius
paused = false
time = 0
strobo = false
m = nil
--[[
original source code , love2d version:
https://github.com/vincent23/love2d-experiments/blob/master/metaball/main.lua
]]--
displayMode(STANDARD)
function setup()
parameter.number("schwelle",0.002, 2.0, 0.002)
parameter.boolean("drawMesh",false)
local i = 0
for i=1,40 do
balls[i] = {math.random(0,width), math.random(0,height)}
local v_ges = math.random(200,400)
local v_x = math.random(0,v_ges)
local v_y = math.sqrt(math.pow(v_ges,2) - math.pow(v_x,2))
v[i] = {v_x, v_y}
end
m = mesh()
m.texture = "Cargo Bot:Codea Icon"
m.shader = shader("Documents:MetaBall")
rIdx = m:addRect(0, 0, 0, 0)
m:setRectColor(i, 127,0,0)
m:setRect(rIdx, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
m.shader.width = width
m.shader.height = height
m.shader.time = time
m.shader.schwelle = schwelle
end
function draw()
background(0)
strokeWidth(2)
fill(17, 120, 223, 255)
stroke(17, 120, 223, 255)
local dt = DeltaTime
time = time + dt
if paused then
return
end
for i=1,#balls do
for j=1,#balls do
if i ~= j then
local left, right
local bottom, top
if balls[i][1] < balls[j][1] then
left = i
right = j
else
left = j
right = i
end
if balls[i][2] < balls[j][2] then
bottom = i
top = j
else
bottom = j
top = i
end
local x = balls[right][1]-balls[left][1]
local y = balls[right][2]-balls[left][2]
local r = math.sqrt(math.pow(x,2) + math.pow(y,2))
local f = 200000/math.pow(r,2) * dt
local fx = x/r*f
local fy = y/r*f
balls[left][1] = balls[left][1] - fx
balls[right][1] = balls[right][1] + fx
balls[left][2] = balls[left][2] - fy
balls[right][2] = balls[right][2] + fy
end
end
end
for i=1,#balls do
balls[i][1] = balls[i][1] + v[i][1] * dt
if (balls[i][1] < 10 and v[i][1] < 0) or (balls[i][1] >= width -10 and v[i][1] > 0) then
v[i][1] = v[i][1] * (-1)
end
balls[i][2] = balls[i][2] + v[i][2] * dt
if (balls[i][2] < 10 and v[i][2] < 0) or (balls[i][2] >= height-10 and v[i][2] > 0) then
v[i][2] = v[i][2] * (-1)
end
if not drawMesh then
ellipse(balls[i][1],balls[i][2],radius)
end
end
if drawMesh then
--local cw,ch = spriteSize(m.texture)
--m:setRect(rIdx, WIDTH/2, HEIGHT/2, cw, ch) -- uncomment if texture size changes
-- Configure out custom uniforms for the shader
if strobo then
m.shader.time = time --ElapsedTime
end
--m.shader.schwelle = schwelle
--m.shader.width = cw
--m.shader.height = ch
m.shader.balls = balls
-- Draw the mesh
m:draw()
end
end
function touched(touch)
if touch.state == BEGAN then
paused = not paused
print("paused:",paused)
end
end
This is the vertex program for the metaballs shader:
//
// A metaballs shader
//
//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;
uniform float width;
uniform float height;
uniform float schwelle;
uniform vec2 balls[40];
uniform float time;
//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying highp vec4 bColor;
float metaball(vec2 center, vec2 point) {
vec2 v = point-center;
return 1.0/dot(v, v);
}
vec4 effect(
vec4 color, vec2 tex_c,vec2 coord
) {
float val = 0.0;
for (int i =0; i<40; i++) {
val = val + metaball(balls[i],coord);
}
vec4 bar;
if (val < schwelle) {
val = val / schwelle;
bar = vec4(
0.8*(1.0-coord.x/width),
0.8*(1.0-coord.y/height),
0.3*val,
1.0
);
}
else {
bar = vec4(
0.8*coord.x/width,
0.8*coord.y/height,
0.0,1.0
);
}
float foo = mod(time,1.0);
if (foo < 0.1) {
return bar + vec4(vec3(foo*3.14*50.0), 1.0);
}
return bar;
}
void main()
{
//Pass the mesh color to the fragment shader
vColor = color;
vTexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
//Pass the balls effect color to the fragment
bColor = effect(color, texCoord, vTexCoord);
//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
and here it is the fragment program:
//
// A metaballs fragment shader
//
//This represents the current texture on the mesh
uniform lowp sampler2D texture;
//The interpolated vertex color for this fragment
varying lowp vec4 vColor;
//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;
//balls effect
varying highp vec4 bColor;
void main()
{
//Sample the texture at the interpolated coordinate
lowp vec4 col = texture2D( texture, vTexCoord );
//Set the output color to the texture color
gl_FragColor = bColor+col;
}
Hope you smart people know How to fix this ;-)
Comments
Not quite the shader you are referring too, but something in that direction. Performance is poor all code is nicked off the web. Coder as string, so paste it all into main and it should run.
Only tested landscape ipad2
Not really sure what the effect should look like, so this is just a pointer. Main things: the shader looks like a fragment shader, not a vertex one. And you passed the balls' centres as an array of arrays of floats, not an array of vec2s.
Vertex shader
Fragment shader
.@spacemonkey you did it!!
Here is a video
.@andrew_stacey ok, I understand now thanks
Here it is another approximation using this shader:
http://www.niksula.hut.fi/~hkankaan/Homepages/metaballs.html
WebGL:
http://glsl.heroku.com/e#6920.0
Lua code:
Vertex Shader part:
Fragment Shader Part:
And the video:

OK, now we have physics, we can say this is the first fluid simulation in Codea
The shader is the same of my last post here.
This is the result in the video:

1) there are only balls with default Gravity
2) iPad accelerometer gravity activated
3) glsl shader activate
moving around, water simulation ready
That's fantastic!
Thanks @Jmv38 ,has anyone tried this webgl shader?
)
http://madebyevan.com/webgl-water/
wouldnt be amazing to have this working with our beloved Codea?
That's a fairly hectic example. It contains multiple shaders, the biggest barrier is it uses a couple of capabilities which we don't have. Specifically it uses textures in vertex shaders which the iPad doesn't support. It looks like it uses some cube maps which I'm not sure if codea supports. Also it uses some extensions such as OES_Texture_Float and I'm not sure whether ipad has this or not and if so how you use it via codea.
But other than that, it would be amazing ;-)
I understand, maybe we just need to understand how this kind of shaders ( vertex, fragment and pixel shaders...because we cant use geometry shaders with a good framerate ) works to replicate the behaviour of the surface in the water of this video (3d):
Shaders explained here in this video at 1:35
You can create a fairly simple moving water effect by using noise and overlaying a slightly transparent rectangle. The video below shows the result using the noise demo project with a single line of code to overlay a rect, showing the effect of using different colours and alpha values to create water, cloud, dust, etc. it's amazing how much it improves the basic noise effect.
NB the original looks better than the video
@Ignatz I think that is faster but with low res , do you think that we can achieve to traslate this
http://www.bonzaisoftware.com/water_tut.html#glsl
- GLSL program:
http://forum.bonzaisoftware.com/viewthread.php?tid=10
to Codea + GLSL Shaders?
or this one!:
I think Codea is going to struggle with detailed 3D surface rendering, but I am not an expert in this, so don't take my word for it.
This is a new version based on processing, this time I'm using the virtual space of an image to read/write values of the metaball...it is still too slow for gaming...
Opinions?
Video:

I had a idea on this, it does the metaballs by first creating a texture representing the fall off for a point, then rendering all points addatively to an off screen image, and then finally using that image as a texture to render back to screen based on a threshold.
It's a bit ugly (2 color) but the methodology could definitely be extended and it's very fast. It's also a little fuzzy round the edges...
I wish I had seen this before I made my own version. I'll post my version once I finish optimizing it.
@spacemonkey - what does this do?
extension GL_EXT_shader_framebuffer_fetch : require
@Ignatz it enables an extension beyond the base OpenGL ES capabilities. Extensions allow hardware manufacturers to add interesting things as options on their gear, but of course it reduces the compatability of the shader as it now only works on hardware that supports the extension.
Anyway, this specific one allows you to read data back from the current framebuffer. So in the fragment shader I can additively blend to the current screen, gl_LastFragData[0]; reads the current color of the pixel from the screen (or image if you are using setContext) when you are in the fragment shader.
Here's another one, it takes my old bouncing balls, and applies the metaballs approach as above.
I only see a black screen running in an iPad2 with iOS 5.1 and Codea 1.5.4(2).
Error:
GL_EXT_shader_framebuffer_fetch not supported
Interesting. It's definitely supported hardware wise on iPad2 cos that's what I have, I guess it's iOS 5, I am running 6.
Yes @spacemonkey ,that extension was added with iOS6 beta
After about two hours of coding, my first Metaball shader:
It only gets about 10 FPS... At a thousand Metaballs. :P
Mine uses the simplest math to calculate bridges...none. It just draws a bunch of shaded balls on the screen with the ADDITIVE blend mode. Then it has a shader check if a pixel is bright enough, if it is it renders it white, if it isn't it renders it transparent. Turn off the shader using the parameter to see what I mean. The shader just filters out the gradients.
Sorry for lots of commented-out lines and messy code. I'm too lazy to clean it up. :P
Steady 50 FPS at a hundred Metaballs.
I really like this piece of code, since there is a generated texture you could add a noise to give more "water" appearance
Yep. I'm also gonna work on a shader for the screen, that replaces the white with a specific texture.
Here's one where I encode color across the falloff (dark blue middle, light blue ring, then yellow falloff). Somethings not right that I haven't debugged, you might notice some strange internal artifacts, but it pretty much works. It's slower though... Probably would be better to colorise on a final pass perhaps.
Code tweaked because I realised colorising the source falloff texture was unecessary and caused more calculation
.@spacemonkey I have exported the code to a project and then run it in an iPhone4 with iOS6.1.1 and it appears the next warning:
But it worked!, so weird when the balls are created
I cant understand how are you coloring the balls, where are you defining the "power of yellow"? I would like to change it and try with another layer in multiply mode...
Here it is a video:

@jauxix I think iPhone doesn't support high precision, change the shader line: precision highp float; to precision mediump float; and it might work.
For the coloring it's the colorize and numberize that do the work. Effectively I treat the strength in a pixel as a number from 0.0 - 3.0. It encodes 0.0 - 1.0 as black through to bright yellow, then 1.0 - 2.0 as the yellow declining to half strength while blue comes to full strength, and finally 2.0 to 3.0 as the blue declining to half strength (ie ending in mid grey).
Colorize builds the right color for this in a fairly clear way. The numberize is doing the reverse, but it looks at the various values of the color to decode it. So if the blue is 0.0 then I know it must be in the 0.0 - 1.0 range as the other 2 ranges include blue the strength within that range (decimal part) is then just the red or green value. If the blue has some value, and the red/green is still strong than 0.5 then it must be in 1.0 - 2.0 as that finishes with the red/green just below 0.5 the decimal part is then just blue. Finally if red/green is below 0.5 it must be in the 3rd range 2.0 - 3.0 and the strength will be where the blue is in it's change from full strength to half strength.
I dont understand...so, if we want to turn it like the @Zoyt version here:
http://twolivesleft.com/Codea/Talk/discussion/3200/realistic-2d-water-effect
we need to change the values to encode blue in stead of yellow, in the numberize function or the colorize? >:D<
Hmmm... I described my algorithm, I haven't looked at the other code (and I don't have my ipad here today), but you need to conceptually come up with a colour pattern you like and then think how you can translate from that color pattern to a strength and back. Then those algorithms for translation get put into numberize (color in, strength out) and colorize (strength in, color out).
If you do an image of the kind of color gradient you want to use I'd happily look at it and see if I can implement it.
Ok , @spacemonkey , take a look to this:
http://appaddict.net/wordpress/wp-content/uploads/2011/10/wheres-my-water_449735650_ipad_02.jpg
Hey, @SkyTheCoder, here it is a mod of your code with some color and box2d physics.
Thanks for the code, im using it in 6Dimensions game!
Very Nice @juaxix however, individual drops have weird behavior when they merge/separate...
Yes, we can try with joints each two balls, but it could be weird too, maybe a little noise for every single drop alone
what do you think @Jmv38 ?
Well, must admit i havent understood how your code works. I have seen that when 2 unit balls touch each other they are transformed in a single ball too much bigger. The ideal would be to keep the surface constant (ball1+ball2+junction surface = constant), or better the volume constant, but this is easier to specify it than to code it!
The code is easy to understand, look, the balls are just physic bodies generated with parameters to give them the behaviour of water drops, it is: restitution, friction, damping, linear velocity, ok, to draw these balls we are using a technique with a shader and a texture, you need a mesh to apply the shader, just like the ripple or other samples, we are setting the width and height of the area of the mesh to the whole screen:
this way we can use the (x,y) position of each ball to paint in the virtual space of the texture (with setContext) of the rect attached to the mesh, so, each ball is represented in the texture painted with the image generated of the ball (200*200) -ballTex -
then , you have to use the ADDITIVE blend mode to add all the painted balls to the texture and mix with a background.
Correct me if I'm wrong @SkyTheCoder.
We can improve the separated drops with the method from @Zoyt and @spacemonkey shaders, where they numberize and colorize each fragment and use a constant to smooth the draws.
@juaxix Yep, that's how it works.
Shortened/simplified version:
In setup you generate a texture, a circle with a gradient, starting at invisible and working its way up to white in the center.
In setup you also create a mesh, the size of the screen, and a separate texture for it. Maybe named "screen."
In setup, one more thing, set the blend mode to ADDITIVE. You have to do this AFTER generating the gradient texture, though.
Set the context (setContext(screen)) to the image you created above. You can then use a mesh or sprite() to draw the above texture at the position of every ball.
Set the rendering back to the screen (setContext()), and set the screen-sized mesh's texture to the one we created for it, named screen. The mesh just uses a shader to filter out the gradients. If the brightness is greater than half way, it renders it white. If it isn't, it's transparent.
Haha, that's not too much shorter...
One thing I forgot to mention: The reason it acts as Metaballs is because, with the blend mode ADDITIVE, when two gradient circles merge, the darker parts blend together to qualify as light enough to render white. And the reason why it goes from transparent to white instead of black to white is because if it was black to white I think with the blend mode ADDITIVE it would actually darken the brighter parts on the other gradient circle.
Thank you for your explanations @juaxix and @skythecoder now i understand it. So here is a very little tweek that will make your balls fusion / separation more reallistic, with no extra cost:
.@Jmv38 this water Looks awesome Smooth
thanks
I tried to add at the end of setup:
but this slows down the fps by x5! And it doesnt seem to work. Any idea of what is wrong?
That's weird...you have to set physics.gravity(Gravity) in the draw() function, because it is updated each frame
I'm getting the same FPS value...it might not change anything...
@juaxix i've put it in the draw loop and now direction is ok when i tilt the ipad (of course, silly me!) and the FPS is ok too. => works fine, you are correct.
Very nice. I didn't get time to look back at this, but I think the 2 pass method is much better for real world applications, especially as then you can just worry about coloring once in the final pass. The whole get the graphics processor to do it visually rather than mathematically is sooo nice.
Pity that won't work for 3d metaballs ;-)
Dont be bad @spacemonkey
You are right, we need another 3d metaball shader...i am studying a new way of doing this in 3D. And to improve the method I'm using with physics...
This could be interesting to implement with mesh API:
http://http.developer.nvidia.com/GPUGems3/gpugems3_ch07.html
but the real thing would be to code a Runge Kutta 4 (RK2+RK2):
http://www.niksula.hut.fi/~hkankaan/Homepages/metaballs.html
I'm mixing some terrain generation over a sphere with 3d...
from this:
https://pbs.twimg.com/media/BSsGJUyCEAEE9JY.jpg:large
,to this:
https://pbs.twimg.com/media/BSsGPW5CcAI-Xnb.jpg:large
but if I use normals ( http://www.blackpawn.com/texts/metanormals/ ) it does not work...I would like to mix with metaballs so you can have terrains and 3d water mixed.
Ah, I have found the @SkyTheCoder method in this forum:
https://love2d.org/forums/viewtopic.php?f=5&t=9061
so, no copyright for him as it is copied
hehe
Ah! Runge-Kutta 4th order is music to my ears... :-B
@juaxix, I'm glad you are moving in the direction I'd like to be going myself too: towards simulation of real physical phenomena, like fluids flow, with games' physics engines... 8-> pero me subí tarde al tren (I don't know how to translate this)
(
I look forward to seeing where you get to. Good luck!