Jump to content
  • Advertisement
Sign in to follow this  
16bit_port

beginner glsl question

This topic is 3267 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, according to lighthouse3D.com: "You can create as many shaders as you want to add to a program, but remember that there can only be a main function for the set of vertex shaders and one main function for the set of fragment shaders in each single program." so does that mean I can do something like: v_main.vert :
   void main()
   {
	gl_Position = ftransform();
   }


f_main.frag :
   void main()
   {
        gl_FragColor = somecolor();
   }


f.frag :
   vec4 somecolor()
   {
        return vec4( 1.0, 0.0, 0.0, 1.0 );
   }


and assuming I compile and linked the program correctly:
	unsigned v = glCreateShader( GL_VERTEX_SHADER );
	unsigned f1 = glCreateShader( GL_FRAGMENT_SHADER );
	unsigned f2 = glCreateShader( GL_FRAGMENT_SHADER );

	const char *vs = (const char *)textFileRead( "shaders/v_main.vert" );
	const char *fs1 = (const char *)textFileRead( "shaders/f_main.frag" );
	const char *fs2 = (const char *)textFileRead( "shaders/f.frag" );

	glShaderSource( v, 1, &vs, NULL );
	glShaderSource( f1, 1, &fs1, NULL );
	glShaderSource( f2, 1, &fs2, NULL );

	glCompileShader( v );
	glCompileShader( f1 );
        glCompileShader( f2 );

	unsigned P = glCreateProgram();
	glAttachShader( P, v );
	glAttachShader( P, f1 );
	glAttachShader( P, f2 );

	glLinkProgram( P );


because well, I tried it and it doesn't work... I know I can put the somecolor function into f_main.frag and that would work:
vec4 somecolor()
{
	return vec4(1.0,0.0,0.0,1.0);
}

void main()
{
	gl_FragColor = somecolor();
}

but I'm just curious about what author meant in that quote when he says you can have multiple vertex shaders but they can only have 1 main function. How would that work? Edit: Also, lets say I have a lighting shader and texturing shader. If I want to use them on an object, would I have to create a completely new shader and combine them together (i.e. copy and paste and some modifications) or do I do a similar approach like the above where instead of having the lighting and texturing shaders in their own main functions, I put them into functions (and in their own files) and have the vert's main and frag's main call them? [Edited by - 16bit_port on December 3, 2009 1:45:51 PM]

Share this post


Link to post
Share on other sites
Advertisement
I think the ambiguity here stems from the fact that you can have a glsl program and a c/c++ program. glsl programs are really just 1 vertex shader and 1 fragment shader (and maybe even 1 geometry shader). but you can call glUseProgram() however many times in your c/c++ program for your render passes. so you could do:

glUseProgram (lightshader);
Draw();
glUseProgram (textureshader);
Draw();
glUseProgram (0); //return to fixed function when you are done

Share this post


Link to post
Share on other sites
Quote:
Original post by sdaq
I think the ambiguity here stems from the fact that you can have a glsl program and a c/c++ program. glsl programs are really just 1 vertex shader and 1 fragment shader (and maybe even 1 geometry shader). but you can call glUseProgram() however many times in your c/c++ program for your render passes. so you could do:

glUseProgram (lightshader);
Draw();
glUseProgram (textureshader);
Draw();
glUseProgram (0); //return to fixed function when you are done



So, regarding the main topic(multiple vertex/fragment shaders but only 1 main function for each type of shader in a program), you think what he wrote was incorrect?

Regarding the situation with lighting and texture shaders that you've posted, wouldn't that be inefficient though? I mean you're making 2 passes and you're not really combining the lighting and texture in a single pass, giving you an undesired result. I mean in what you posted, you're rendering a set of vertices with only lighting and then another set (possibly the same vertices) with just textures only.

Share this post


Link to post
Share on other sites
You can do some combining by specifying more than one source string to glShaderSource. It takes an array of strings with the source, so you could for example specify a header string, a function string, and a main string, where the main calls a function in the previous string. Then you only need to replace that particular string to change the function. Of course it depends on how much you can make it compatible if you require different inputs etc. to different shaders.

Share this post


Link to post
Share on other sites
Quote:
Original post by Erik Rufelt
You can do some combining by specifying more than one source string to glShaderSource. It takes an array of strings with the source, so you could for example specify a header string, a function string, and a main string, where the main calls a function in the previous string. Then you only need to replace that particular string to change the function. Of course it depends on how much you can make it compatible if you require different inputs etc. to different shaders.


Thanks. So I think I understand what you're saying. Assuming that the frag files that I posted in the first post is correct, I went and changed the way I linked the programs to:


unsigned v = glCreateShader( GL_VERTEX_SHADER );
unsigned f1 = glCreateShader( GL_FRAGMENT_SHADER );
// unsigned f2 = glCreateShader( GL_FRAGMENT_SHADER );

const char *vs = (const char *)textFileRead( "shaders/v_main.vert" );
const char *fs1 = (const char *)textFileRead( "shaders/f_main.frag" );
const char *fs2 = (const char *)textFileRead( "shaders/f.frag" );

const char* fragment_strings[2];
fragment_strings[0] = fs1;
fragment_strings[1] = fs2;

glShaderSource( v, 1, &vs, NULL );
glShaderSource( f1, 2, fragment_strings, NULL );
// glShaderSource( f2, 1, &fs2, NULL );

glCompileShader( v );
glCompileShader( f1 );
// glCompileShader( f2 );

unsigned P = glCreateProgram();
glAttachShader( P, v );
glAttachShader( P, f1 );
// glAttachShader( P, f2 );

glLinkProgram( P );



but it still doesn't work. Any ideas?

Share this post


Link to post
Share on other sites
The function must be visible to the main function, which it might not be if you include main before the other function.

I recommend using something like the following after glCompileShader, to read any error messages:

const GLsizei maxLen = 1024;
GLchar str[maxLen];
GLsizei len;
glGetShaderInfoLog(f1, maxLen, &len, str);


str will then contain a string with any errors that have occurred during shader compilation, which you can put in a message box or write to a log or similar.

Share this post


Link to post
Share on other sites
Quote:
Original post by Erik Rufelt
The function must be visible to the main function, which it might not be if you include main before the other function.

I recommend using something like the following after glCompileShader, to read any error messages:
*** Source Snippet Removed ***
str will then contain a string with any errors that have occurred during shader compilation, which you can put in a message box or write to a log or similar.


It works now. Thank you very much!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!