Simple GLSL Shader Example


#1

Hi,

Many people recently asked me how to use GLSL within of. Actually I think there are allready a few threads that also helped me out on that topic but anyways I though it would be a good idea to post a simple example.
This basically uses the ofShader addon posted in the forums, I only changed and added a few things. Unfortunatelly I don’t know who the original made so if it was you, post it!
The example is really simple. It only uses one shader to color each fragment with it’s per pixel normal. The next step would be to use Frame Buffer Objects to make use of Multiple Render Targets and other cool features of OpenGL. I would recommend to everybody of you to write those classes on your own for two reasons:

  1. It makes alot of sense to understand what you are actually doing if you want to go beyond the basics.

  2. You can’t really put all FBO functionality into one class without making things complicated (at least I can not). That is so because for example shadow FBOs need a completely different setup than normal color buffers do.

To get started you will find some simple FBO examples on google and the of Forum,

no more talking, here is the code:

http://code.google.com/p/mokacode/downloads/list

Hope that helps!


#2

Hi moka!

thanks a lot for this, and i’m also looking forward for your other additions to mokacode :slight_smile:


#3

hehe, I don’t really have anything planned. I am just using it for things like this. even though I might pull something off with the time worth sharing as a whole library :slight_smile:


#4

Thanks Moka

Do you have any links or info about creating shaders, in terms of what to put into the .frag and .vert files?


#5

I can recommend you guys to check out the GLSL tutorial over at lighthouse 3D:
http://www.lighthouse3d.com/opengl/glsl/

Its a good starting point. Also the orange book was helping alot to get an understanding about how the GPU works and what Shaders do.


#6

Hi,

Thanks Moka fo sharing.

I’m not able to compile this example [oF06 on OsX]
I don’t get any helpful error message - I’m pointed to the line “GLint length = strlen(vs);” in ofxShader.cpp.

What could I be missing ?

Thanks,

Hugues.


#7

Hmm thats weird, are you sure you set up everything how it should be? You should try if it helps to also load the shaders into the xCode Project.


#8

To add the shaders to the xCode project was the solution. Thanks.


#9

Hi,

I’m trying now to merge two texture. But I only get a totally black texture.
[This is a merge of Moka example and I think a old shader example from Theo].

Is “setUniformVariable1i” the correct method to pass texture to the shader ?
What else I’m doing wrong ?

Here is the code:

  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	myShader.loadShader("textShader");  
	  
	w = 640;  
	h = 480;  
	texture1.allocate(w,h,GL_RGB);  
	texture2.allocate(w,h,GL_RGB);  
	  
	vidGrabber.setVerbose(true);  
	vidGrabber.initGrabber(w,h);  
	  
	// color pixels, use w and h to control red and green  
	colorPixels 		= new unsigned char [w*h*3];  
	for (int i = 0; i < w; i++){  
		for (int j = 0; j < h; j++){  
			colorPixels[(j*w+i)*3 + 0] = i;	// r  
			colorPixels[(j*w+i)*3 + 1] = j;	// g  
			colorPixels[(j*w+i)*3 + 2] = 0; // b  
		}  
	}  
	  
    // activate GL_TEXTURE4 as current ...  
    glActiveTexture(GL_TEXTURE4);  
    // bind my texture1 to GL_TEXTURE4  
    glBindTexture(GL_TEXTURE_2D, texture1.getTextureData().textureID);  
	  
    // the same with GL_TEXTURE5 and our second texture.  
    glActiveTexture(GL_TEXTURE5);  
    glBindTexture(GL_TEXTURE_2D, texture2.getTextureData().textureID);  
	  
    // go back to default texture unit !!  
    glActiveTexture(GL_TEXTURE0);   
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
	vidGrabber.grabFrame();  
	  
	if (vidGrabber.isFrameNew()){  
		unsigned char * pixels = vidGrabber.getPixels();  
		texture1.loadData(pixels, w,h, GL_RGB);  
	}  
	  
	texture2.loadData(colorPixels, w,h, GL_RGB);  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	  
	myShader.setShaderActive(true);  
	  
	myShader.setUniformVariable1i("tex1",int(GLuint(4)));  
	myShader.setUniformVariable1i("tex2" ,int(GLuint(5)) );  
	  
	texture1.draw(0,0,w,h);   
  
	myShader.setShaderActive(false);  
}  
  

