-
-
Notifications
You must be signed in to change notification settings - Fork 351
Multiple render passes and Buffers
You can use multiple buffers by forking the code using #ifdef BUFFER_[number]
, #if defined (BUFFER_[number])
and/or #elif defined (BUFFER_[number])
. Then you can fetch the content of those buffers by using the uniform sampler2D u_buffer[number]
texture. Ex.:
uniform sampler2D u_buffer0;
uniform sampler2D u_buffer1;
varying vec2 v_texcoord;
void main() {
vec3 color = vec3(0.0);
vec2 st = v_texcoord;
#ifdef BUFFER_0
color.g = abs(sin(u_time));
#elif defined( BUFFER_1 )
color.r = abs(sin(u_time));
#else
color.b = abs(sin(u_time));
color = mix(color,
mix(texture2D(u_buffer0, st).rgb,
texture2D(u_buffer1, st).rgb,
step(0.5, st.x) ),
step(0.5, st.y));
#endif
gl_FragColor = vec4(color, 1.0);
}
There is an extended example on examples/test_multibuffer.frag
and examples/grayscott.frag
.
If you load a 3D model or set a shader without opacity you will notice the background is black by default (actually transparent in RaspberryPi).
It's possible to set a background by adding a #ifdef BACKGROUND
check and adding your code there. Check the example examples/model_background.frag
uniform vec2 u_resolution;
uniform float u_time;
varying vec4 v_color;
varying vec3 v_normal;
float stroke(float x, float size, float w) {
float d = step(size, x+w*.5) - step(size, x-w*.5);
return clamp(d, 0., 1.);
}
vec2 ratio(in vec2 st, in vec2 s) {
return mix( vec2((st.x*s.x/s.y)-(s.x*.5-s.y*.5)/s.y,st.y),
vec2(st.x,st.y*(s.y/s.x)-(s.y*.5-s.x*.5)/s.x),
step(s.x,s.y));
}
float rectSDF(vec2 st, vec2 s) {
st = st*2.-1.;
return max( abs(st.x/s.x),
abs(st.y/s.y) );
}
void main(void) {
vec4 color = vec4(1.0);
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec2 pixel = 1./u_resolution.xy;
#ifdef BACKGROUND
st = ratio(st, u_resolution);
color.rgb *= vec3(0.75, 0.0, 0.0) * step(0.5, fract((st.x - st.y - u_time * 0.1) * 20.));
float sdf = rectSDF(st, vec2(1.0));
color.rgb *= step(sdf, 0.7);
color.rgb += vec3(1.0, 0.0, 0.0) * stroke(sdf, 0.75, 0.01);
#else
color.rgb = v_color.rgb;
float shade = dot(v_normal, normalize(vec3(0.0, 0.75, 0.75)));
color.rgb *= smoothstep(-1.0, 1.0, shade);
#endif
gl_FragColor = color;
}
Also when loading 3D models it's possible to add a postprocessing layer adding a #ifdef POSTPROCESSING
to branch the logic of the shader. To apply a postprocessing layer you need to read the scene as a texture, this is saved on the uniform sampler2D u_scene;
texture together with a depth render pass of the scene located in uniform sampler2D u_scene_depth;
. Here is an example of a cheap DoF at examples/model_postprocessing.frag
uniform sampler2D u_scene; // Scene RGB
uniform sampler2D u_scene_depth; // Scene Depth
uniform vec2 u_resolution;
uniform float u_time;
varying vec4 v_position;
varying vec4 v_color;
varying vec3 v_normal;
varying vec2 v_texcoord;
float stroke(float x, float size, float w) {
float d = step(size, x+w*.5) - step(size, x-w*.5);
return clamp(d, 0., 1.);
}
vec2 ratio(in vec2 st, in vec2 s) {
return mix( vec2((st.x*s.x/s.y)-(s.x*.5-s.y*.5)/s.y,st.y),
vec2(st.x,st.y*(s.y/s.x)-(s.y*.5-s.x*.5)/s.x),
step(s.x,s.y));
}
float rectSDF(vec2 st, vec2 s) {
st = st*2.-1.;
return max( abs(st.x/s.x),
abs(st.y/s.y) );
}
float LinearizeDepth(float zoverw) {
float n = 1.0; //
float f = 20000.0;
return (2.0 * n) / (f + n - zoverw * (f - n));
}
void main(void) {
vec4 color = vec4(1.0);
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec2 pixel = 1./u_resolution.xy;
#ifdef BACKGROUND
// Background pattern
st = ratio(st, u_resolution);
color.rgb *= vec3(0.75, 0.0, 0.0) * step(0.5, fract((st.x - st.y - u_time * 0.1) * 20.));
float sdf = rectSDF(st, vec2(1.0));
color.rgb *= step(sdf, 0.7);
color.rgb += vec3(1.0, 0.0, 0.0) * stroke(sdf, 0.75, 0.01);
#elif defined(POSTPROCESSING)
// Get depth
float depth = texture2D(u_scene_depth, st).r;
depth = LinearizeDepth(depth) * 200.0;
// Define focal point
float focalDistance = 100.0;
float focalRange = 50.0;
depth = min( abs(depth - focalDistance) / focalRange, 1.0);
// Cheap box blur
pixel *= 4.;
color.rgb = texture2D(u_scene, st + vec2(pixel.x, 0.0)).rgb;
color.rgb += texture2D(u_scene, st + vec2(0.0, pixel.y)).rgb;
color.rgb += texture2D(u_scene, st + vec2(-pixel.x, 0.0)).rgb;
color.rgb += texture2D(u_scene, st + vec2(0.0, -pixel.y)).rgb;
color.rgb *= 0.25;
// Mix blur and crisp scene images based on depth
color.rgb = mix(color.rgb, texture2D(u_scene, st).rgb, 1.0 - depth);
// Debug Depth
// color.rgb = vec3(1.) * depth;
#else
// Material of model
color.rgb = v_color.rgb;
float shade = dot(v_normal, normalize(vec3(0.0, 0.75, 0.75)));
color.rgb *= smoothstep(-1.0, 1.0, shade);
#endif
gl_FragColor = color;
}