Hello,
I try to apply a shader filters taken from ofxFilterLibrary on a texture using Fbo but i have a black texture instead of the texture with the shader applied.
https://github.com/mfargo/ofxFilterLibrary
I can’t solve this problem myself, i spent a few days on it but i’m stuck on this
Here is my code, sorry it’s a bit long (i have tried to keep only the interresting parts)
The most interresting part i think is in Ornament.cpp::update.
main.cpp :
int main()
{
ofSetupOpenGL(1280, 768, OF_WINDOW);
ofRunApp(new ofApp());
}
ofApp.cpp :
void ofApp::setup()
{
ornament.setup(ofGetWidth() * ZOOM_FACTOR, ofGetHeight() * ZOOM_FACTOR);
ofLoadImage(preview, "img/mytexture.png");
ornament.loadTexture(preview);
}
void ofApp::draw()
{
int w = ofGetWindowWidth() * ZOOM_FACTOR;
int h = ofGetWindowHeight() * ZOOM_FACTOR;
ornament.draw(-w / 2, -h / 2);
}
void ofApp::update()
{
ornament.update();
}
Ornament.cpp :
void Ornament::setup(int w, int h, WALLPAPER_GROUP wallpaperGroup_, int tileSize_, float angle_)
{
width = w;
height = h;
wallpaperGroup = wallpaperGroup_;
tileSize = tileSize_;
angle = angle_;
fbo.allocate(width, height);
ornamentShader.setupShaderFromSource(GL_VERTEX_SHADER, getVertexShader());
ornamentShader.setupShaderFromSource(GL_FRAGMENT_SHADER, getOrnamentShader());
ornamentShader.linkProgram();
wallpaperShader.setupShaderFromSource(GL_VERTEX_SHADER, getVertexShader());
wallpaperShader.setupShaderFromSource(GL_FRAGMENT_SHADER, getWallpaperShader());
wallpaperShader.linkProgram();
// INIT SHADER BASED FILTER TAKEN FROM OFXFILTERLIBRARY
postProcessFilter = new ToonFilter(w, h);
}
void Ornament::loadTexture(ofTexture texture){
inputTexture = texture;
//inputTexture.setAnchorPercent(0.5, 0.5);
inputTexture_preview = texture;
inputTexture_preview.setAnchorPercent(0.5, 0.5);
int w = width;
int h = height;
if (texture.getWidth() > w) {
w = texture.getWidth();
}
if (texture.getHeight() > h) {
h = texture.getHeight();
}
if (!tileFbo.isAllocated() || tileFbo.getWidth() != w || tileFbo.getHeight()!=h) {
tileFbo.allocate(w, h);
resizeFbo.allocate(w, h);
}
createOrnament();
}
void Ornament::update()
{
//resize texture
resizeFbo.begin();
ofClear(0, 0, 0, 0);
ofVec2f pNew, sizeNew;
getBoundingBox(tile->getOrnamentBase(), pNew, sizeNew);
ofVec2f sizeTex = resize(ofVec2f(inputTexture.getWidth(), inputTexture.getHeight()), sizeNew);
ofVec2f posTex = (pNew + sizeNew * 0.5) - sizeTex * 0.5;
ofSetMatrixMode(OF_MATRIX_TEXTURE);
ofPushMatrix();
ofMatrix4x4 m;
m.glRotate(tileRotation);// 10, 1, 1, 1);
m.glScale(tileScale);// 0.5, 1, 1);
m.glTranslate(tilePosition);// 100, 0, 0);
ofMultMatrix(m);
inputTexture.draw(posTex.x, posTex.y, sizeTex.x, sizeTex.y);
ofPopMatrix();
ofSetMatrixMode(OF_MATRIX_MODELVIEW);
resizeFbo.end();
//create tile
tileFbo.begin();
ofClear(0, 0, 0, 0);
ornamentShader.begin();
ornamentShader.setUniform1i("cell_structure", tile->getCellStructure());
ornamentShader.setUniform1i("wallpaper_group", wallpaperGroup);
ornamentShader.setUniform1f("width", inputTexture.getWidth());
ornamentShader.setUniform1f("height", inputTexture.getHeight());
resizeFbo.draw(0, 0);
ornamentShader.end();
tileFbo.end();
//create wallpaper
fbo.begin();
ofClear(255, 255, 255, 0);
ofSetColor(255, 255, 255, 255);
wallpaperShader.begin();
wallpaperShader.setUniform1i("cell_structure", tile->getCellStructure());
wallpaperShader.setUniform1f("width", width);
wallpaperShader.setUniform1f("height", height);
wallpaperShader.setUniform1f("tile_size", tileSize);
wallpaperShader.setUniform1f("angle", angle);
wallpaperShader.setUniform1f("tex_width", inputTexture.getWidth());
wallpaperShader.setUniform1f("tex_height", inputTexture.getHeight());
tileFbo.draw(0, 0);
wallpaperShader.end();
fbo.end();
// try to apply ofxFilterLibrary ToonShader
// PROBLEM OCCURS HERE
postProcessFilter->begin(); // BLACK TEXTURE BECAUSE OF THAT LINE !
fbo.draw(0, 0);
postProcessFilter->end(); // BLACK TEXTURE BECAUSE OF THAT LINE !
outputTexture = fbo.getTexture();
tile->updateTile();
}
void Ornament::draw(int x, int y)
{
outputTexture.draw(x, y);
}
string Ornament::getVertexShader(){
string out = string("#version 120\n") +
STRINGIFY(
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
);
return out;
}
string Ornament::getOrnamentShader(){
string out = string("#version 120\n#extension GL_ARB_texture_rectangle : enable\n#define PI 3.141592653589793\n#define P4 9\n#define P4M 10\n#define P4G 11\n#define P3 12\n#define P3M1 13\n#define P31M 14\n#define P6 15\n#define P6mm 16\n") +
STRINGIFY(
uniform sampler2DRect u_tex_unit0;
uniform float width,height;
uniform int wallpaper_group;
/*
0 = P1,
1 = P2,
2 = PM,
3 = PG,
4 = CM,
5 = PMM,
6 = PMG,
7 = PGG,
8 = CMM
*/
uniform int cell_structure;
/*
0 = RECTANGLE,
1 = SQUARE,
2 = RHOMBIC,
3 = HEXAGONAL,
4 = OBLIQUE
*/
vec2 p1,p2,p3,p4;
vec2 base1,base2,base3,base4,mid;
vec2 p1p2, p2p3, p3p4, p1p4;
/*****************
* Transformation *
******************/
vec2 translate(vec2 point ,vec2 trans){
return point + trans;
}
vec2 rotate(vec2 point, float angle){
mat2 rot = mat2 (
cos(angle), sin(angle),
-sin(angle),cos(angle));
return rot * point;
}
vec2 rotateAt(vec2 point, vec2 anchor, float angle){
return vec2(
cos(angle)*point.x - sin(angle)*point.y + anchor.x - cos(angle)*anchor.x + sin(angle)*anchor.y,
sin(angle)*point.x + cos(angle)*point.y + anchor.y - sin(angle)*anchor.x - cos(angle)*anchor.y);
}
vec2 reflectAt(vec2 point, vec2 anchor, vec2 dir){
vec2 I = point-anchor;
vec2 N = normalize(dir);
vec2 r = reflect(I,N);
return anchor - r;
}
/************************
* Position calculation *
************************/
void getBorders(){
// CUTTED BECAUSE TOO LONG
}
bool PointInTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2)
{
// CUTTED BECAUSE TOO LONG
}
bool isInTile(vec2 p)
{
//pt resolves edge jitter
vec2 pt = vec2(p.x-0.1,p.y-0.1);
if(PointInTriangle(p,p1,p2,p4) || PointInTriangle(p,p2,p3,p4)
||PointInTriangle(pt,p1,p2,p4) || PointInTriangle(pt,p2,p3,p4)){
return true;
}
return false;
}
//type 0=P4, 1=P4M, 2=P4G
int getTileSquare(vec2 pos,int type){
// CUTTED BECAUSE TOO LONG
}
int getTileTriangle(vec2 pos,int type){
//ornament base
base1 = p1;
vec2 p1p2 = p1 + (p2-p1)/2;
base2 = p1p2 + (p3-p1p2)/3;
base3 = p3;
vec2 p1p4 = p1 + (p4-p1)/2;
base4 = p1p4 + (p3-p1p4)/3;
int t1,t2,t3;
if(PointInTriangle(pos,p1,p3,p4)){
t1 = 0;
if(PointInTriangle(pos,p1,p3,base4)){
t2 = 0;
if (PointInTriangle(pos,p1,p1 + (p3-p1)/2,base4)) t3 = 0;
else t3 = 1;
}else if(PointInTriangle(pos,p4,p3,base4)){
t2 = 1;
if (PointInTriangle(pos,p3,p4 + (p3-p4)/2,base4)) t3 = 0;
else t3 = 1;
}
else{
t2 = 2;
if (PointInTriangle(pos,p4,p4 + (p1-p4)/2,base4)) t3 = 0;
else t3 = 1;
}
}else{
t1 = 1;
if(PointInTriangle(pos,p1,p3,base2)){
t2 = 0;
if (PointInTriangle(pos,p1,p1 + (p3-p1)/2,base2)) t3 = 0;
else t3 = 1;
}else if(PointInTriangle(pos,p1,p2,base2)){
t2 = 1;
if (PointInTriangle(pos,p2,p1 + (p2-p1)/2,base2)) t3 = 0;
else t3 = 1;
}
else{
t2 = 2;
if (PointInTriangle(pos,p3,p3 + (p2-p3)/2,base2)) t3 = 0;
else t3 = 1;
}
}
int t = t1*6 + t2*2 + t3;
int lut[12];
if(type == 0){
// 000 001 010 011 020 021 100 101 110 111 120 121
lut = int[12]( 0, 0, 3, 3, 4, 4, 0, 0, 1, 1, 2, 2);
}else if(type == 1){
// 000 001 010 011 020 021 100 101 110 111 120 121
lut = int[12]( 0, 1, 31, 30, 40, 41, 0, 1, 11, 10, 20, 21);
}else if(type == 2 || type == 3){
// 000 001 010 011 020 021 100 101 110 111 120 121
lut = int[12]( 0, 0, 4, 4, 5, 5, 1, 1, 2, 2, 3, 3);
}else if(type == 4){
// 000 001 010 011 020 021 100 101 110 111 120 121
lut = int[12]( 0, 1, 40, 41, 50, 51, 10, 11, 20, 21, 30, 31);
}
return lut[t];
}
/*************************************
* WALLPAPER RENDERING P4 Groups*
************************************/
void do_p4(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
void do_p4m(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
void do_p4g(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
/*************************************
* WALLPAPER RENDERING P3, P6 Groups*
************************************/
void do_p3(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
void do_p3m1(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
void do_p31m(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
void do_p6(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
void do_p6mm(vec2 pos)
{
// CUTTED BECAUSE TOO LONG
}
void main( void )
{
getBorders();
vec4 color = texture2DRect( u_tex_unit0, gl_TexCoord[0].st );
vec2 pos = gl_TexCoord[0].st;
//gl_FragColor = texture2DRect( u_tex_unit0, rotateAt (pos,vec2(width/2,height/2),cos(u_time) ));
if(isInTile(pos)){
if (wallpaper_group == P4) do_p4(pos);
else if (wallpaper_group == P4M) do_p4m(pos);
else if (wallpaper_group == P4G) do_p4g(pos);
else if (wallpaper_group == P3) do_p3(pos);
else if (wallpaper_group == P3M1) do_p3m1(pos);
else if (wallpaper_group == P31M) do_p31m(pos);
else if (wallpaper_group == P6) do_p6(pos);
else if (wallpaper_group == P6mm) do_p6mm(pos);
}else{
gl_FragColor = vec4(0.0,0.0,0.0,0.0);
}
} );
return out;
}
string Ornament::getWallpaperShader(){
string out = string("#version 120\n#extension GL_ARB_texture_rectangle : enable\n#define PI 3.141592653589793\n#define RECTANGLE 0\n#define SQUARE 1\n#define RHOMBIC 2\n#define HEXAGONAL 3\n#define OBLIQUE 4\n") +
STRINGIFY(uniform sampler2DRect u_tex_unit0;
uniform float tex_width,tex_height;
uniform float width,height;
uniform int cell_structure;
/*
0 = RECTANGLE,
1 = SQUARE,
2 = RHOMBIC,
3 = HEXAGONAL,
4 = OBLIQUE
*/
uniform float tile_size;
uniform float angle;
vec2 p1,p2,p3,p4;
vec2 base1,base2,base3,base4;
vec2 nextCellSouth, nextCellEast, nextCellNorth, nextCellWest;
/*****************
* Transformation *
******************/
float map(float val,float inMin,float inMax,float outMin,float outMax){
return outMin + ((outMax - outMin) / (inMax - inMin)) * (val - inMin);
}
float fmod(float val, float modulo){
int i = int(val/modulo);
return val - (i*modulo);
}
vec2 translate(vec2 point ,vec2 trans){
return point + trans;
}
vec2 rotate(vec2 point, float angle){
mat2 rot = mat2 (
cos(angle), sin(angle),
-sin(angle),cos(angle));
return rot * point;
}
vec2 rotateAt(vec2 point, vec2 anchor, float angle){
return vec2(
cos(angle)*point.x - sin(angle)*point.y + anchor.x - cos(angle)*anchor.x + sin(angle)*anchor.y,
sin(angle)*point.x + cos(angle)*point.y + anchor.y - sin(angle)*anchor.x - cos(angle)*anchor.y);
}
vec2 reflectAt(vec2 point, vec2 anchor, vec2 dir){
vec2 I = point-anchor;
vec2 N = normalize(dir);
vec2 r = reflect(I,N);
return anchor - r;
}
bool PointInTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2)
{
float s = p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y;
float t = p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y;
if ((s < 0) != (t < 0))
return false;
float A = -p1.y * p2.x + p0.y * (p2.x - p1.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y;
if (A < 0.0)
{
s = -s;
t = -t;
A = -A;
}
return s > -0.01 && t > -0.01 && (s + t) < A;
}
/************************
* Position calculation *
************************/
void updateCornerPoints(){
// CUTTED BECAUSE TOO LONG
}
vec2 do_square(vec2 pos){
// CUTTED BECAUSE TOO LONG
}
vec2 do_hexagonal(vec2 pos){
// CUTTED BECAUSE TOO LONG
}
void main( void )
{
updateCornerPoints();
vec4 color = texture2DRect( u_tex_unit0, gl_TexCoord[0].st );
vec2 pos = gl_TexCoord[0].st;
pos = rotateAt(pos,vec2(width/2,height/2),angle);
if(cell_structure == SQUARE){
pos = do_square(pos);
}
if(cell_structure == HEXAGONAL){
pos = do_hexagonal(pos);
}
vec4 c = texture2DRect(u_tex_unit0, pos);
gl_FragColor = c;
}
);
return out;
}
Thanks a lot for your help !
I really need to solve that issue
Eviral