MetaBalls from shaderToy

Hello,
I’m trying to use this metaballs shaders found on shaderToy with no results. I’ve got a black screen with this error :

OpenGL error 1282 at bot endDraw(): invalid operation

I adapt a little bit the code but I’m not a shader master.
Here’s the code that I would like to put in a PGraphics as a layer.
Thanks for help

#define PROCESSING_COLOR_SHADER
uniform vec3  iResolution;
uniform vec2 iMouse;
uniform float iTime;
uniform	float divide;
uniform	float intensity = 0.2;

uniform	float coordX;
uniform	float coordY;
	
uniform	float ball1x;
uniform	float ball1y;
uniform	float ball1z;
	
uniform	float ball2x;
uniform	float ball2y;
uniform	float ball2z;
	
uniform	float ball3x;
uniform	float ball3y;
uniform	float ball3z;

uniform	vec3 ball1;
uniform	vec3 ball2;
uniform	vec3 ball3;

uniform	float sum = 0.0;
void mainImage( out vec4 fragColor, in vec2 fragCoord );

void main() {
    mainImage(gl_FragColor,gl_FragCoord.xy);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	// Hold the mouse and drag to adjust  
	
	float ratio = iResolution.y / iResolution.x;
	float divider = float(iMouse.y / iResolution.x * 10.0) + 1.0;
	float intensity = float(iMouse.x / iResolution.y * 10.0) + 1.0;

	float coordX = fragCoord.x / iResolution.x;
	float coordY = fragCoord.y / iResolution.x;
	
	float ball1x = sin(iTime * 2.1) * 0.5 + 0.5;
	float ball1y = cos(iTime * 1.0) * 0.5 + 0.5;
	float ball1z = sin(iTime * 2.0) * 0.1 + 0.2;
	
	float ball2x = sin(iTime * 1.0) * 0.5 + 0.5;
	float ball2y = cos(iTime * 1.8) * 0.5 + 0.5;
	float ball2z = cos(iTime * 2.0) * 0.1 + 0.2;
	
	float ball3x = sin(iTime * 0.7) * 0.5 + 0.5;
	float ball3y = cos(iTime * 1.5) * 0.5 + 0.5;
	float ball3z = cos(iTime * 1.0) * 0.1 + 0.2;

	vec3 ball1 = vec3(ball1x, ball1y * ratio, ball1z);
	vec3 ball2 = vec3(ball2x, ball2y * ratio, ball2z);
	vec3 ball3 = vec3(ball3x, ball3y * ratio, ball3z);

	float sum = 0.0;
	sum += ball1.z / distance(ball1.xy, vec2(coordX, coordY));
	sum += ball2.z / distance(ball2.xy, vec2(coordX, coordY));
	sum += ball3.z / distance(ball3.xy, vec2(coordX, coordY));
	
    sum = pow(sum / intensity, divider);
	
	fragColor = vec4(sum * 0.2, sum * 0.2, sum * 0.4, 1.0);
}
PShader metaBalls;
void setup() {
  size(896, 768, P2D);
  noStroke();
  metaBalls = loadShader("metaBalls.glsl");
  metaBalls.set("iResolution", float(width), float(height));
}
void draw() {
  metaBalls.set("iTime", millis() / 500.0);  
  shader(metaBalls); 
 rect(0, 0, width, height);
}

Hi @matheplica ,

Seems the issue was already encountered before :wink: :

https://forum.processing.org/two/discussion/3155/opengl-error-1282-at-top-enddraw-invalid-operation

Are your gpu drivers up to date?

I hesitate to say this but “it’s not how it works”. You are mixing up different GLSL versions, and you need to adapt it to the one that Processing supports. First, always start with a very simple example

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

varying vec4 vertTexCoord;

void main() {
  gl_FragColor = vec4(vertTexCoord.xy, 1.0,1.0);
}
PShader metaBalls;
void setup() {
  size(896, 768, P2D);
  noStroke();
  metaBalls = loadShader("metaBalls.glsl");
  metaBalls.set("iResolution", float(width), float(height));
}
void draw() {
  metaBalls.set("iTime", millis() / 500.0);  
  metaBalls.set("iMouse", mouseX, mouseY);  
  filter(metaBalls); 
}

if you know the shader works, then add things to it

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

varying vec4 vertTexCoord;

uniform vec2 iResolution;
uniform vec2 iMouse;
uniform float iTime;

uniform float sum = 0.0;