the vertex shader :

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

the fragment shader:

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

Thanks.


#10

Hi moka,

i wanted to ask which OS/driver you are using…

in ofxShader::loadShader the ifs for “infobufferlen” return unconditionally. I had some trouble getting my shaders to run, since my driver (ATI Catalyst 9.04 under Windows XP) also replies into the InfoLog if the glCompileShaderARB was succesful ( “Vertex shader was successfully compiled to run on hardware”)… returning immediately after that results in not compiling the fragment-shader, not attaching or linking the objects.

I didn’t look up the correct protocol (opengl-wise), but maybe a return is not necessary at this point since it is an error _logging_ mechanism anyway?

Just wanted to let you know.

Cheers,
Misch


#11

i compile this in OF 0.06 and not works ok

i put the myshader.frag and myshader.vert in data/

i used windows, do you now we i cant use, the program copiled ok, but whe trid to open closed fast S:…

I apreciated your help…


#12

you need to add the shaders to the project of your program I guess (xcode codeblocks or whatever!)


#13

Hi Moka, how i can put this example Shader to the camera, or other examples i found with camara or videos, images etc…


#14

your question does not really make any sense, can you try to clearify what you want to do?


#15

hi, my error, i am very bad with english

i make all the tutorials in web about glsl and make with OF, but all the examples was make or glutsolidSphere, glutSolidSpot… etc, how can apply glsl to a webcam, like your apply with water example webcam with glsl, or the applys that make in this post

I want to now how can I convert this examples for webcam, I am not a expert programmer, I program the basic, can you redirect me to a tutorial, or something, I read about orange book glsl, but make me crazy, this is my question.
For example

http://www.clockworkcoders.com/oglsl/tutorial10.htm

here is an toon shader, imagine this in webcam, and see the webcam like cartoon, was very funny,. I have this in openframeworks in glut solidSphere, and many things

You understand me better??


#16

hey

if you want to apply the shader to a webcam
then you’re effectively applying the shader to a quad that fills the whole screen
the texture for that quad will be the image from your webcam

the problem is that to use conventional cel shaders, you need to apply the shader to 3d geometry. with a webcam that’s not generally possible since you’re applying the shader to a 2d surface with a flat texture (you dont know anything about the 3d geometry of the scene)

my question:
i’m in oF 0.061 in XCode and keep gettin EXC_BAD_ACCESS on the line

  
	loadShader(fragmentName, vertexName);  

of ofxShader

i presume it’s because it’s not finding my shader files correctly
where should i put them
tried in XCode project (under src, and at top level)
and also tried manually putting inside the application package

anyone got it working with 0061?


#17

I remember that if you add the shaders to your xCode project it should find them. Another possibility would be to put them in the data folder and use loadShader(ofToDataPath(…), ofToDataPath(…));

to you first question. a 2D quad is still geometry. It should simply work by defining a sampler2D in your shader and bind it to texture unit 0 (which whould be were the webcam texture is bound to).


#18

cel shaders need scene geometry
normals, positions

if you rasterise anything to a texture then you lose all the original scene geometry
the same way, if you take an image with a webcam, you dont have the scene geometry

you might be able to get a cel type shader which just works on the colour data, but it wont be able to produce the same results.

will check the filepath thing in a min (thanks!)


#19

fantastic, that works
now the beginning of the loadShader function in ofxShader looks like:

  
		char *vs = NULL,*fs = NULL;  
		  
		char * vertexPath = new char[1024];  
		char * fragmentPath = new char[1024];  
		  
		strcpy(vertexPath,ofToDataPath(vertexName).c_str());  
		strcpy(fragmentPath,ofToDataPath(fragmentName).c_str());  
		  
		vs = LoadShaderText(vertexPath);  
		fs = LoadShaderText(fragmentPath);  
		  
		delete []vertexPath;  
		delete []fragmentPath;  
		  
		vertexShader = (GLhandleARB)glCreateShader(GL_VERTEX_SHADER);  
		fragmentShader = (GLhandleARB)glCreateShader(GL_FRAGMENT_SHADER);  
  

it loads without error
will remember some GLSL in a bit!


#20

Hi,
Thanks for the great example:)
One question:
I had to copy the shader files to contents/MacOS folder opening .app file to get this work. Is this a right way? Or is there a smarter way to get the shaders included in the app file?