shader questions

hi,

i’m just getting started with shaders so please bear with me.

I understand that uniform variables at the top of shaders are variable that you control from your main c++ code
http://www.lighthouse3d.com/opengl/glsl-…-ogluniform

Using the shader addon this can be done with setUniformVariable1f(…)

My thought is that with a shader, anything you draw will have that shader applied, i.e.:
shader bind;
draw stuff;
shader unbind;

But most of the shader stuff I have been looking at has something like:
uniform sampler2D someImage;

Does that mean you have to pass a texture into the shader?

Any clarity would be greatly appreciated.

Thanks

yes, what you would do is this:

glActiveTexture(GL_TEXTURE1234);
texture.bind();
shader.on();
shader.uniformVariable1i(“textureVarInShader”, 1234);
drawstuff();
shader.off();

thanks moka, what if you were drawing stuff into an fbo, then you wanted to apply a shader to the fbo?

my code looks like this:

  
  
testFbo.swapIn();  
testFbo.setupScreenForMe();  
  
particleMan.draw();  
  
testFbo.swapOut();  
testFbo.setupScreenForThem();  
  
ofSetColor(255,255,255);  
testShader.setShaderActive(true);  
testFbo.draw(0, 0);  
testShader.setShaderActive(false);  
  

I am doing particles in a vbo. I was trying to use a shader when drawing them into the fbo, but realised this isn’t how it works.

Many thanks

do you want to apply the shader to the FBO texture or to the stuff you draw to the FBO?

EDIT:

Ah now I see, you would do it like this:

glActiveTexture(GL_TEXTURE0);
myFBO->bindAsTexture();
shader.on();
shader.setUniform1i(“textureVarInShader”, 0);
drawFullScreenQuad();
shader.off()

hi moka

This doesnt work…
testFbo->bindAsTexture();

Where is the bindAsTexture() function? DO you use the fbo class from the forum?

drawFullScreenQuad(); also doesnt work.

How else does anyone else draw their fbo using a shader? Memo?

uff… i’ve been working on the same problem today… any luck?

no, I just wrote pseudo code :), but you can simply add the function it would look like this:

  
  
void fboClass::bindAsTexture(){  
	glBindTexture(GL_TEXTURE_2D, fboTextureId); 	  
}  
  

you should actually have that part in the function where you draw the FBO. but since often times you upscale an FBO to the whole screen it makes sense to give the binding an extra function. so you (pseudo)code would look like this:

  
  
glActiveTexture(GL_TEXTURE0);  
myFBO.bindAsTexture();  
myShader.setActive(true);  
myShader.sendUniform1("textureVariableInShader", 0);  
drawFullScreenQuad();  
myShader.setActive(false);  
  

the name for the uniformvariable needs to be the same as the texture variable in your shader!

DrawFullscreenQuad() should be a function like this:

  
	float tcy1, tcy2, tcy3, tcy4;  
	tcy1 = 1.0;  
	tcy2 = 1.0;  
	tcy3 = 0.0;  
	tcy4 = 0.0;  
	glBegin(GL_QUADS);  
	glTexCoord2f(0.0,tcy1);			glVertex3f(0,0,0);  
	glTexCoord2f(1.0,tcy2);			glVertex3f(ofGetWidth(),0,0);  
	glTexCoord2f(1.0,tcy3);			glVertex3f(ofGetWidth(), ofGetHeight(),0);  
	glTexCoord2f(0.0,tcy4);			glVertex3f(0, ofGetHeight(),0);  
	glEnd();  
  

Hope that helps in any way!

[quote author=“chrisoshea”]hi moka

This doesnt work…
testFbo->bindAsTexture();

Where is the bindAsTexture() function? DO you use the fbo class from the forum?

drawFullScreenQuad(); also doesnt work.

How else does anyone else draw their fbo using a shader? Memo?[/quote]

Using those addons the code would be something like…

  
  
fbo.swapIn();  
fbo.setupScreenForMe();  
     
// draw stuff     
  
fbo.swapOut();  
fbo.setupScreenForThem();  
     
glActiveTexture(GL_TEXTURE0);  
glBindTexture(GL_TEXTURE_2D, (GLuint)fbo.getTextureData().textureName[0]);  
shader.setUniformVariable1i("tex", 0);  
  
shader.setShaderActive(true);  
// takes care of drawing the GL_TRIANGLE_FAN primitives  
// with appropriate texture coords for you  
fbo.draw(0, 0);  
shader.setShaderActive(false);  
  

Vertex shader would be…

  
  
void main()  
{  
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;  
   gl_TexCoord[0] = gl_MultiTexCoord0;  
}  
  

Fragment shader would be…

  
  
uniform sampler2D tex;  
  
void main()  
{  
   gl_FragColor = texture2D(tex, gl_TexCoord[0].st);  
}  
  

One other thing to note is that if you define a sampler2D uniform variable in your shader and don’t initialize it with a set uniform method, OpenGL automatically binds the sampler2D variable with texture unit 0. This gets bound for you in ofTexture::draw() so you could get away without…

  
  
glActiveTexture(GL_TEXTURE0);  
glBindTexture(GL_TEXTURE_2D, (GLuint)fbo.getTextureData().textureName);  
shader.setUniformVariable1i("tex", 0);  
  

Neil.

well you could get away without sending the texture ID to the shader. But since that only works if you only use one texture I would rather get used to it since as soon as you bind more than one texture you need to send the IDs to the shader :slight_smile:

[quote author=“moka”]well you could get away without sending the texture ID to the shader. But since that only works if you only use one texture I would rather get used to it since as soon as you bind more than one texture you need to send the IDs to the shader :wink:

hey thanks guys!

well, all the advice was really great and it all works now!! although in the end it turned out the problem was that I was editing the wrong shader files… i had one set in the data folder and the other in the bin and well, ok, pretty dumb error…

cheers!
chris

Thanks.

Apex I’m trying out your code:
fbo.getTextureData().textureName[0]

But I’m getting back a message saying the texture hasn’t been allocated.

Well I did fbo.allocate() in the setup. Maybe the fbo class I have doesn’t allocate the texture? Although I don’t get any failed messages.

I am using ofxFBOTexture from Zach Gage

hey, yes, i saw that error too. actually, it does allocate, but in that fbo class, the allocate function doesn’t set bAllocated var to true :slight_smile: so just add

  
 texData.bAllocated = true;  
  

to the end of allocate() and it should remove the error.

Hi,

I’m having a strange problem using shader with texture:

my setup

  
  
void testApp::setup(){    
    ofBackground(20,20,20);  
  
    glDepthMask(false);  
    glDisable(GL_DEPTH_TEST);  
    glEnable( GL_BLEND );  
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);                                                                                                                                                                        
      
    tex.allocate(ofGetWidth(), ofGetHeight(), GL_RGBA);  
    shader.loadShader("diffuse");  
    shader.printActiveUniforms();   
    psys.setup(5000);   
  

… draw:

  
  
 tex.begin();  
  ofSetColor(200, 200, 200); //55, 255);                                                                                                                                                                      
  psys.draw();   
  tex.end();  
    
  ofSetColor(255,255,255);  
  
  glActiveTexture(GL_TEXTURE0);  
  glBindTexture(GL_TEXTURE_2D, (GLuint)tex.getTextureData().textureName[0]);  
  shader.setUniform("tex", (int) 0);  
  
  shader.setShaderActive(true);   
     tex.draw(0,0, ofGetWidth()/2.0, ofGetHeight()/2.0);  
  shader.setShaderActive(false);  
  tex.draw( ofGetWidth()/2,0 , ofGetWidth()/2, ofGetHeight()/2);  
  

my frag

  
  
uniform sampler2D tex;  
   
void main()  
{  
     gl_FragColor = texture2D(tex, gl_TexCoord[0].st);  
}  
  
  

and vert

  
  