void main() {
	// Hold the mouse and drag to adjust  
	
	float ratio = iResolution.y / iResolution.x;
	float divider = float(iMouse.y / iResolution.x * 10.0) + 1.0;
	float intensity = float(iMouse.x / iResolution.y * 10.0) + 1.0;

	float coordX = vertTexCoord.x;// / iResolution.x;
	float coordY = vertTexCoord.y;// / iResolution.x;
	
	float ball1x = sin(iTime * 2.1) * 0.5 + 0.5;
	float ball1y = cos(iTime * 1.0) * 0.5 + 0.5;
	float ball1z = sin(iTime * 2.0) * 0.1 + 0.2;
	
	float ball2x = sin(iTime * 1.0) * 0.5 + 0.5;
	float ball2y = cos(iTime * 1.8) * 0.5 + 0.5;
	float ball2z = cos(iTime * 2.0) * 0.1 + 0.2;
	
	float ball3x = sin(iTime * 0.7) * 0.5 + 0.5;
	float ball3y = cos(iTime * 1.5) * 0.5 + 0.5;
	float ball3z = cos(iTime * 1.0) * 0.1 + 0.2;

	vec3 ball1 = vec3(ball1x, ball1y * ratio, ball1z);
	vec3 ball2 = vec3(ball2x, ball2y * ratio, ball2z);
	vec3 ball3 = vec3(ball3x, ball3y * ratio, ball3z);

	float sum = 0.0;
	sum += ball1.z / distance(ball1.xy, vec2(coordX, coordY));
	sum += ball2.z / distance(ball2.xy, vec2(coordX, coordY));
	sum += ball3.z / distance(ball3.xy, vec2(coordX, coordY));
	
  sum = pow(sum / intensity, divider);
	
	gl_FragColor = vec4(sum * 0.2, sum * 0.2, sum * 0.4, 1.0);
}

by the way I get endDraw error but it seems it’s not affecting the result. Also in Processing frag coord is already normalized so you don’t need to divide it by the resolution parameter.

1 Like

Did you know there is a way to use a wrapper around a shaderToy shader, see Raphaël de Courville on github.


I have created a similar tool for JRubyArt see above sketch running from atom. Note the beauty of using atom as an editor is it supports glsl (and processing just use script tool to run sketches…

2 Likes

Once you have a running sketch then you can if you wish convert sketch and shader code as follows:-

attr_reader :last_mouse_position, :mouse_click_state, :mouse_dragged, :shader_t
attr_reader :start

def settings
  size(640, 360, P2D)
end

def setup
  sketch_title 'Shadertoy Metaballs'
  @previous_time = 0.0
  @mouse_dragged = false
  @mouse_click_state = 0.0
  # Load the shader file from the "data" folder
  @shader_t = load_shader(data_path('metaballs.glsl'))
  # Assume the dimension of the window will not change over time
  shader_t.set('iResolution', width.to_f, height.to_f, 0.0)
  @last_mouse_position = Vec2D.new(mouse_x, mouse_y)
  @start = java.lang.System.current_time_millis
end

def draw
  # shader playback time (in seconds)
  current_time = (java.lang.System.current_time_millis - start) / 1000.0
  shader_t.set('iTime', current_time)
  if mouse_pressed?
    @last_mouse_position = Vec2D.new(mouse_x, mouse_y)
    @mouse_click_state = 1.0
  else
    @mouse_click_state = 0.0
  end
  shader_t.set('iMouse', last_mouse_position.x, last_mouse_position.y, mouse_click_state, mouse_click_state)
  # Apply the specified shader to any geometry drawn from this point
  shader(shader_t)
  # Draw the output of the shader onto a rectangle that covers the whole viewport.
  rect(0, 0, width, height)
end

And shader

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

// ----------------------
// SHADERTOY UNIFORMS  -
// ----------------------

uniform vec3      iResolution;           // viewport resolution (in pixels)
uniform float     iTime;                 // shader playback time (in seconds)
uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click

void main()
{
	// Hold the mouse and drag to adjust

	float ratio = iResolution.y / iResolution.x;
	float divider = float(iMouse.x / iResolution.x * 10.0) + 1.0;
	float intensity = float(iMouse.y / iResolution.y * 10.0) + 1.0;

	float coordX = gl_FragCoord.x / iResolution.x;
	float coordY = gl_FragCoord.y / iResolution.x;

	float ball1x = sin(iTime * 2.1) * 0.5 + 0.5;
	float ball1y = cos(iTime * 1.0) * 0.5 + 0.5;
	float ball1z = sin(iTime * 2.0) * 0.1 + 0.2;

	float ball2x = sin(iTime * 1.0) * 0.5 + 0.5;
	float ball2y = cos(iTime * 1.8) * 0.5 + 0.5;
	float ball2z = cos(iTime * 2.0) * 0.1 + 0.2;

	float ball3x = sin(iTime * 0.7) * 0.5 + 0.5;
	float ball3y = cos(iTime * 1.5) * 0.5 + 0.5;
	float ball3z = cos(iTime * 1.0) * 0.1 + 0.2;

	vec3 ball1 = vec3(ball1x, ball1y * ratio, ball1z);
	vec3 ball2 = vec3(ball2x, ball2y * ratio, ball2z);
	vec3 ball3 = vec3(ball3x, ball3y * ratio, ball3z);

	float sum = 0.0;
	sum += ball1.z / distance(ball1.xy, vec2(coordX, coordY));
	sum += ball2.z / distance(ball2.xy, vec2(coordX, coordY));
	sum += ball3.z / distance(ball3.xy, vec2(coordX, coordY));

    sum = pow(sum / intensity, divider);

	gl_FragColor = vec4(sum * 0.2, sum * 0.2, sum * 0.4, 1.0);
}

Similar to @micuat, but I don’t get OpenGl error, might be due to my using vec4 for iMouse see shadertoy howto.

also PixelFlow supports Shadertoy code:

Ok, thanks for all answers, it’s good to see the motivation of the community.
Hope it help other shaders newbies.
Thanks !