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
moka
June 14, 2009, 3:55pm
#2
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
moka
June 14, 2009, 4:00pm
#4
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?
chris
June 20, 2009, 4:57pm
#6
uff… i’ve been working on the same problem today… any luck?
moka
June 20, 2009, 5:37pm
#7
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.
moka
June 21, 2009, 5:11pm
#9
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
[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
chris
June 21, 2009, 10:28pm
#11
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
chris
June 28, 2009, 3:40pm
#13
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 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,
zach
October 12, 2009, 6:32pm
#15
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-
grimus
October 13, 2009, 11:24am
#18
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,