Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Help with general approach  (Read 240 times)

0 Members and 1 Guest are viewing this topic.

redbullmarky

  • Newbie
  • *
  • Posts: 2
    • View Profile
Help with general approach
« on: December 28, 2024, 08:02:19 pm »
Hey, all!
I'm hoping to get a little bit of help with *approach* to something. I'm pretty new to SFML (and more involved graphics programming/OpenGL/etc in general) though have been coding in various languages for ~30years.

To "simplify" my case, let's just say:

- I have two circle shapes, both filled with a colour, and with a 2px black "cartoon" border.
- When the two circles collide, I want them to join (based on an arbitrary distance constraint). I'm imagining some kind of inward curve that joins the two closest outer points of the circles on each side (like you might expect two droplets of liquid to merge when they get close). Any borders within the combined shape would cease to exist, but...there'd still be the overall outer border.
- These (with certain conditions) could be separated too back into their original shapes (but that's for more context, not sure it's relevant yet to the problem)

I'm thinking that I cannot use the regular SFML circle shapes. These circles will be soft-bodies. I'm thinking that maybe shaders come into play (which I have no experience with). I've also seen suggestions mentioning things like stencil buffers, etc - again, also alien to me!

It's the sort of thing that (with plotting individual pixels in code) I could probs work out, but as the shapes that combine are soft-bodies, I want to at least *approach* things in the right way so things don't choke.

I don't necessarily need code, but suggestions such as:

- "I would use xyz library / look into xyz to deal with the combining of shapes into a single mesh"
- "SFML definitely cannot do this out of the box"
- "You need a shader to outline the overall shape"
- "Here's a demo of two outlined objects combining and coming together in a squidgy mess" (in ANY language)

And so on. Because at least I can bark up the right trees on my quest to figure things out and ask better questions :)

Cheers & happy new year, all.
Mark


kojack

  • Sr. Member
  • ****
  • Posts: 352
  • C++/C# game dev teacher.
    • View Profile
Re: Help with general approach
« Reply #1 on: December 28, 2024, 11:01:10 pm »
This sounds like what would traditionally be called metaballs.

How I'd go about it is using shaders with a technique called SDF (Signed Distance Field). Basically it's a mathematical way of determining if a pixel is inside or outside of a shape, and how far. For example if you get an answer of 4, that means 4 pixels away from a shape, 0 means on the surface and -3 would be 3 pixels inside.
That makes it very easy to draw outlines.
The great thing about SDFs is you can combine them and distort them, such as adding the effect you want.

Have a look here for the formulas. They are actually quite small.
https://iquilezles.org/articles/distfunctions2d/  - look at the 2D circle function near the top.
https://iquilezles.org/articles/distfunctions/ - look at the smoothUnion function near the bottom. This page is 3D, but some of the functions like smoothUnion work the same, they deal with distances instead of coordinates.

I made a little shadertoy (great website, by the same guy as the articles I linked above) example.
Go to shadertoy.com and enter this text into the source box:
// Distance to a circle
float sdCircle( vec2 p, float r )
{
    return length(p) - r;
}

// Smoothly combine 2 shapes using their distances.
float opSmoothUnion( float d1, float d2, float k )
{
    float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
    return mix( d2, d1, h ) - k*h*(1.0-h);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Shadertoy passes in pixels instead of UV like normal shaders, so divide by res to get a 0 to 1.0 range.
    vec2 uv = fragCoord/iResolution.xy;

    // Circle positions and radii.
    vec2 c1 = vec2(0.3,0.3);
    vec2 c2 = vec2(0.6,0.4);
    float r1 = 0.15;
    float r2 = 0.15;
   
    // Distances to the circles. The function wants circle relative positions, so do uv - circle pos.
    float d1 = sdCircle(uv-c1, r1);
    float d2 = sdCircle(uv-c2, r2);
   
    // Combine the two distances to do a smooth union. d is now the distance to either shape, including the smooth part between.
    float d = opSmoothUnion(d1,d2,0.15);

    // Set the colour to be dark green for the background, white inside of the circles and black around the edge.
    vec3 col = vec3(0,0.5,0);  // background is default
    if(d<-0.01)
        col=vec3(1,1,1); // inside of circles
    else if(d<=0.0)
        col=vec3(0,0,0); // in the edge

    // Output to screen
    fragColor = vec4(col,1.0);
}

That won't be 100% SFML shader compatible (should be almost right though), but will let you experiment with the look of the technique.

« Last Edit: December 28, 2024, 11:53:23 pm by eXpl0it3r »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11066
    • View Profile
    • development blog
    • Email
Re: Help with general approach
« Reply #2 on: December 28, 2024, 11:56:50 pm »
What kojack said.

Also this is not possible with SFML shapes.
You might be able to calculate the math for a vertex array on CPU side, but you're likely better off with shaders on the GPU side.
Official FAQ: https://www.sfml-dev.org/faq/
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

redbullmarky

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Help with general approach
« Reply #3 on: December 29, 2024, 10:45:54 am »
That is exactly the kind of thing I'm after! Thank you so much for the term and particularly the examples!

As a follow-up - would I be right in thinking these would be useful for simple/symmetrical shapes, rather than perhaps an arbitrary shape passed in as a Vertex Array? Looking through the shape examples in the link above, most of them have a predictable distance calc due to the fixed nature of the shape.
But because generally the plan is to be stretching these things via PBD, I'd need control over the individual vertices that make up the shape.

The above techniques/examples you linked will certainly come into play for certain things I have planned though for sure!

Mark