So, i’ve worked on the implementation of the shaders in ofxFX.
It’s really cleaver, i think i will only use this add-on for shaders from now on :).
The thing is i can’t make it work and i don’t know why, i don’t have any error printed in my console and i’ve checked carefully the examples.
Anyway here is the code, maybe someone could spot something wrong :
The shader “BufA”
#pragma once
#include "ofMain.h"
#include "ofxFXObject.h"
/*
"Suture Fluid" by cornusammonis - 2016 April 2015
https://www.shadertoy.com/view/XddSRX
License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
*/
class ofxSutureFluid_A : public ofxFXObject {
public:
ofxSutureFluid_A(){
passes = 2;
internalFormat = GL_RGBA32F;
fragmentShader = STRINGIFY(
uniform float time; // shader playback time (in seconds)
uniform vec3 mouse;
uniform vec2 resolution; // viewport resolution (in pixels)
uniform sampler2D backbuffer; // input channel. XX = 2D/Cube
uniform sampler2D tex0; // input channel. XX = 2D/Cube
//bool reset() {
// return texture2D(iChannel3, vec2(32.5/256.0, 0.5) ).x > 0.5;
//}
vec2 normz(vec2 x) {
return x == vec2(0.0, 0.0) ? vec2(0.0, 0.0) : normalize(x);
}
// reverse advection
vec3 advect(vec2 ab, vec2 vUv, vec2 step, float sc) {
vec2 aUv = vUv - ab * sc * step;
const float _G0 = 0.25; // center weight
const float _G1 = 0.125; // edge-neighbors
const float _G2 = 0.0625; // vertex-neighbors
// 3x3 neighborhood coordinates
float step_x = step.x;
float step_y = step.y;
vec2 n = vec2(0.0, step_y);
vec2 ne = vec2(step_x, step_y);
vec2 e = vec2(step_x, 0.0);
vec2 se = vec2(step_x, -step_y);
vec2 s = vec2(0.0, -step_y);
vec2 sw = vec2(-step_x, -step_y);
vec2 w = vec2(-step_x, 0.0);
vec2 nw = vec2(-step_x, step_y);
vec3 uv = texture2D(backbuffer, fract(aUv)).xyz;
vec3 uv_n = texture2D(backbuffer, fract(aUv+n)).xyz;
vec3 uv_e = texture2D(backbuffer, fract(aUv+e)).xyz;
vec3 uv_s = texture2D(backbuffer, fract(aUv+s)).xyz;
vec3 uv_w = texture2D(backbuffer, fract(aUv+w)).xyz;
vec3 uv_nw = texture2D(backbuffer, fract(aUv+nw)).xyz;
vec3 uv_sw = texture2D(backbuffer, fract(aUv+sw)).xyz;
vec3 uv_ne = texture2D(backbuffer, fract(aUv+ne)).xyz;
vec3 uv_se = texture2D(backbuffer, fract(aUv+se)).xyz;
return _G0*uv + _G1*(uv_n + uv_e + uv_w + uv_s) + _G2*(uv_nw + uv_sw + uv_ne + uv_se);
}
void main( void )
{
const float _K0 = -20.0/6.0; // center weight
const float _K1 = 4.0/6.0; // edge-neighbors
const float _K2 = 1.0/6.0; // vertex-neighbors
const float cs = -0.6; // curl scale
const float ls = 0.05; // laplacian scale
const float ps = -0.8; // laplacian of divergence scale
const float ds = -0.05; // divergence scale
const float dp = -0.04; // divergence update scale
const float pl = 0.3; // divergence smoothing
const float ad = 6.0; // advection distance scale
const float pwr = 1.0; // power when deriving rotation angle from curl
const float amp = 1.0; // self-amplification
const float upd = 0.8; // update smoothing
const float sq2 = 0.6; // diagonal weight
vec2 vUv = gl_FragCoord.xy / resolution.xy;
vec2 texel = 1. / resolution.xy;
// 3x3 neighborhood coordinates
float step_x = texel.x;
float step_y = texel.y;
vec2 n = vec2(0.0, step_y);
vec2 ne = vec2(step_x, step_y);
vec2 e = vec2(step_x, 0.0);
vec2 se = vec2(step_x, -step_y);
vec2 s = vec2(0.0, -step_y);
vec2 sw = vec2(-step_x, -step_y);
vec2 w = vec2(-step_x, 0.0);
vec2 nw = vec2(-step_x, step_y);
vec3 uv = texture2D(backbuffer, fract(vUv)).xyz;
vec3 uv_n = texture2D(backbuffer, fract(vUv+n)).xyz;
vec3 uv_e = texture2D(backbuffer, fract(vUv+e)).xyz;
vec3 uv_s = texture2D(backbuffer, fract(vUv+s)).xyz;
vec3 uv_w = texture2D(backbuffer, fract(vUv+w)).xyz;
vec3 uv_nw = texture2D(backbuffer, fract(vUv+nw)).xyz;
vec3 uv_sw = texture2D(backbuffer, fract(vUv+sw)).xyz;
vec3 uv_ne = texture2D(backbuffer, fract(vUv+ne)).xyz;
vec3 uv_se = texture2D(backbuffer, fract(vUv+se)).xyz;
// uv.x and uv.y are the x and y components, uv.z is divergence
// laplacian of all components
vec3 lapl = _K0*uv + _K1*(uv_n + uv_e + uv_w + uv_s) + _K2*(uv_nw + uv_sw + uv_ne + uv_se);
float sp = ps * lapl.z;
// calculate curl
// vectors point clockwise about the center point
float curl = uv_n.x - uv_s.x - uv_e.y + uv_w.y + sq2 * (uv_nw.x + uv_nw.y + uv_ne.x - uv_ne.y + uv_sw.y - uv_sw.x - uv_se.y - uv_se.x);
// compute angle of rotation from curl
float sc = cs * sign(curl) * pow(abs(curl), pwr);
// calculate divergence
// vectors point inwards towards the center point
float div = uv_s.y - uv_n.y - uv_e.x + uv_w.x + sq2 * (uv_nw.x - uv_nw.y - uv_ne.x - uv_ne.y + uv_sw.x + uv_sw.y + uv_se.y - uv_se.x);
float sd = uv.z + dp * div + pl * lapl.z;
vec2 norm = normz(uv.xy);
vec3 ab = advect(vec2(uv.x, uv.y), vUv, texel, ad);
// temp values for the update rule
float ta = amp * ab.x + ls * lapl.x + norm.x * sp + uv.x * ds * sd;
float tb = amp * ab.y + ls * lapl.y + norm.y * sp + uv.y * ds * sd;
// rotate
float a = ta * cos(sc) - tb * sin(sc);
float b = ta * sin(sc) + tb * cos(sc);
vec3 abd = upd * uv + (1.0 - upd) * vec3(a,b,sd);
if (mouse.z > 0.0) {
vec2 d = gl_FragCoord.xy - mouse.xy;
float m = exp(-length(d) / 10.0);
abd.xy += m * normz(d);
}
// initialize with noise
if(mouse.z > 0.0) {
gl_FragColor = -0.5 + texture2D(tex0, gl_FragCoord.xy / resolution.xy);
} else {
//gl_FragColor = clamp(vec4(abd,0.0), -1., 1.);
abd.z = clamp(abd.z, -1.0, 1.0);
abd.xy = clamp(length(abd.xy) > 1.0 ? normz(abd.xy) : abd.xy, -1.0, 1.0);
gl_FragColor = vec4(abd, 0.0);
}
}
);
};
void update(){
for( int i = 0; i < passes ; i++ ){
pingPong.dst->begin();
ofClear(0,0,0,255);
shader.begin();
shader.setUniform1f("time", ofGetElapsedTimef());
shader.setUniform2f("resolution", (float)width, (float)height);
shader.setUniform2f("mouse", (float)ofGetMouseX()/width, (float)ofGetMouseY()/height);
shader.setUniformTexture("backbuffer", pingPong.src->getTexture(), 0 );
shader.setUniformTexture("tex0", textures[0].getTexture(), 1 );
renderFrame();
shader.end();
pingPong.dst->end();
pingPong.swap();
}
pingPong.swap();
};
};
The shader “Image”
#pragma once
#include "ofMain.h"
#include "ofxFXObject.h"
/*
"Suture Fluid" by cornusammonis - 2016 April 2015
https://www.shadertoy.com/view/XddSRX
License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
*/
class ofxSutureFluid : public ofxFXObject {
public:
ofxSutureFluid(){
passes = 1;
internalFormat = GL_RGBA32F;
fragmentShader = STRINGIFY(
uniform float time; // shader playback time (in seconds)
uniform vec3 mouse;
uniform vec2 resolution; // viewport resolution (in pixels)
uniform sampler2D tex0; // input channel. XX = 2D/Cube
// Visualization of the system in Buffer A
void main( void )
{
vec2 texel = 1. / resolution.xy;
vec2 uv = gl_FragCoord.xy / resolution.xy;
vec3 c = texture2D(tex0, uv).xyz;
vec3 norm = normalize(c);
vec3 div = vec3(0.1) * norm.z;
vec3 rbcol = 0.5 + 0.6 * cross(norm.xyz, vec3(0.5, -0.4, 0.5));
gl_FragColor = vec4(rbcol + div, 0.0);
});
};
};
ofApp.h
#pragma once
#include "ofMain.h"
#include "ofxSutureFluid.h"
#include "ofxSutureFluid_A.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
ofxSutureFluid SutureFluid;
ofxSutureFluid_A SutureFluid_A;
};
ofApp.cpp
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
ofSetFrameRate(60);
ofBackground(0);
ofEnableAlphaBlending();
SutureFluid.allocate(1000,600);
SutureFluid_A.allocate(1000,600);
ofImage background;
background.load("noise2.jpg");
SutureFluid_A.setTexture(background.getTexture(), 1);
}
//--------------------------------------------------------------
void ofApp::update(){
SutureFluid_A.update();
SutureFluid << SutureFluid_A;
SutureFluid.update();
}
//--------------------------------------------------------------
void ofApp::draw(){
ofSetColor(255);
SutureFluid.draw(0,0,ofGetWidth(),ofGetHeight());
}
The project : Test.zip (67.7 KB)