# Chaining GLSL frag shaders

**URL:** <https://discourse.processing.org/t/chaining-glsl-frag-shaders/28006>\
**Category:** Coding Questions\
**Created:** [February 22, 2021, 6:48pm UTC](https://discourse.processing.org/t/chaining-glsl-frag-shaders/28006 "2021-02-22T18:48:07Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![rikitiki](https://avatars.discourse-cdn.com/v4/letter/r/65b543/32.png) [@rikitiki](https://discourse.processing.org/u/rikitiki)\
**Post date:** [February 22, 2021, 6:48pm UTC](https://discourse.processing.org/t/chaining-glsl-frag-shaders/28006/1 "2021-02-22T18:48:07Z")

</div>

Hello,

I’m attempting to chain some very simple fragment shaders and I’m unsure what I’m doing wrong. I’m following the concept outlined in the readme posted by cansik in this bloom filter:

[https://github.com/cansik/processing-bloom-filter](https://github.com/cansik/processing-bloom-filter)

There are a couple of issues here:

1 - The image is upside down. I have no idea why this would be, since I’m not doing any transforms. I would suspect it’s because of some coordinate system snafu, but I’m unsure where I went wrong.  
2 - The brightness control (which is earlier in the chain) does not work at all.

If I set them up individually, they work fine, but it seems to be the chaining that does not work. Any help would be much appreciated.

Here is my Processing code:

```auto
PGraphics imageView;
PImage previewImage;

PGraphics canvas;
PGraphics brightness_pass;
PGraphics contrast_pass;

PShader brightness_shader;
PShader contrast_shader;

float adjust_brightness = 0.0;
float adjust_contrast = 1.0;

void setup() {
  size(512, 512, P2D);

  imageView = createGraphics(width, height, P2D);
  previewImage = loadImage("mandrill.png");

  // --Set-up-filter-chain-with-PGraphics--
  canvas = createGraphics(previewImage.width, previewImage.height, P2D);
  brightness_pass = createGraphics(previewImage.width, previewImage.height, P2D);
  contrast_pass = createGraphics(previewImage.width, previewImage.height, P2D);

  // --Set-up-shaders--
  brightness_shader = loadShader("brightness.glsl");
  brightness_shader.set("srcTex", previewImage);
  contrast_shader = loadShader("contrast.glsl");
  contrast_shader.set("srcTex", previewImage);
}

void draw() {
  background(0);

  adjust_brightness = map(mouseX, 0, width, -1.0, 1.0);
  adjust_contrast = map(mouseY, 0, height, 0.0, 4.0);

  canvas.beginDraw();
  canvas.image(previewImage, 0, 0);
  canvas.endDraw();

  brightness_pass.beginDraw();
  brightness_shader.set("brightness", adjust_brightness);
  brightness_pass.shader(brightness_shader);
  brightness_pass.image(canvas, 0, 0);
  brightness_pass.endDraw();

  contrast_pass.beginDraw();
  contrast_shader.set("contrast", adjust_contrast);
  contrast_pass.shader(contrast_shader);
  contrast_pass.image(brightness_pass, 0, 0);
  contrast_pass.endDraw();

  imageView.beginDraw();
  imageView.imageMode(CENTER);
  imageView.image(contrast_pass, imageView.width/2, imageView.height/2);
  imageView.endDraw();

  image(imageView, 0, 0);
}

```

And here are my simple frag shaders. Brightness:

```auto
varying vec4 vertTexCoord;

uniform sampler2D srcTex;
uniform float brightness;

void main() {
    lowp vec4 textureColor = texture2D(srcTex, vertTexCoord.xy);

    gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);

 }

```

Contrast:

```auto
varying vec4 vertTexCoord;

uniform sampler2D srcTex;
uniform float contrast;

void main()
{
    lowp vec4 textureColor = texture2D(srcTex, vertTexCoord.xy);
    
    highp float contrastScaled = 4.0 * contrast;
    
    gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrastScaled + vec3(0.5)), textureColor.a);
}

```

---

<div class="post-metadata">

**Author:** ![rikitiki](https://avatars.discourse-cdn.com/v4/letter/r/65b543/32.png) [@rikitiki](https://discourse.processing.org/u/rikitiki)\
**Post date:** [February 23, 2021, 5:07pm UTC](https://discourse.processing.org/t/chaining-glsl-frag-shaders/28006/2 "2021-02-23T17:07:41Z")

</div>

Adam Ferriss was kind enough to help me here, so I thought I’d pay it forward and share the solution to everyone.

**Problem 1 - The image is upside down:**  
Applying shaders to images doesn’t quite work here. What I really needed to do was apply a texture to a rectangle. This fixes the orientation problem.

OpenGL will flip the image with each pass. I have two passes here, so with the corrected code it ends up being OK. If you have an odd number of passes, you can simply store the texture coordinates, `vertTexCoord`, in a new vec2 within the last fragment shader like this:

```auto
    vec2 uv = vertTexCoord.xy;
    uv.y = 1.0 - uv.y;

```

Use uv.xy instead of vertTexCoord.xy after this in your code and the orientation will be corrected. You could also create a shader for flipping, or just use a transform.

**Problem 2 - Only the last adjustment works:**  
The chaining will not work because I needed to pass the textures using set from shader to shader in the draw cycle. Previously I was doing it in setup.

It’s a simple fix that makes sense. Here’s the code. And thanks again Adam!

```auto
PGraphics imageView;
PImage previewImage;

PGraphics canvas;
PGraphics brightness_pass;
PGraphics contrast_pass;

PShader brightness_shader;
PShader contrast_shader;

float adjust_brightness = 0.0;
float adjust_contrast = 1.0;

void setup() {
  size(512, 512, P2D);

  imageView = createGraphics(width, height, P2D);
  previewImage = loadImage("mandrill.png");

  // --Set-up-filter-chain-with-PGraphics--
  canvas = createGraphics(previewImage.width, previewImage.height, P2D);
  brightness_pass = createGraphics(previewImage.width, previewImage.height, P2D);
  contrast_pass = createGraphics(previewImage.width, previewImage.height, P2D);

  // --Set-up-shaders--
  brightness_shader = loadShader("brightness.glsl");
  contrast_shader = loadShader("contrast.glsl");
}

void draw() {
  background(0);

  adjust_brightness = map(mouseX, 0, width, -1.0, 1.0);
  adjust_contrast = map(mouseY, 0, height, 0.0, 4.0);

  canvas.beginDraw();
  canvas.image(previewImage, 0, 0);
  canvas.endDraw();

  brightness_pass.beginDraw();
  brightness_pass.shader(brightness_shader);
  brightness_shader.set("brightness", adjust_brightness);
  brightness_shader.set("srcTex", canvas);
  brightness_pass.rect(0, 0, brightness_pass.width, brightness_pass.height);
  brightness_pass.endDraw();

  contrast_pass.beginDraw();
  contrast_shader.set("contrast", adjust_contrast);
  contrast_pass.shader(contrast_shader);
  contrast_shader.set("srcTex", brightness_pass);
  contrast_pass.rect(0, 0, contrast_pass.width, contrast_pass.height);
  contrast_pass.endDraw();

  imageView.beginDraw();
  imageView.imageMode(CENTER);
  imageView.image(contrast_pass, imageView.width/2, imageView.height/2);
  imageView.endDraw();

  image(imageView, 0, 0);
}

```
