PostFX

Even though Gorilla3D is compatible with Firemonkey post effects, it is difficult for many users to build their own post effect.

To solve this issue we provide the TGorillaRenderPassPostFX component.

It is now possible for you to easily create your own effect and to write a shader in the IDE at design time.

DesignTime

  1. Drop a TGorillaRenderPassPostFX component from component palette onto your form
  2. Select your TGorillaRenderPassPostFX instance in structure view
  3. Link the GorillaViewport instance to the “Viewport” property of your TGorillaRenderPassPostFX instance
  4. Open “SurfaceShader” property editor
  5. Write GLSL shader code using “vec3 SurfaceShader(inout TLocals DATA){…}” as entry function

Here is some nice television post-effect for the surface shader.

Just copy & paste into GorillaRenderPassPostFX1.SurfaceShader property editor:

vec3 mod289(vec3 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}
 
vec2 mod289(vec2 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}
 
vec3 permute(vec3 x) {
  return mod289(((x*34.0)+1.0)*x);
}
 
float snoise(vec2 v){
  const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
  vec2 i  = floor(v + dot(v, C.yy) );
  vec2 x0 = v -   i + dot(i, C.xx);
 
  vec2 i1;
  i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
  vec4 x12 = x0.xyxy + C.xxzz;
  x12.xy -= i1;
 
  i = mod289(i);
  vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 ));
 
  vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
  m = m*m ;
  m = m*m ;
 
  vec3 x = 2.0 * fract(p * C.www) - 1.0;
  vec3 h = abs(x) - 0.5;
  vec3 ox = floor(x + 0.5);
  vec3 a0 = x - ox;
 
  m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
 
  vec3 g;
  g.x  = a0.x  * x0.x  + h.x  * x0.y;
  g.yz = a0.yz * x12.xz + h.yz * x12.yw;
  return 130.0 * dot(m, g);
}
 
float rand(vec2 co){
   return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
 
vec3 SurfaceShader(inout TLocals DATA){
    vec2 uv = DATA.TexCoord0.xy;
    float iTime = mod(_TimeInfo.y, 360.0);
    float time = iTime * 2.0;
 
    float noise = max(0.0, snoise(vec2(time, uv.y * 0.3)) - 0.3) * (1.0 / 0.7);
 
    noise = noise + (snoise(vec2(time*10.0, uv.y * 2.4)) - 0.5) * 0.15;
 
    vec4 fragColor;
    float xpos = uv.x - noise * noise * 0.25;
	fragColor = tex2D(_RenderedTexture, vec2(xpos, uv.y));
 
    fragColor.rgb = mix(fragColor.rgb, vec3(rand(vec2(uv.y * time))), noise * 0.3).rgb;
 
    if (floor(mod(gl_FragCoord.y * 0.25, 2.0)) == 0.0){
        fragColor.rgb *= 1.0 - (0.15 * noise);
    }
 
    fragColor.g = mix(fragColor.r, texture(_RenderedTexture, vec2(xpos + noise * 0.05, uv.y)).g, 0.25);
    fragColor.b = mix(fragColor.r, texture(_RenderedTexture, vec2(xpos - noise * 0.05, uv.y)).b, 0.25);
 
    return fragColor.rgb;
}

Source: https://www.shadertoy.com/view/XtK3W3

Runtime

Of course you can also setup post effects at runtime.

Have a look at the following function simply extracting the red-color channel from main render pass.

var LPostFX := TGorillaRenderPassPostFX.Create(GorillaViewport1, 'RedChannelPostEffect');
LPostFX.Viewport := GorillaViewport1;
LPostFX.SurfaceShader.Text := 
  'vec3 SurfaceShader(inout TLocals DATA){'#13#10 +
  '  return vec3(tex2D(_RenderedTexture, DATA.TexCoord0.xy).r, 0.0, 0.0));'#13#10 +
  '}'#13#10;

Shaders

You can write shaders in GLSL syntax compatible with OpenGL 4.3 (on Windows) and OpenGLES 3.1+ (on Android).

WARNING: GLSL compiler does not allow comments in shader code. The framework currently does not filter comments.

The SurfaceShader property of the PostFX instance allows to put a string with compatible shader code into.

At least every shader needs a “SurfaceShader” function with the following header. Besides that you can add further functions to the shader.

vec3 SurfaceShader(inout TLocals DATA){
...
}

The shader itself provides some variables for usage:

Shader Variable Type Description
_RenderedTexturesampler2DThe main render pass result texture.
_MaskTexturesampler2DOptional texture for post effects. You can use this texture for additional shader computation.
_TimeInfo.xfloatStarting timestamp of the post effect shader
_TimeInfo.yfloatCurrent timestamp of the post effect shader
_TimeInfo.zfloatPrevious timestamp of the post effect shader
_TimeInfo.wfloatDelta timestamp of the post effect shader
DATA.TexCoord0vec2Texture coordinate of the post effect plane.
DATA.WorldViewProjVertPosvec4World-View-Projected vertex position of the post effect plane.
DATA.Normalvec3Normal vector of the post effect plane.

You can find many free shaders in the web with less need of change.