Skip to content

Commit 0bf54bf

Browse files
committed
Added CustomBlend example
1 parent 0dcaa8e commit 0bf54bf

7 files changed

Lines changed: 204 additions & 0 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* Custom Blend
3+
*
4+
* The OpenGL-based renderers (P2D and P3D) only support some of the
5+
* blending modes available in the default renderer. The reason for this
6+
* is that the blend equations in OpenGL allow for combinations of the
7+
* form dest_factor * dest_color + src_factor * src_color of the source and
8+
* destination colors (see this page http://www.opengl.org/wiki/Blending
9+
* for an extensive discussion of blending in OpenGL).
10+
* Complex blending modes typically available in photo editing tools,
11+
* like hard light or dodge, cannot be modeled with those equations.
12+
* However, we can implement virtually any blending math directly in the
13+
* fragment shader.
14+
*
15+
* This example shows how custom blend shaders can be loaded and used in
16+
* Processing.
17+
* For detailed information on how to implement Photoshop-like blending modes,
18+
* check the following pages (a bit old but still useful):
19+
* http://www.pegtop.net/delphi/articles/blendmodes/index.htm
20+
* http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/
21+
*
22+
*/
23+
24+
PImage destImage;
25+
PImage srcImage;
26+
PShader dodge;
27+
PShader burn;
28+
PShader overlay;
29+
PShader difference;
30+
31+
void setup() {
32+
size(640, 360, P2D);
33+
destImage = loadImage("leaves.jpg");
34+
srcImage = loadImage("moonwalk.jpg");
35+
36+
initShaders();
37+
}
38+
39+
void draw() {
40+
background(0);
41+
42+
shader(dodge);
43+
drawOutput(0, 0, width/2, height/2);
44+
shader(burn);
45+
drawOutput(width/2, 0, width/2, height/2);
46+
shader(overlay);
47+
drawOutput(0, height/2, width/2, height/2);
48+
shader(difference);
49+
drawOutput(width/2, height/2, width/2, height/2);
50+
51+
noLoop();
52+
}
53+
54+
void initShaders() {
55+
dodge = loadShader("dodge.glsl");
56+
burn = loadShader("burn.glsl");
57+
overlay = loadShader("overlay.glsl");
58+
difference = loadShader("difference.glsl");
59+
60+
// The names destination and source come from the OpenGL terminology:
61+
// destination from the image already in the framebuffer, or "base layer",
62+
// and source for the image that will be blended into the framebuffer, or
63+
// "blend layer":
64+
dodge.set("destSampler", destImage);
65+
dodge.set("srcSampler", srcImage);
66+
burn.set("destSampler", destImage);
67+
burn.set("srcSampler", srcImage);
68+
overlay.set("destSampler", destImage);
69+
overlay.set("srcSampler", srcImage);
70+
difference.set("destSampler", destImage);
71+
difference.set("srcSampler", srcImage);
72+
73+
// We set the sizes of de st and src images, and the rectangular areas
74+
// from the images that we will use for blending:
75+
dodge.set("destSize", 640, 360);
76+
dodge.set("destRect", 100, 50, 200, 200);
77+
burn.set("destSize", 640, 360);
78+
burn.set("destRect", 100, 50, 200, 200);
79+
overlay.set("destSize", 640, 360);
80+
overlay.set("destRect", 100, 50, 200, 200);
81+
difference.set("destSize", 640, 360);
82+
difference.set("destRect", 100, 50, 200, 200);
83+
84+
dodge.set("srcSize", 640, 360);
85+
dodge.set("srcRect", 0, 0, 640, 360);
86+
burn.set("srcSize", 640, 360);
87+
burn.set("srcRect", 0, 0, 640, 360);
88+
overlay.set("srcSize", 640, 360);
89+
overlay.set("srcRect", 0, 0, 640, 360);
90+
difference.set("srcSize", 640, 360);
91+
difference.set("srcRect", 0, 0, 640, 360);
92+
}
93+
94+
void drawOutput(float x, float y, float w, float h) {
95+
pushMatrix();
96+
translate(x, y);
97+
noStroke();
98+
beginShape(QUAD);
99+
// Although we are not associating a texture to
100+
// this shape, the uv coordinates will be stored
101+
// anyways so they can be used in the fragment
102+
// shader to access the destination and source
103+
// images.
104+
vertex(0, 0, 0, 0);
105+
vertex(w, 0, 1, 0);
106+
vertex(w, h, 1, 1);
107+
vertex(0, h, 0, 1);
108+
endShape();
109+
popMatrix();
110+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
uniform sampler2D destSampler;
2+
uniform sampler2D srcSampler;
3+
4+
uniform ivec2 destSize;
5+
uniform ivec4 destRect;
6+
7+
uniform ivec2 srcSize;
8+
uniform ivec4 srcRect;
9+
10+
varying vec4 vertTexCoord;
11+
12+
void main() {
13+
vec2 st = vertTexCoord.st;
14+
15+
vec2 dest = vec2(destRect.xy) / vec2(destSize) + st * vec2(destRect.zw) / vec2(destSize);
16+
vec2 src = vec2(srcRect.xy) / vec2(srcSize) + st * vec2(srcRect.zw) / vec2(srcSize);
17+
18+
vec3 destColor = texture2D(destSampler, dest).rgb;
19+
vec3 srcColor = texture2D(srcSampler, src).rgb;
20+
21+
gl_FragColor = vec4(1.0 - (1.0 - destColor) / srcColor, 1.0);
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
uniform sampler2D destSampler;
2+
uniform sampler2D srcSampler;
3+
4+
uniform ivec2 destSize;
5+
uniform ivec4 destRect;
6+
7+
uniform ivec2 srcSize;
8+
uniform ivec4 srcRect;
9+
10+
varying vec4 vertTexCoord;
11+
12+
void main() {
13+
vec2 st = vertTexCoord.st;
14+
15+
vec2 dest = vec2(destRect.xy) / vec2(destSize) + st * vec2(destRect.zw) / vec2(destSize);
16+
vec2 src = vec2(srcRect.xy) / vec2(srcSize) + st * vec2(srcRect.zw) / vec2(srcSize);
17+
18+
vec3 destColor = texture2D(destSampler, dest).rgb;
19+
vec3 srcColor = texture2D(srcSampler, src).rgb;
20+
21+
gl_FragColor = vec4(abs(srcColor - destColor), 1.0);
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
uniform sampler2D destSampler;
2+
uniform sampler2D srcSampler;
3+
4+
uniform ivec2 destSize;
5+
uniform ivec4 destRect;
6+
7+
uniform ivec2 srcSize;
8+
uniform ivec4 srcRect;
9+
10+
varying vec4 vertTexCoord;
11+
12+
void main() {
13+
vec2 st = vertTexCoord.st;
14+
15+
vec2 dest = vec2(destRect.xy) / vec2(destSize) + st * vec2(destRect.zw) / vec2(destSize);
16+
vec2 src = vec2(srcRect.xy) / vec2(srcSize) + st * vec2(srcRect.zw) / vec2(srcSize);
17+
18+
vec3 destColor = texture2D(destSampler, dest).rgb;
19+
vec3 srcColor = texture2D(srcSampler, src).rgb;
20+
21+
gl_FragColor = vec4(destColor / (1.0 - srcColor), 1.0);
22+
}
42.2 KB
Loading
117 KB
Loading
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
uniform sampler2D destSampler;
2+
uniform sampler2D srcSampler;
3+
4+
uniform ivec2 destSize;
5+
uniform ivec4 destRect;
6+
7+
uniform ivec2 srcSize;
8+
uniform ivec4 srcRect;
9+
10+
varying vec4 vertTexCoord;
11+
12+
void main() {
13+
vec2 st = vertTexCoord.st;
14+
15+
vec2 dest = vec2(destRect.xy) / vec2(destSize) + st * vec2(destRect.zw) / vec2(destSize);
16+
vec2 src = vec2(srcRect.xy) / vec2(srcSize) + st * vec2(srcRect.zw) / vec2(srcSize);
17+
18+
vec3 destColor = texture2D(destSampler, dest).rgb;
19+
vec3 srcColor = texture2D(srcSampler, src).rgb;
20+
21+
float luminance = dot(vec3(0.2126, 0.7152, 0.0722), destColor);
22+
23+
if (luminance < 0.5) {
24+
gl_FragColor = vec4(2.0 * destColor * srcColor, 1.0);
25+
} else {
26+
gl_FragColor = vec4(1.0 - 2.0 * (1.0 - destColor) * (1.0 - srcColor), 1);
27+
}
28+
}

0 commit comments

Comments
 (0)