# blendMode(DIFFERENCE) in P2D / P3D

**URL:** https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541
**Category:** Gallery
**Created:** [February 4, 2020, 10:32am UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541 "2020-02-04T10:32:07Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![hamoid](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hamoid/32/58_2.png) [@hamoid](https://discourse.processing.org/u/hamoid)
#### Post date: [February 4, 2020, 10:32am UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541/1 "2020-02-04T10:32:07Z")

</div>

This image is very easy to do using `blendMode(DIFFERENCE)`.

 ![Screenshot from 2020-02-04 11-28-35](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/3/30cfae5cc126a8ff8f53b871b93a3a903a8be9d8.png)  
Unfortunately it’s not supported in P2D / P3D, so here a workaround in case someone needs this:

```auto
import com.jogamp.opengl.*;
com.jogamp.opengl.GL3 gl;
void setup() {
  size(600, 600, P2D);
  noStroke();
  smooth(8);
  fill(255);
  
  // DIFFERENCE is not supported in P2D / P3D
  //blendMode(DIFFERENCE);
  
  gl = GLContext.getCurrentGL().getGL3();
}

void draw() {
  background(255);
  // This provides blendMode(DIFFERENCE) in P2D / P3D
  gl.glEnable(GL3.GL_BLEND);
  gl.glBlendFunc(GL3.GL_ONE_MINUS_DST_COLOR, GL3.GL_ZERO);
  
  for (int i = 0; i < 20; i++) {
    float sz = 50 + (i % 4) * 50;
    float x = width * noise(i * 0.527 + millis() * 0.0003);
    float y = height * noise(i * 0.729 + millis() * 0.0001);
    circle(x, y, sz);
  }
}

```

_ported from [openFrameworks](https://forum.openframeworks.cc/t/blend-mode-invertcolor/34415/8)_

---

<div class="post-metadata">

### Author: ![monkstone](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/monkstone/32/64_2.png) [@monkstone](https://discourse.processing.org/u/monkstone)
#### Post date: [February 4, 2020, 11:13am UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541/2 "2020-02-04T11:13:14Z")

</div>

That’s excellent, here’s the same sketch translated for JRubyArt:-

```ruby
java_import 'com.jogamp.opengl.GL3'
java_import 'com.jogamp.opengl.GLContext'

attr_reader :gl
def setup
  sketch_title 'Blend Mode Difference P2D'
  noStroke
  fill(255)
  # DIFFERENCE is not supported in P2D / P3D
  # blendMode(DIFFERENCE)
  @gl = GLContext.getCurrentGL.getGL3
end

def draw
  background(255)
  # This provides blendMode(DIFFERENCE) in P2D / P3D
  gl.glEnable(GL3::GL_BLEND)
  gl.glBlendFunc(GL3::GL_ONE_MINUS_DST_COLOR, GL3::GL_ZERO)
  20.times do |i|
    sz = 50 + (i % 4) * 50
    x = width * noise(i * 0.527 + millis * 0.0003)
    y = height * noise(i * 0.729 + millis * 0.0001)
    circle(x, y, sz)
  end
end

def settings
  size(600, 600, P2D)
  smooth(8)
end

```

---

<div class="post-metadata">

### Author: ![monkstone](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/monkstone/32/64_2.png) [@monkstone](https://discourse.processing.org/u/monkstone)
#### Post date: [February 5, 2020, 12:00pm UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541/3 "2020-02-05T12:00:22Z")

</div>

The RaspberryPI only officially supports GL2 (this may change for RaspberryPI4) anyway I managed to get sketch with PiCrate on RaspberryPI4:-

```ruby
 # frozen_string_literal: true

require 'picrate'

class BlendModeSketch < Processing::App
  java_import 'com.jogamp.opengl.GL3'
  java_import 'com.jogamp.opengl.GLContext'

  attr_reader :gl
  def setup
    sketch_title 'Blend Mode Difference P2D'
    noStroke
    fill(255)
    # DIFFERENCE is not supported in P2D / P3D
    # blendMode(DIFFERENCE)
    @gl = GLContext.getCurrentGL.getGL2
  end

  def draw
    background(255)
    # This provides blendMode(DIFFERENCE) in P2D / P3D
    gl.glEnable(GL3::GL_BLEND)
    gl.glBlendFunc(GL3::GL_ONE_MINUS_DST_COLOR, GL3::GL_ZERO)
    20.times do |i|
      sz = 50 + (i % 4) * 50
      x = width * noise(i * 0.527 + millis * 0.0003)
      y = height * noise(i * 0.729 + millis * 0.0001)
      circle(x, y, sz)
    end
  end

  def settings
    size 600, 600, P3D
    smooth 8
  end
end

BlendModeSketch.new

```

 ![blend_mode](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/1/1d06a9e6c7706c2379e25d1b604f5b1ee3811b9d.jpeg)

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [February 5, 2020, 12:14pm UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541/4 "2020-02-05T12:14:26Z")

</div>

That’s not a true DIFFERENCE blend though. You can only achieve that with shaders.

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [February 5, 2020, 6:48pm UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541/5 "2020-02-05T18:48:30Z")

</div>

I’ve refactored @hamoid’s Java Mode sketch just a little: ☕

```auto
// Discourse.Processing.org/t/blendmode-difference-in-p2d-p3d/17541/5
// Forum.OpenFrameworks.cc/t/blend-mode-invertcolor/34415/8

// Hamoid (2020/Feb/05)

import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GL3;

//static final float[] FS = { .527, 3e-4, .729, 1e-4 };

static final String RENDER = P2D;
static final color C = #00FFFF; // cyan

static final int
  SMOOTH = 8, BLENDER = DIFFERENCE, 
  BALLS = 20, DIAM = 50, 

  SFACTOR = GL3.GL_ONE_MINUS_DST_COLOR, 
  DFACTOR = GL3.GL_ZERO;

void setup() {
  size(600, 600, RENDER);
  smooth(SMOOTH);

  fill(C);
  noStroke();

  blendMode(BLENDER); // DIFFERENCE isn't supported by OPENGL

  GLContext.getCurrentGL().getGL3().glBlendFunc(SFACTOR, DFACTOR);
}

void draw() {
  background(C);

  final int w = width, h = height, m = millis();

  for (int i = 0; i < BALLS; ++i) {
    final float
      x = noise(.527 * i + 3e-4 * m) * w, 
      y = noise(.729 * i + 1e-4 * m) * h, 
      d = i % 4 * DIAM + DIAM;

    circle(x, y, d);
  }
}

```

And then made a Python Mode version out of it: 🐍

```auto
# Discourse.Processing.org/t/blendmode-difference-in-p2d-p3d/17541/5
# Forum.OpenFrameworks.cc/t/blend-mode-invertcolor/34415/8

# Hamoid (2020/Feb/05)

from com.jogamp.opengl import GLContext, GL3

FS = .527, 3e-4, .729, 1e-4

RENDER, SMOOTH, BLENDER = P2D, 8, DIFFERENCE

BALLS, DIAM, C = 20, 50, 0xffFFFF00 # yellow
BALLS_RANGE = tuple(range(BALLS))

SFACTOR, DFACTOR = GL3.GL_ONE_MINUS_DST_COLOR, GL3.GL_ZERO

def setup():
    size(600, 600, RENDER)
    smooth(SMOOTH)

    fill(C), noStroke()
    blendMode(BLENDER) # DIFFERENCE isn't supported by OPENGL

    GLContext.getCurrentGL().getGL3().glBlendFunc(SFACTOR, DFACTOR)

def draw():
    background(C)

    w = width
    h = height
    m = millis()

    for i in BALLS_RANGE:
        x = noise(FS[0] * i + FS[1] * m) * w
        y = noise(FS[2] * i + FS[3] * m) * h
        d = i % 4 * DIAM + DIAM

        circle(x, y, d)

```

---

<div class="post-metadata">

### Author: ![hamoid](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hamoid/32/58_2.png) [@hamoid](https://discourse.processing.org/u/hamoid)
#### Post date: [February 6, 2020, 2:56pm UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541/6 "2020-02-06T14:56:08Z")

</div>

Assuming JAVA2D provides “True DIFFERENCE ®” 😛 , I see what you mean:

JAVA2D DIFFERENCE

 ![java2D](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/f/f7820760d09720f6fa5bb4de1405b18fdfce4c28.png)

P2D difference with glBlendFunc

 ![P2D](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/2/239702142451ab5df958c0f53635f73ee13b31cb.png)

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [February 6, 2020, 4:30pm UTC](https://discourse.processing.org/t/blendmode-difference-in-p2d-p3d/17541/7 "2020-02-06T16:30:47Z")

</div>

Yes, DIFFERENCE should be `abs(src - dst)`. The Java2D version actually uses the code from PImage [here](https://github.com/processing/processing/blob/master/core/src/processing/core/PImage.java#L2672). It’s mostly right, although as Processing doesn’t use premultiplied alpha (unlike the extension in PraxisLIVE) most blending is a bit off when there’s transparent surfaces involved.

The equivalent software code in PraxisLIVE is [here](https://github.com/praxis-live/praxis/blob/master/praxis.video.render/src/org/praxislive/video/render/ops/RGBComposite.java#L232) if you’re interested. And the shader support for DIFFERENCE blending is [here](https://github.com/praxis-live/praxis/blob/master/praxis.video.pgl/src/org/praxislive/video/pgl/ops/PGLBlitOp.java#L190). The latter shows how to use multiple PImage to do this, but also requires my extended PShader class that sets up the correct uniforms for additional texture inputs.

Unfortunately, doing what you’re doing above would have a lot of overhead with the shader approach as you’d have to keep swapping what surface you’re drawing to.

Incidentally, there’s an interesting slide set from an nvidia engineer on OpenGL, blend modes and premultiplied alpha here - [https://www.slideshare.net/Mark\_Kilgard/blend-modes-for-opengl](https://www.slideshare.net/Mark_Kilgard/blend-modes-for-opengl)
