using ofShader with ofTexture's

hi all …

i’m trying to use the ofShader addon to work by filtering an ofTexture that i paint on the screen. The main idea is to code a GLSL lumakey effect on the ofTextures painted.

i’m a bit confused with this information found in Nehe Tutorials :

/////////////////////////////////////////////

As I said before… textures are available in GLSL via sampler, which have to be uniform. But how do we tell GLSL which texture image should be used for which sampler?

Textures are not directly passed to GLSL, but we pass the texture unit where our texture is bound to OpenGL. This works in the following way:

Get the sampler uniform location.
Bind the texture to texture unit i.
Pass i as an integer by glUniform.

Here an example:

glUseProgramObjectARB(my_program);
int my_sampler_uniform_location = glGetUniformLocationARB(my_program, “my_color_texture”);

glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, my_texture_object);

glUniform1iARB(my_sampler_uniform_location, i);

/////////////////////////////////////////////

Does anybody knows if i should also make the call to glACtiveTexture() inside the ofTexture code or if i could use textures and shader in some other way ? Any hints or simple texture with shaders ?

i’ve been looking at the information about GLSL texture and i can’t find the way to work properly, when i activate the shader the image gets black.

the thing is that i’ve a code already running in an ATI M9600 computer, but it doesn’t work in NVIDIA M 8700 computer … It’s really strange that this code works, but it does in an ATI old card … confussing even more …

anybody dealed with GLSL shaders affecting an ofTexture ??

many thanks, so stuck on this …

well i’ve get to a strange point .

i’ve the same implementation working fine under an ATI m9600 and not working in a new nVidia 8700M.

both cards have GLSL support and both compile ok the fragment and vertex shaders.

i include the code of both shaders :

fragment shader
·························
uniform sampler2D tex;
void main()
{
vec4 color = texture2D(tex,gl_TexCoord[0].st);
gl_FragColor = color * 0.5;
}
vertex shader
···················
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

with the ATI m9600 i’m just creating the ofShader, making it active just before paiting the video texture and the shader works, so i see the image.

with the nVidia 8700 when i active shaders the image goes black and no texture is passed.

anybody knows about nVidia cards difficulties with GLSL ? with GLExtensionsViewer i could check that shader support is enabled in the nVidia card …

what i’m trying right now is the simplest example for texture processing and i don’t understand why such a simple example could work differently on both hardware configurations … ?¿

any suggestions ?

I really don’t know about this stuff, but you should check this part of ofTexture:

  
  
if (GLEE_ARB_texture_rectangle){  
		textureTarget = GL_TEXTURE_RECTANGLE_ARB;  
	} else {  
		textureTarget = GL_TEXTURE_2D;  
	}  
  

we choose non power of two if we can, and this target switch could mess you up alot (because the coordinates are way different). you might try disabling it, ie, only doing GL_TEXTURE_2D and see if that helps

take care,
zach

well keeping on my problem i got to another data :

the ATI m9600 is using ofTextures as GL_TEXTURE_2D
and
the NVIDIA m87000 is using ofTextures as GL_TEXTURE_RECTANGLE_ARB

that would explain your problem, right?
ie, why it works on one card and not the other…

  • z

hi zach !

well first sorry i didn’t read you message when i wrote my last message …
later i saw a forum discussion where you talk about this and that it could maybe effect to GLSL …

and YES ! it was that … I’ve disabled the GL_TEXTURE_RECTANGLE_ARB and now it works great on both machines :wink:

This is part of a software that i would like to distribute so … is there some option to keep the OF code as it is and avoiding this hack ?

thanks

e*

hi again …

well i do know how can i solve the problem (hack to GL_TEXTURE_2D always)
but i would like to understand why it doesn’t work properly.

zach pointed out that the mapping coordinates where so different.

as far as i understand “shaders” functions (just newbie), i think shaders use the GL coordinates present at every moment on the GL state .And i was thinking that the change for differnet coordinates is already done by ofTexture (on all the if (GLEE_ARB_texture_rectangle)…) , but maybe i’m wrong ?

i would like to understand why i can’t use GL_ARB_texture_rectangle if my card supports it . AS i’ve read, when u work with GL_ARB_texture_rectangle, the shader code might change on it’s texture uniform variables from sample2D (for GL_TEXTURE_2D) to sample2DRect.

