Implementing shader question

Hey!

I am trying to implement the blur shader from the examples into my code.
The problem is, that I can only see the image [index] = 1. [index] = 0 doesnt show. I would like to see them both at the same time. Can it be that it somehow gets overwritten by index = 1? If I dont use the blur-shader, I see both images at the same time. Any suggestions?
Thank you :slight_smile:

void ofApp::draw(){
    for(index = 0; index < 2; index++){
//here apparently only the index = 1 gets send to the BrightnessTreshold::draw() function, or maybe index = 0 gets visually overwritten by index = 1 ?
        bimg[index].draw(alpha[index], x[index], y[index], z[index], zoom[index], blur[index]);
    }
}


void BrightnessTreshold::draw(float alpha, float x, float y, float z, float zoom, float blur){

    fboBlurOnePass.begin();
        shaderBlurX.begin();
        shaderBlurX.setUniform1f("blurAmnt", blur);

  //--------------------------------------------------------------------- 
 // drawing the mesh, with a simple alphachannel - shader
    easyCam.setPosition(image.getWidth()/2, image.getHeight()/2, zoom);
    easyCam.begin();
        ofPushMatrix();
    
            ofTranslate(image.getWidth()/2, image.getHeight()/2);
                ofRotateXDeg(x);
                ofRotateZDeg(y);
                ofRotateYDeg(z);
            ofTranslate(-image.getWidth()/2, -image.getHeight()/2);
 
            shaderAlpha.begin();
                shaderAlpha.setUniform1f("alpha", alpha);
                mesh.draw();
            shaderAlpha.end();
    
        ofPopMatrix();
    easyCam.end();
  //---------------------------------------------------------------------  

        shaderBlurX.end();
    fboBlurOnePass.end();

    fboBlurTwoPass.begin();
        shaderBlurY.begin();
            shaderBlurY.setUniform1f("blurAmnt", blur);
            fboBlurOnePass.draw(0, 0);
        shaderBlurY.end();
    fboBlurTwoPass.end();
    
    ofSetColor(ofColor::white);
    fboBlurTwoPass.draw(0,0, w, h);
}

Hi @Maedd,

Yes I think that right: the second image re write on top of the first one.
As a common practice I would say that the EasyCam should be taken out, and its position set once at the start, as getting the size of the app every frames * amountOfImages will end up adding up in CPU.

To solve you problem, in the shader, either you can:

  1. try to do something like not put the alpha to 1 in the shader, so what’s behind is seen, or
  2. pass the previous result of the image to the next iteration, and therefore have the blur applied again on the second iteration to the first layer:
