ofShader cancelling ofLight

Hi all

I have a collection of ofMesh objects wrapped in ofNodes (the meshes are simple planes). I’m using an ofShader to bind ofVbo’s to my Mesh. I just went to alter the properties of the light and noticed that it no longer makes any difference now that I am using the shader and not a normal coloured mesh. How can I use both the ofShader and the ofLight to render my scene? Any advice would be greatly appreciated.

I found the original shader here - http://forum.openframeworks.cc/t/tutorial-:::-fbos,-textures,-shaders-in-of-007…/6843/4

Hi James,

I don’t think the code you are using accounts for lights. In that case, the the lights won’t influence the output of the shader. A sample of shaders using lights below ( I haven’t tested these specifically, but you can see the adjustments for lights).

http://www.geeks3d.com/20091013/shader-library-phong-shader-with-multiple-lights-glsl/

http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php

Thanks Nick. It looks like I’m going to have to investigate shaders further to implement this. I’ll post my findings.

I spent the last couple of days learning about shaders including reading this excellent set of tutorials:

http://www.lighthouse3d.com/tutorials/glsl-tutorial/

I tried to use shaders in this section -

http://www.lighthouse3d.com/tutorials/glsl-tutorial/combine-texture-fragment/

But my meshes are black.

Upon further investigation I found that this should be the minimum amount of code required to use a texture:

Vertex shader:

  
void main()  
{   
     gl_TexCoord[0] = gl_MultiTexCoord0;  
     gl_Position = ftransform();   
}  

Fragment shader:

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

But again, my objects are black. Most shaders I have found that use textures have use this approach. It seems that I can’t use the sampler2D.

I can’t figure out why this isn’t working. Any ideas?

Are you using ofDisableArbTex()? I pretty sure OF still defaults to non power of two textures.

Try something like the following grayscale frag shader:

  
uniform sampler2DRect tex0;  
  
void main(void)  
{  
	vec4 texcolor = texture2DRect(tex0, gl_TexCoord[0].st);   
	float gray = dot(texcolor.rgb, vec3(0.299, 0.587, 0.114));  
        gl_FragColor = vec4(gray, gray, gray, texcolor.a);  
}  

Keep in mind that sampler2DRect uses 0->width and 0->height texture coordinates, as opposed to sampler2D’s 0->1.

Thanks for your reply astellato. I followed your suggestion and used ofDisableArbTex(). I also normalised my texCoord values. Using the simple shaders I mentioned above (with sampler2D) produced the strange results below. It should look like the bottom image.

Weirdly, the texture now seems to contain a collection of characters. Even if I don’t draw anything into the ofFbo. I’m calling ofClear(0, 0, 0, 1); in the ofFbo so that isn’t the problem.

Does anyone have an example of a shader that combines a texture with lighting that works in OF?

Your grayscale shader worked btw although I’m trying to get the sampler2D to work. I had to include this line to get it to work:

  
#extension GL_ARB_texture_rectangle : enable  

Hi James,

I have made a sample app that loads in a texture and applies some diffuse shading to it. I don’t think that the position of the light is working correctly. :confused: But it seems to basically have what you are looking for. It is not double sided. I’m sure that this could be improved upon, but hope that this helps!

texture_light_shader.zip

Thanks for the example Nick. Really useful. Just managed to get it running in Code::Blocks without a problem. I’ll try to integrate this into my project when I get home later.

One big difference here is that you seem to be using ofMaterial. I didn’t even know this existed. Hopefully this was where I was going wrong.

Im glad it was useful. The material is not actually taken into account in the shader. You can comment out the material.begin() and .end() and you won’t notice a difference. You can use the material attributes in the shader by accessing its different characteristics like gl_FrontMaterial.shininess in the .frag

I don’t think that the gl_LightSource[0].position.xyz in the vertex shader is returning the correct light position. :confused: You can pass in the light position as a vec3 if it is not responding using gl_LightSource

I’ve got something that works now. Thanks again for your help Nick.

In terms of the issue using sampler2D in GLSL, I seem to have found what was causing the problem. I tried to alter your project to mimic what I was doing. You loaded an ofImage whereas I am using an ofFbo. For some reason, I can’t use an ofFbo as the shader texture with sampler2D. Even if I pass

  
myFbo.getTextureReference();   

So I’m using sampler2DRect.

I wonder if this is the only option when working with FBOs? or if there is just something I’m leaving out.

you can setup the fbo using a Settings struct like:

  
ofFbo::Settings settings;  
settings.width = ...;  
settings.height = ...;  
...  
settings.textureTarget = GL_TEXTURE_2D;  
  
fbo.allocate(settings);  

setting the textureTarget to GL_TEXTURE_2D makes it use internally a 2D texture instead of the default RECTANGLE_ARB and then you can use sampler2D in the shader

Thanks Arturo. I tried your suggestion but the 3D objects have now disappeared. I’m using the following:

  
      
ofFbo::Settings settings;  
settings.width = 160;  
settings.height = 40;  
settings.internalformat = GL_RGBA;  
settings.textureTarget = GL_TEXTURE_2D;  
fbo.allocate(settings);  
  

With these shaders from modified from Nick’s sample project:

Frag (changing sampler2DRect to sampler2D and texture2DRect to texture2D):

  
  
uniform sampler2D baseMap;  
varying vec3 vertex_light_position;  
varying vec3 norm;  
uniform float contrast;  
uniform float brightness;  
uniform float alpha;  
  
void main(void) {  
  
    /* Extract colors from baseMap */  
    vec4 baseColor      = texture2D( baseMap, gl_TexCoord[0].st );  
    vec3 normal			= normalize( norm );  
    float diffuse_value = max(dot(normal, vertex_light_position), 0.0);  
    vec4 alphaVec       = vec4(1, 1, 1, alpha);  
    baseColor.rgb       *= diffuse_value;  
  
    baseColor.rgb       *= contrast;  
    baseColor.rgb       += brightness;  
    baseColor            *= alpha;  
    gl_FragColor	    =	baseColor;  
}  
  

Vert:

  
  
varying vec3 vertex_light_position;  
varying vec3 norm;  
// [http://www.swiftless.com/tutorials/glsl/7-texturing.html](http://www.swiftless.com/tutorials/glsl/7-texturing.html) ///  
void main(void) {  
	 // Set the front color to the color passed through with glColor*f  
    gl_FrontColor = gl_Color;  
  
	 // Calculate the light position for this vertex  
    vertex_light_position = normalize(gl_LightSource[0].position.xyz);  
  
    norm = -1.0 * gl_NormalMatrix * gl_Normal;  
  
    /* Transform vertices and pass on texture coordinates */  
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;  
    gl_TexCoord[0] = gl_MultiTexCoord0;  
}  
  

Any ideas?

Figured out my mistake as soon as I posted. I forgot to convert the TexCoords to 1->0. Thanks again for your help.

@NickHardeman @jamesalliban do you still have the example attached in the previous reply? I’m having the exact same problem.

Hey Joa, the project I was working on at the time can be found here

I believe the code you’re looking for is here. Shaders are in the usual place.

I wrote this a few years ago and I was only just learning about shaders at the time so there are probably a few issues in the code. One I can see straight away is that I’m wrapping the shader around each individual plane rather than all of them collectively in CloudTagManager. I don’t believe mine was the most efficient approach. Basically go easy :smile:

Sure James, Thanks a lot for this. I’m learning shaders too so all the code where I can put my hands on will be a great help :slight_smile: