greenhouse
a creative coding toolkit for spatial interfaces

Shaders

In Greenhouse, every object has built-in capabilities to use OpenGL vertex and fragment shaders. Greenhouse abstracts away a certain amount of OpenGL complexity into two basic operations:

  1. load shaders
  2. update their inputs every frame

In the example shown, the fragment shader adjust the blue pigment of each pixel it works upon. The pixel is colored more blue, depending on how far it is from a given location. The location is provided – each frame – from the C++ side, and is updated there based on the location of an object.

  • LoadShaders ()
  • AssignShaderInputs ()
  • SetShaderUniform ()

Example

///// Vertex Shader (radius.vert) //////
#version 120

// stores the physical location of the vertex
varying vec4 world_pos;

void main ()
{
  gl_FrontColor = gl_Color;
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform();
  world_pos = gl_Vertex;
}

///// Fragment Shader (radius.frag) //////
const float blurSize = 25.0;
// the location to calculate this pixel's distance from
uniform vec3 center;
// the physical location of this pixel
varying vec4 world_pos;

// the image being rendered
uniform sampler2D tex0;

void main(void)
{ // calculate the physical distance between this pixel and the center loc
  float dist = distance(world_pos.xyz, center.xyz);
  // make a color whose blue is determined by the distance from the center
  vec4 shade = vec4(1.0, 1.0, min(dist/blurSize, 1.0), 1.0);
  // multiply the color of the pixel in the texture by the shade
  gl_FragColor = shade * gl_Color * texture2D (tex0, gl_TexCoord[0].xy);
}

///// Greenhouse Application /////

#include "Greenhouse.h"

struct GlowingRect  :  public Image
{ Thing *invisibleDot;

  GlowingRect (const Str p) : Image (p)
    { LoadShaders ("shaders/radius.vert", "shaders/radius.frag");
      SetCornerRadius (0);
      SetHeightUniformly(0.7  * Feld () -> Height ());

      invisibleDot = new Thing ();
      AppendKid (invisibleDot);
      invisibleDot -> TranslationAnimateOrbit (0.25 * Height () * Up (),
                                               0.25 * Width () * Over (),
                                               1.0);
    }

  void AssignShaderInputs ()
    { SetShaderUniform ("center",
                        WrangleLoc (invisibleDot -> Loc ()));
    }

};

void Setup ()
{ GlowingRect *r = new GlowingRect ("share/images/1.jpg");
  r -> SlapOnFeld ();
}