So I'm making an electric field simulation in which the user can dynamically create charges through a mouse click.Currently, the electric field is just calculated on the CPU with a pretty bad algorithm on every cell within a grid.
https://i.imgur.com/BFtnkou.gifvTo illustrate the equipotential lines, I have made a shader that computes the potential according to the charge position and q(electric charge).
https://i.imgur.com/hipLStv.gifvThis is the shader code for glslViewer:
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
#define PI 3.14159265
void main( void ) {
vec2 position = ( gl_FragCoord.xy / u_resolution.y );
vec2 mousePos = u_mouse/u_resolution.y;
vec2 r = position - mousePos;
vec2 r2 = position - vec2(0.5, 0.5);
float potential = 0.125/length(r) - 0.125/length(r2);
potential = clamp(potential, -1.0, 1.0);
float cutoff = sin(2.0*PI*10.0*potential);
cutoff = smoothstep(1.0,0.0, 0.5*abs(cutoff)/fwidth(cutoff));
//Maps negative potential to blue
// and positive potential to red
gl_FragColor = cutoff * vec4(potential, 0.0, -potential, 1.0);
}
Quick edit: I know I'll have to modify the shader, obviously.
My problem is: how do I use this shader with a dynamic amount of charges? One of the GLSL paradigms is that the shader can't just have a variable amount of inputs--therefore, I can't just throw in an array of vec3 to represent q and position of every charge and hope the shader knows how to sum up the electric potential without knowing the array size
a priori.
My two cents on solving the problem:
- Use a floating point texture FPT.
- Have two separate shaders:
- One is used for every charge, and takes the charge's q and position as inputs.It outputs a "voltage" created by the charge and adds that value to the FPT(superposition principle).The iteration over every charge is done in a for loop, inside the application's update() method or something like that.
- The other is used as a final step, to implement the clamping for very big potentials(in absolute value), the cutoff to make the equipotential lines and, lastly, to map negative values to blue and positive ones to red.
- Render the final result to a sprite and draw it.
That all sounds great in theory, but my attempts at implementing that were all failures.Namely, I don't think I understand the openGL functions, as I'm mostly inexperienced with pure openGL.