i’ve tried that and then the ofShader compilation says :

“Sample2DRect #extension GL_ARB_texture_rectangle neeeds Enable before use”

is there a way to enable extra extensions in OF ?¿

e*

I’m afraid this out of the scope of knowledge, but as I remember you will need different shader code for ARB textures vs. non ARB textures. I’ve done this once, and may have some code – will check.

for loading extnesions, we use the glee library you can use it too - it’s in OF. take a look in ofTexture to see how we use it (ie, the ARB stuff)…

take care,
zach

as i would like to distribute the work i’m doing …

wouldn’t it be possible to make something like :

useARBTexturesRect() // something that u can choose

instead of changing the texture target depending on Glee detection ??

does it make sense ?

right now with OF.04 the only way i can run the code (with just 1 shader code) is to “hack” ofTexture to avoid entering into ARBtextureRect …

thanks x thousands :wink:

e*

could you just create a class that extends of texture and does it the way you would like? that way you don’t have to change OF at all ?

we are likely not going to add that functionality at this moment. not that I’m closed to it by any means, but I can’t see it yet … thanks for suggesting it though -

take care,
zach

hi all …

well i solved some of my problems to work with shaders but i’m facing new problems to make a simple GLSL shader to work with an ofTexture …

i’m using some sample code from the book “More OpenGL Game Programming” but still i can’t make OF to show me a texture passed by a shader programs …

has anybody played with it and could give me a hand ?

these are my shader simple programs …

  
fragment shader  
·························  
uniform sampler2D tex;  
void main()  
{  
vec4 color = texture2D(tex,gl_TexCoord[0].st);  
gl_FragColor = color * 0.5;  
}  
vertex shader  
···················  
void main()  
{  
gl_TexCoord[0] = gl_MultiTexCoord0;  
gl_Position = ftransform();  
}   

then where i’ve problems … what should be done in OF before calling to paint the ofTexture?? . . .

i load correctly the shader (it compiles ok) then in the draw() function from the main loop i’m trying …

.h i’ve :

  
ofTexture videoTexture;  

then in testApp::draw()
…/…

  
shader.setActiveShader(true);  
  
glPushMatrix();  
  
glActiveTexture(GL_TEXTURE0);  
  
//i've modified the ofTexture making the parameter textureName to  
//be 'public' ... not sure if that's correct ...   
glBindTexture(GL_TEXTURE_2D,(GLuint)videoTexture.textureName[0]);  
  
//then i added a new function in ofShader which is explained below  
shader.sendUniformVariableTexture();  
  
//draw the texture normally  
videoTexture.draw(0,0);  
glPopMatrix();  
shader.setActiveShader(false);  
  
---------------  
ofShader::sendUniformVariableTexture()  
{  
  if(bLoaded==true)  
 {  
      glUniform1iARB(glGetUniformLocationARB(shader,"tex"),0);  
  }  
}  
  