varying vec3 normal;  
  
void main()  
{      
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;  
  gl_TexCoord[0] = gl_MultiTexCoord0;  
}      
  

…The original texture draw correctly but the shaded one results in a black screen. The problem seems to come from my texture passing.

Is anyone have any idea ?

PS: tex is a ofxFBOTexture

Regards,

If you post a zip of src / data we can take a look…

one thought, try ofDisableArbTex(); right at the top – your shader is looking to work with GL_TEXTURE_2D - but ofTextures be default will use the ARB (non power of 2 rectangle) if they can. calling ofDisableArbTex() at the top of the code (before allocation) will force your FBO to be a normal, POW2 tex.

take care!
zach

Hi,

Here you can find the code it you want to have a look.

Thanks,
F-

pshape-test.tar.gz

Hi,

Using simple ofTexture from an image appears to work correctly. I don’t know if this clue can help.
Any way the code that does not work was uploaded here:

http://github.com/dopuskh3/ofx-projects-…-haderTest/

Bests,
F-

Hi,

try this:

  
  
    glActiveTexture(GL_TEXTURE0);  
    psys.setup(5000);  
  

Hi,

Doing this does not work:

  
  
  ...  
  
  tex.begin();   
  glActiveTexture(GL_TEXTURE0);  
  psys.draw();   
  tex.end();  
  
  tex.draw( ofGetWidth()/2,0 , ofGetWidth()/2, ofGetHeight()/2);  
    
  glActiveTexture(GL_TEXTURE0);  
  tex.bindAsTexture();   
  shader.setUniform((char *)"tex", (int) 0);  
  shader.setShaderActive(true);   
  tex.draw(0,0, ofGetWidth()/2.0, ofGetHeight()/2.0);  
  shader.setShaderActive(false);  
  ..  
  

does produce a blank screen on the shaded part of the screen.

Doing the same with an image works well:

  
  
  
  ofTexture &itex = image.getTextureReference();  
  
  itex.draw( ofGetWidth()/2,0 , ofGetWidth()/2, ofGetHeight()/2);  
  
  glActiveTexture(GL_TEXTURE0);  
  glBindTexture(GL_TEXTURE_2D, (GLuint)itex.getTextureData().textureName[0]);  
    
  shader.setUniform((char *)"tex", (int) 0);  
  shader.setShaderActive(true);  
  itex.draw(0,0, ofGetWidth()/2.0,  ,ofGetHeight()/2.0);                                                                                                                                                                     
  shader.setShaderActive(false);  
...  
  

Although itex is not a ofxOFBTexture but I don’t think it’s the problem as i tested the same loading screen
as a texture after drawing and pass it thought the shader.

Regards,

Hi there,

I finaly got my program working by modifying the ofxOFBTexture. Maybe the one I’m using is not up to date (I don’t know where to find the good one).

The problem was due to the texData.textureTarget initialized as GL_TEXTURE_RECTANGLE_ARB in this part of the ofxFBOTexture.cpp:

  
  
  
    if (GLEE_ARB_texture_rectangle){  
        texData.tex_w = w;  
        texData.tex_h = h;  
        texData.textureTarget = GL_TEXTURE_RECTANGLE_ARB;                                                                                                                                                          
    } else {  
        texData.tex_w = ofNextPow2(w);  
        texData.tex_h = ofNextPow2(h);  
    }  
  
        if (GLEE_ARB_texture_rectangle){  
                texData.tex_t = w;  
                texData.tex_u = h;  
        } else {  
                texData.tex_t = 1.0f;  
                texData.tex_u = 1.0f;  
        }  
  
  
  

I just modified it as in the ofTexture.cpp code:

  
  
  
texData.tex_w = ofNextPow2(w);                                                                                                                                                                             
        texData.tex_h = ofNextPow2(h);  
        texData.tex_t = 1.0f;  
        texData.tex_u = 1.0f;  
        texData.textureTarget = GL_TEXTURE_2D;  
  
  

… and my shader work now.

Bests,