Closed marioecg closed 1 year ago
https://github.com/patriciogonzalezvivo/glsl-sandbox/blob/main/examples/000.js#L70-L89
: )
Try this other ; )
#define PLATFORM_WEBGL
uniform sampler2D u_scene;
uniform sampler2D u_doubleBuffer0;
uniform vec2 u_resolution;
uniform float u_time;
uniform int u_frame;
varying vec2 v_texcoord;
varying vec3 v_normal;
varying vec4 v_position;
#include "lygia/math/saturate.glsl"
#include "lygia/space/ratio.glsl"
#include "lygia/space/scale.glsl"
#include "lygia/color/mixOklab.glsl"
#include "lygia/generative/snoise.glsl"
void main() {
vec4 color = vec4(vec3(0.0), 1.0);
vec2 pixel = 1.0 / u_resolution;
vec2 st = gl_FragCoord.xy * pixel;
vec2 sst = ratio(st, u_resolution);
vec2 uv = v_texcoord;
#if defined(BACKGROUND)
color.a = 0.0;
#elif defined(DOUBLE_BUFFER_0)
float n = snoise( vec3(sst * (1.5 + sin(u_time)) * 5.0, u_time * 0.5) ) * 0.0025;
vec2 st0 = scale(st, 0.995 + n);
color = texture2D(u_doubleBuffer0, st0);
vec4 scene = texture2D(u_scene, st);
color.rgb = mixOklab(color.rgb, scene.rgb, step(0.99,scene.a));
color.a = 1.0;
#elif defined(POSTPROCESSING)
color = texture2D(u_doubleBuffer0, st);
#else
color.rgb = v_normal * 0.5 + 0.5;
color.rg = mix(color.rg, uv, saturate(distance(sst, vec2(0.5))*2. ) );
#endif
gl_FragColor = color;
}
Thanks @patriciogonzalezvivo! Love the example using noise. So having a background, setting its alpha to 0 and interpolating with the previous frame and the scene's transparency is key.
Could this work as a generalized basic structure for ping-pong buffers with 3D shaders?
void main() {
vec4 color = vec4(vec3(0.0), 1.0);
vec2 pixel = 1.0 / u_resolution;
vec2 st = gl_FragCoord.xy * pixel;
#if defined(BACKGROUND)
// If you need a background billboard behind the scene
// I think this just works for 3D shaders
// ...
#elif defined(DOUBLE_BUFFER_0)
// Sample the texture that does ping-pong between
// the two buffers (or previous frame)
// Keep in mind that changes inside here accumulate over time
vec2 st1 = scale(st, 0.995);
color.rgb = texture2D(u_doubleBuffer0, st1).rgb;
#elif defined(POSTPROCESSING)
// Displays the content of the double buffer
// directly to the screen
color = texture2D(u_doubleBuffer0, st);
#endif
gl_FragColor = color;
}
What if we want this same scale effect in a 2D shader that shows a square SDF. How would that be?
It's key to that particular effect on where the pixels expands through the space. Ping-pong is the overall use of two buffers where the output of one pass is the input of the following.
From that code you just share what is missing is the scene. There is no explicit content for the material of the geometry and in the double buffer you are not mixing the previous pass with nothing new.
The original example I provided have a 2D example in doubleBuffer0... that then is use as texture for the cube's material
I just added two 2D examples:
And simplify the previous one, so it's clear that the main shader in glslViewer is used for the geometry material
This makes the interface more compact
Thanks for putting the new examples @patriciogonzalezvivo! It makes more sense to me now.
Sometimes for my work I like exploring 3D scenes that I pass through a double buffer to make a poisson fill effect. How would you implement it in this workflow?
I think I figured it out following a very similar example from above, but if you have a different way of using poisson fill I'll be curious to know!
#define PLATFORM_WEBGL
uniform sampler2D u_scene;
uniform sampler2D u_doubleBuffer0;
uniform vec2 u_resolution;
#include "lygia/morphological/poissonFill.glsl"
void main() {
vec2 pixel = 1.0 / u_resolution;
vec2 st = gl_FragCoord.xy * pixel;
vec4 color = vec4(vec3(0.0), 1.0);
#if defined(BACKGROUND)
color.a = 0.0;
#elif defined(DOUBLE_BUFFER_0)
vec4 prevFrame = poissonFill(u_doubleBuffer0, u_doubleBuffer0, st, pixel, false);
vec4 scene = texture2D(u_scene, st);
color = mix(prevFrame, scene, scene.a);
#elif defined(POSTPROCESSING)
color = texture2D(u_doubleBuffer0, st);
#endif
gl_FragColor = color;
}
Poisson fill uses another structure that is not just a simple double buffer but a double pyramid convolution (one pyramid for down sampling and other for up sampling). That kind of structure is supported on GlslViewer in this way, but not yet on glsl-sandbox.
If you are curious on how it's implemented you can start here in vera which is my C++/OpenGL framework on which glslViewer is implemented. You can see there how multiple set's of buffers are created... one half the size of the previous one (for the down sampling pyramid) and the other set is each double the size of the previous (for the up sampling pyramid).
Following the same branching logic I use only one single shader for going through both pyramids. But their logic is different depending at what point is.
https://github.com/patriciogonzalezvivo/vera/blob/main/include/vera/shaders/poissonfill.h
I have been using it in GlslViewer for all sort of things and is pretty handy for all sort of things.
I just made a visualization example here for you to see how it works https://github.com/patriciogonzalezvivo/lygia_examples/blob/main/morphological_poissonFill.frag
Also in GlslViewer if you press p
(you see all the passes) and can see how the actual pyramids look (top right corner)
To clarify, that visualization basically cut the upsampling short, so you can see how the borders are expanding but actually glslViewer does the entire poisson fill going through the entire pyramids convolution in one single render pass
Oh I see!! Very insightful, thanks for sharing and putting up the examples Patricio. I need to read more on pyramid convolutions.
Now I realize that in my poisson fill example I'm using the formula not ideally, it's just doing the down sampling and that's it — no upscaling and pyramid convolutions are being taken into account. So it falls short or is not being used in all its possibilities. I do get a similar result though as it renders over time (it takes > 5 secs) but less appealing than your visualization.
I'm trying to understand how double buffers work using the sandbox workflow, and as practice I want to port this ping-pong example I made a while ago.
The next shader works for making a similar effect that fades away over time:
What if I want the effect not to fade overtime and persist like in the codesandbox from above? Is it possible with GlslSandbox / glslViewer, if so how would this be?