In this recipe, we will learn how we can implement organic looking objects called metaballs.
In this recipe, we are going to use the code base from the Applying repulsion and attraction forces recipe in Chapter 5, Building Particle Systems.
We will implement the metaballs' rendering using a shader program. Perform the following steps to do so:
assets
folder with a name, passThru_vert.glsl
, and put the following code snippet inside it:void main() { gl_Position = ftransform(); gl_TexCoord[0] = gl_MultiTexCoord0; gl_FrontColor = gl_Color; }
assets
folder with a name, mb_frag.glsl
, and put the following code snippet inside it:#version 120 uniform vec2 size; uniform int num; uniform vec2 positions[100]; uniform float radius[100]; void main(void) { // Get coordinates vec 2 texCoord = gl_TexCoord[0].st; vec4 color = vec4(1.0,1.0,1.0, 0.0); float a = 0.0; int i; for(i = 0; i<num; i++) { color.a += (radius[i] / sqrt( ((texCoord.x*size.x)- positions[i].x)*((texCoord.x*size.x)-positions[i].x) + ((texCoord.y*size.y)- positions[i].y)*((texCoord.y*size.y)-positions[i].y) ) ); } // Set color gl_FragColor = color; }
#include "cinder/Utilities.h" #include "cinder/gl/GlslProg.h"
GlslProg
object for our GLSL shader program.gl::GlslProg mMetaballsShader;
setup
method, change the values of repulsionFactor
and numParticle
.repulsionFactor = -40.f; int numParticle = 10;
setup
method, load our GLSL shader program, as follows:mMetaballsShader = gl::GlslProg( loadAsset("passThru_vert.glsl"), loadAsset("mb_frag.glsl") );
draw
method, which looks like the following code snippet:void MainApp::draw() { gl::enableAlphaBlending(); gl::clear( Color::black() ); int particleNum = mParticleSystem.particles.size(); mMetaballsShader.bind(); mMetaballsShader.uniform( "size", Vec2f(getWindowSize()) ); mMetaballsShader.uniform( "num", particleNum ); for (int i = 0; i<particleNum; i++) { mMetaballsShader.uniform( "positions[" + toString(i) + "]", mParticleSystem.particles[i]->position ); mMetaballsShader.uniform( "radius[" + toString(i) + "]", mParticleSystem.particles[i]->radius ); } gl::color(Color::white()); gl::drawSolidRect( getWindowBounds() ); mMetaballsShader.unbind(); }
The most important part of this recipe is the fragment shader program mentioned in step 2. The shader generates texture with rendered metaballs based on the positions and radius passed to the shader from our particle system. In step 7, you can find out how to pass information to the shader program. We are using setMatricesWindow
and setViewport
to set OpenGL for drawing.
3.16.79.147