for(index = 0; index < 2; index++){
//here apparently only the index = 1 gets send to the BrightnessTreshold::draw() function, or maybe index = 0 gets visually overwritten by index = 1 ?
        if( index > 0){
    bimg[index].drawWithPreviousIndex(bimg[index-1].fboBlurTwoPass.getTexture(), alpha[index], x[index], y[index], z[index], zoom[index], blur[index]);
}else{
// here keep the same constructor for your function, as it's index 0, and nothing has to change
    bimg[index].draw(alpha[index], x[index], y[index], z[index], zoom[index], blur[index]);

    }

and your drawWithPreviousIndex function :

 void BrightnessTreshold::drawWithPreviousIndex(ofTexture texPreviousIndex, float alpha, float x, float y, float z, float zoom, float blur){
fboBlurOnePass.begin();
        shaderBlurX.begin();
        shaderBlurX.setUniform1f("blurAmnt", blur);
shaderBlurX.setUniformTexture("texPIndex", texPreviousIndex);
// [...] rest of the code of the function
}

and in your shaderBlur code, just add the texture to your second shader.

Hope this helps,

If not clear, post the whole thing here, I’ll take a closer look.

Best,

P

Thank you very much!

This works, but the first image only gets drawn where the second image has been drawn. Not anywhere else. Also the background of the app, or at least where no image gets drawn, is blue. I really dont know where this color is coming from.

I tried to implemented your second suggestion, but I dont know shaders at all, so I was wondering on how and where to implement the texture to the shader.

Thats the code of shaderBlurX.frag (there is also shaderBlurY.frag, is that what you mean by second shader?)

#version 150

uniform sampler2DRect tex0;
uniform float blurAmnt;

in vec2 texCoordVarying;
out vec4 outputColor;

void main()
{
    vec4 outputColor = vec4(0.0, 0.0, 0.0, 0.0);
    vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
    
	
	color += 0.000229 * texture(tex0, texCoordVarying + vec2(blurAmnt * -4.0, 0.0));
	color += 0.005977 * texture(tex0, texCoordVarying + vec2(blurAmnt * -3.0, 0.0));
	color += 0.060598 * texture(tex0, texCoordVarying + vec2(blurAmnt * -2.0, 0.0));
	color += 0.241732 * texture(tex0, texCoordVarying + vec2(blurAmnt * -1.0, 0.0));
    
	color += 0.382928 * texture(tex0, texCoordVarying + vec2(0.0, 0));
	
	color += 0.241732 * texture(tex0, texCoordVarying + vec2(blurAmnt * 1.0, 0.0));
	color += 0.060598 * texture(tex0, texCoordVarying + vec2(blurAmnt * 2.0, 0.0));
	color += 0.005977 * texture(tex0, texCoordVarying + vec2(blurAmnt * 3.0, 0.0));
	color += 0.000229 * texture(tex0, texCoordVarying + vec2(blurAmnt * 4.0, 0.0));
    
    outputColor = color;
}

Also I was wondering on how to take out the EasyCam. I am changing the parameters x/y/z/zoom in real time. What would be a solution for that?

This is the code how it is right now, except that the shaderBlurX.setUniformTexture("texPIndex", texPreviousIndex); is not working yet.

Thank you for your answer! :slight_smile:

void BrightnessTreshold::draw(float alpha, float x, float y, float z, float zoom, float blur){
    
    fboBlurOnePass.begin();
        shaderBlurX.begin();
        shaderBlurX.setUniform1f("blurAmnt", blur);
    
    easyCam.setPosition(image.getWidth()/2, image.getHeight()/2, zoom);
    easyCam.begin();
        ofPushMatrix();
    
            ofTranslate(image.getWidth()/2, image.getHeight()/2);
                ofRotateXDeg(x);
                ofRotateZDeg(y);
                ofRotateYDeg(z);
            ofTranslate(-image.getWidth()/2, -image.getHeight()/2);
 
            shaderAlpha.begin();
                shaderAlpha.setUniform1f("alpha", alpha);
                mesh2.draw();
            shaderAlpha.end();
    
        ofPopMatrix();
    easyCam.end();
    
        shaderBlurX.end();
    fboBlurOnePass.end();

    fboBlurTwoPass.begin();
        shaderBlurY.begin();
            shaderBlurY.setUniform1f("blurAmnt", blur);
            fboBlurOnePass.draw(0, 0);

        shaderBlurY.end();
    fboBlurTwoPass.end();
    
    ofSetColor(ofColor::white);
    fboBlurTwoPass.draw(0,0, w, h);
}


void BrightnessTreshold::drawWithPreviousIndex(ofTexture texPreviousIndex, float alpha, float x, float y, float z, float zoom, float blur){
    
    fboBlurOnePass.begin();
    shaderBlurX.begin();
        shaderBlurX.setUniform1f("blurAmnt", blur);
        shaderBlurX.setUniformTexture("texPIndex", texPreviousIndex);
        // [...] rest of the code of the function
    
    easyCam.setPosition(image.getWidth()/2, image.getHeight()/2, zoom);
    easyCam.begin();
        ofPushMatrix();
    
            ofTranslate(image.getWidth()/2, image.getHeight()/2);
                ofRotateXDeg(x);
                ofRotateZDeg(y);
                ofRotateYDeg(z);
            ofTranslate(-image.getWidth()/2, -image.getHeight()/2);
    
            shaderAlpha.begin();
                shaderAlpha.setUniform1f("alpha", alpha);
                mesh2.draw();
            shaderAlpha.end();
    
        ofPopMatrix();
    easyCam.end();
    
    shaderBlurX.end();
    fboBlurOnePass.end();
    
    fboBlurTwoPass.begin();
        shaderBlurY.begin();
            shaderBlurY.setUniform1f("blurAmnt", blur);
            fboBlurOnePass.draw(0, 0);
    
        shaderBlurY.end();
    fboBlurTwoPass.end();
    
    ofSetColor(ofColor::white);
    fboBlurTwoPass.draw(0,0, w, h);
}

Hi @Maedd,

I think if you write something like this for the blurX shader :

#version 150

uniform sampler2DRect tex0;
uniform sampler2DRect texPIndex;
uniform float blurAmnt;

in vec2 texCoordVarying;
out vec4 outputColor;

void main()
{
    vec4 outputColor = vec4(0.0, 0.0, 0.0, 0.0);
    vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
    
    vec4 previousColor = texture(texPIndex,texCoordVarying);
    
    
    color += 0.000229 * texture(tex0, texCoordVarying + vec2(blurAmnt * -4.0, 0.0));
    color += 0.005977 * texture(tex0, texCoordVarying + vec2(blurAmnt * -3.0, 0.0));
    color += 0.060598 * texture(tex0, texCoordVarying + vec2(blurAmnt * -2.0, 0.0));
    color += 0.241732 * texture(tex0, texCoordVarying + vec2(blurAmnt * -1.0, 0.0));
    
    color += 0.382928 * texture(tex0, texCoordVarying + vec2(0.0, 0));
    
    color += 0.241732 * texture(tex0, texCoordVarying + vec2(blurAmnt * 1.0, 0.0));
    color += 0.060598 * texture(tex0, texCoordVarying + vec2(blurAmnt * 2.0, 0.0));
    color += 0.005977 * texture(tex0, texCoordVarying + vec2(blurAmnt * 3.0, 0.0));
    color += 0.000229 * texture(tex0, texCoordVarying + vec2(blurAmnt * 4.0, 0.0));
    
    outputColor = color + previousColor;
}

you will get the previousColor added to your blur.
But maybe you will want to add it to the blurY, as the previous layer will be blur twice in Y, but once in X.

so your method drawWithPreviousIndex(ofTexture texPreviousIndex, float alpha, float x, float y, float z, float zoom, float blur) would look something like this :

 void BrightnessTreshold::drawWithPreviousIndex(ofTexture texPreviousIndex, float alpha, float x, float y, float z, float zoom, float blur){
fboBlurOnePass.begin();
// [...]

shaderBlurY.setUniform1f("blurAmnt", blur);
shaderBlurY.setUniformTexture("texPIndex", texPreviousIndex);
fboBlurOnePass.draw(0, 0);
shaderBlurY.end();
fboBlurTwoPass.end();
    
ofSetColor(ofColor::white);
fboBlurTwoPass.draw(0,0, w, h);
}

For the EasyCam, it would be to create a different method to just move the EasyCam around, then inside that method, call the draws functions :

 void BrightnessTreshold::drawWithEasyCam(){
   easyCam.setPosition(image.getWidth()/2, image.getHeight()/2, zoom);
    easyCam.begin();

for(index = 0; index < 2; index++){
//here apparently only the index = 1 gets send to the BrightnessTreshold::draw() function, or maybe index = 0 gets visually overwritten by index = 1 ?
        if( index > 0){
    bimg[index].drawWithPreviousIndex(bimg[index-1].fboBlurTwoPass.getTexture(), alpha[index], x[index], y[index], z[index], zoom[index], blur[index]);
}else{
    bimg[index].draw(alpha[index], x[index], y[index], z[index], zoom[index], blur[index]);

    }
easyCam.end();
}

Hope this helps,

Best,

P

yes that helped! Thanks a lot!
I also tried to take out the easyCam. The strange thing is, that the mesh doesn’t get drawn in the center of the screen anymore:

If I call the easyCam in void BrightnessTreshold::draw(…) as I did before, the mesh gets drawn in the center. Any idea why this is the case? Could the problem be, that ofApp inherence from BrightnessTrehsold? (class ofApp : public ofBaseApp, BrightnessTreshold{ ... )
I also call image.setAnchorPercent(0.5, 0.5) in the setup() function. But since I am turning the image into a mesh in setup(), I think that doesnt apply anymore (?).

I also tried it with no camrea at all, but in this case I am also having trouble getting the mesh drawn in the center of the screen. Any suggestions?

Thank you :slight_smile:

void ofApp::bimgdraw(){

    easyCam.setPosition(image.getWidth()/2, image.getHeight()/2, 0);
        easyCam.begin();
        ofPushMatrix();
    
    for(index = 0; index < 2; index++){
        bimg[index].draw(alpha[index], x[index], y[index], z[index], zoom[index], threeD[index]);
    }
    
        ofPopMatrix();
    easyCam.end();
}

void BrightnessTreshold::draw(float alpha, float x, float y, float z, float zoom, float threeD){
    
            ofTranslate(image.getWidth()/2, image.getHeight()/2, zoom);
                ofRotateXDeg(x);
                ofRotateZDeg(y);
                ofRotateYDeg(z);
                ofScale(1, 1, threeD);
            ofTranslate(-image.getWidth()/2, -image.getHeight()/2);

                mesh2.draw();
}

Hello @Maedd,

So the ofEasyCam essentially centers the (0,0) to the center of the screen.

Therefore, I think :

can be reomved and left with just the rotations and scaling.

Best,

P