anybody could give me a hand on how to paint a texture which passes through a simple shader ?? i’m always getting a black screen instead of a texture … :_( … any advice ? any sample code ??

thanks a lot …

e

hi eloi

I’m not sure how to help you with this, but could I ask you a favor?

can you use the “code” tags in phpbb ? it will help format your code so that it’s easier to read – I realized seeing all the code you just posted it could be alot helpful for everyone who gets to this entry to see the code formatted (the code tag is like a pre tag in html)…

ie

test(float a, float b){
ofLine(a,b,0,0);
}

vs

  
  
test(float a, float b){  
	ofLine(a,b,0,0);  
}  
  

the code tags are really helpful !!

many thanks!!
zach

Hi Eloi,

I’ve got some experience with loading textures into shaders, except the stuff I’ve done is on my laptop at home…I should be able to help you with exactly that problem because I’ve had to solve it before. It’s really easy once you have the solution, but the documentation isn’t always that good so I certainly remember being confused for a bit…

I’ll try and post something as soon as possible

I don’t know if this is helpful, but this is code (vertex, frag) that I have that performs a threshold on all the images:

  
  
// ---------------------------- vert  
void main()  
{  
  
	gl_TexCoord[0] = gl_MultiTexCoord0;  
	gl_Position = ftransform();  
}   
  
  
// ---------------------------- frag  
  
uniform sampler2D tex;  
  
void main()  
{  
	vec4 color = texture2D(tex,gl_TexCoord[0].st);  
	if (color.r > 0.5) color.rgb = vec3(0,0,0);  
	else color.rgb = vec3(1,1,1);  
	gl_FragColor = color;  
}  
  
  

and the infamous brick shader, rewritten for the coordinate system that OF uses (ie, 0,0 to 1024,768).

  
  
// frag  
//  
// Fragment shader for procedural bricks  
//  
// Authors: Dave Baldwin, Steve Koren, Randi Rost  
//          based on a shader by Darwyn Peachey  
//  
// Copyright (c) 2002-2004 3Dlabs Inc. Ltd.  
//  
// See 3Dlabs-License.txt for license information  
//    
  
uniform vec3  BrickColor;  
uniform vec3  MortarColor;  
uniform vec2  BrickSize;  
uniform vec2  BrickPct;  
  
varying vec2  MCposition;  
varying float LightIntensity;  
  
void main(void)  
{  
    vec3  color;  
    vec2  position, useBrick;  
      
    position = MCposition / BrickSize;  
  
    if (fract(position.y * 0.5) > 0.5)  
        position.x += 0.5;  
  
    position = fract(position);  
  
    useBrick = step(position, vec2(0.8,0.8));  
  
    color  = mix(vec3(BrickSize.xy,0), vec3(1,1,1), useBrick.x * useBrick.y);  
    //color *= LightIntensity;  
    gl_FragColor = vec4 (color, 1.0);  
}  
  

  
  
//  
// Vertex shader for procedural bricks  
//  
// Authors: Dave Baldwin, Steve Koren, Randi Rost  
//          based on a shader by Darwyn Peachey  
//  
// Copyright (c) 2002-2004 3Dlabs Inc. Ltd.   
//  
// See 3Dlabs-License.txt for license information  
//  
  
uniform vec3 LightPosition;  
  
const float SpecularContribution = 0.3;  
const float DiffuseContribution  = 1.0 - SpecularContribution;  
  
varying float LightIntensity;  
varying vec2  MCposition;  
  
void main(void)  
{  
    vec3 ecPosition = vec3 (gl_ModelViewMatrix * gl_Vertex);  
    vec3 tnorm      = normalize(gl_NormalMatrix * gl_Normal);  
    vec3 lightVec   = normalize(LightPosition - ecPosition);  
    vec3 reflectVec = reflect(-lightVec, tnorm);  
    vec3 viewVec    = normalize(-ecPosition);  
    float diffuse   = max(dot(lightVec, tnorm), 0.0);  
    float spec      = 0.0;  
  
    if (diffuse > 0.0)  
    {  
        spec = max(dot(reflectVec, viewVec), 0.0);  
        spec = pow(spec, 16.0);  
    }  
  
    LightIntensity  = DiffuseContribution * diffuse +  
                      SpecularContribution * spec;  
  
    MCposition      = gl_Vertex.xy;  
    gl_Position     = ftransform();  
}  
  

one point to note as that certain types of primitives in OF - like of circle look strange, the reason is that they are scaled up (ie, an OF circle is a unit circle - radius = 1 – that is cached and scaled when drawn – you will need to draw it manually at full size in order for the brick pattern to match the other objects you draw).

hope these codes are helpful –

take care,
zach

hi zach :wink:

my biggest doubt right now is … which calls are u making in the OF code to let the shader know which texture unit to use ?

regarding the first example, the thershold one … are u modyfing or adding some code on the OF code to make the texture to be painted with thershold ? or u just use the **shader.setActiveShader(true); ** before painting ?

to be honest, I have no idea – it doesn’t look like I am doing anything that fancy with textures…

here is the code - it’s really basic, not even a class for shaders (all the shader code is in testApp.h, etc)…

openFrameworks.cc/files/glsl_v4_Example.zip

I hope it’s helpful just as something to hack , etc

take care,
zach

and on the flip side, this code does have a shader class:

http://www.openframeworks.cc/files/glsl-v5-Example.zip

and does the brick thing, illustrates the issue with the cached circle…

hope it’s helpful !!
zach

To get basic texturing using GLSL in OF 0.04 you have to do the following:

Comment out all references to code that would normally reference GLEE_ARB_texture_rectangle and also make sure that the default “textureTarget” is GL_TEXTURE_2D.

Then you need load your shader and activate it in setup() and all should work fine.

Regarding multitexturing, this is a little more complex because you need to call

  
glActiveTexture(GL_TEXTURE0);  
glBindTexture(GL_TEXTURE_2D, textureID1);  
  
glActiveTexture(GL_TEXTURE1);  
glBindTexture(GL_TEXTURE_2D, textureID2);  

and

  
GLint texLoc;  
  
texLoc   = glGetUniformLocationARB(shader, "texture1");  
glUniform1i(texLoc, 0);	  
		  
texLoc   = glGetUniformLocationARB(shader, "texture2");  
glUniform1i(texLoc, 1);	  
  

etc… depending on how many textures you want to use simultaneously in your shader. The ofTexture class would then need some extra functionality such as setActiveTexture(int x) in order to set the active texture at the correct time. With only one texture you don’t need to worry about this because the shaders pick it up by default, but with several it becomes a problem.

An example of a multitexturing shader:

texture.vert

  
varying vec2  TexCoord;  
  
void main(void)  
{  
    
	TexCoord = gl_MultiTexCoord0.st;  
	gl_Position = ftransform();     
}  

texture.frag

  
  
uniform sampler2D texture1;  
uniform sampler2D texture2;  
varying vec2  TexCoord;  
  
void main(void)  
{  
  	// get texture info  
	vec4 v1 = texture2D(texture1, TexCoord);  
	vec4 v2 = texture2D(texture2, TexCoord);  
	gl_FragColor =  vec4(mix(v1, v2,0.5).rgb, 1.0);  
  
}  
  

My setup program therefore looks like:

  
  
void testApp::setup(){	  
	myshader.loadShader("texture");  
  
	glActiveTexture(GL_TEXTURE0);  
	myimage.loadImage("test.jpg");  
  
	glActiveTexture(GL_TEXTURE1);	  
	myimage2.loadImage("blue.jpg");  
}  

And then I only draw one image but the 2 textures are blended together by the shader:

  
void testApp::draw(){  
	ofBackground(255,255,255);	  
  
	myimage.draw(100,100);  
}  

In ofTexture::Draw() just before binding the texture I do this hack (just to get it working, not recommended):

  
if (textureName[0]  == 1)  
		glActiveTexture(GL_TEXTURE0);  
		  
if (textureName[0]  == 2)  
		glActiveTexture(GL_TEXTURE1);  

What I found slightly annoying when playing with GLSL and OF textures was that in order to load a texture you need an ofImage first, which uses ofTexture…which is ok until you want to do stuff like setActiveTexture(int x) and all you have is a handle to an ofImage, not the texture itself…

What are your plans for this sort of stuff Zach? I see you’re going to put basic shader support into 0.05, but multitexturing would be cool to support…
I also noticed that you were using the OpenGL 1.5 ARB extension API. It would be good to have a choice to use the Opengl 2.0 API for future improvements…
but I understand if all the feature requests are becoming overwhelming!

Hope that was helpful to someone :slight_smile:
Pierre

Also, if you want to do any GLSL and not bang your head against the wall, I thoroughly recommend the Orange book:

http://www.3dshaders.com/home/

It’s not always well written, but all the information you need is there…

thanks for the info !!! it’s great.

What are your plans for this sort of stuff Zach?

actually, one of the reasons we made the code in 0.04 have “protected” and not private variables is so that someone could take ofImage, extend it and write it to support the kind of texture that they want (or another image model, like floating point) etc. you can take ofTexture for example, and subclass it,

  
  
class myNonArbTexture : public ofTexture {  
  

and do whatever it is you need to do. the problem with adding too many specific things to the core is that it might make the API confusing and it might make the core look more spaghetti-ish.

if there is some fundemental flaw in the objects, we’ll fix it - but looking at the above requests, I wonder if it’s not just better to include them in an ofShader addon that would be a kind of kit that’s necessary for shaders, just as ofCvGrayscale is necessary for opencv. ofShaderImage ? perhaps or ofShaderTexture. what do you think?

take care,
zach