Linking multiple glsl source files into one program
Right now, I'm not certain if it's my GLSL code that's to blame, or my C++ code calling gl functions to attach multiple glsl source files into one program.
Anyway, my situation is that I want to define a few useful functions in a single glsl file. Then, other glsl files, which define a main(), can call those functions.
What I'm not certain about is whether I'm linking the two files ( into one program ) incorrectly, of if I'm defining my functions ( in the "library" file ) incorrectly.
First, the error I'm getting is this:
"ERROR: 0:14: 'GC_blurredFragment' : no matching overloaded function found"
Where, "GC_blurredFragment" is a function defined in the file "gaussian_combiner_lib.fs":
gaussian_combiner_lib.fs:
And here's the file, "bloom_mix.fs" which calls those functions:
My code which attaches the two files to one program is here:
The implementation of the method glsl::Program::attachFile ( and dependant other methods ) is here:
So, can anybody help me? Is it even possible to define a "library" which defines methods which other files can call?
For what it's worth, my glsl code works if I define it all in one file, I just want to eliminate redundant code... since I have a lot of filters which do the same stuff and might as well recycle one library of functions.
Anyway, my situation is that I want to define a few useful functions in a single glsl file. Then, other glsl files, which define a main(), can call those functions.
What I'm not certain about is whether I'm linking the two files ( into one program ) incorrectly, of if I'm defining my functions ( in the "library" file ) incorrectly.
First, the error I'm getting is this:
"ERROR: 0:14: 'GC_blurredFragment' : no matching overloaded function found"
Where, "GC_blurredFragment" is a function defined in the file "gaussian_combiner_lib.fs":
gaussian_combiner_lib.fs:
Code:
uniform float downsampleFactor;
uniform sampler2DRect srcImage;
uniform sampler2DRect blurredImage;
vec4 GC_blurredFragment( void )
{
return texture2DRect( blurredImage, gl_FragCoord.st / downsampleFactor );
}
vec4 GC_sourceFragment( void )
{
return texture2DRect( srcImage, gl_FragCoord.st );
}And here's the file, "bloom_mix.fs" which calls those functions:
Code:
uniform float alpha;
uniform float lumaScale;
uniform float lumaPower;
uniform float lumaMin;
uniform float lumaMax;
void main( void )
{
vec3 src = GC_blurredFragment().rgb;
vec3 dst = GC_sourceFragment().rgb;
//Get luminance
float luma = dot( vec3( 0.299, 0.587, 0.114 ), src );
//Ramp luma from lumaMin to lumaMax, raise it to power, and multiply it by lumaScale
luma = min( pow( smoothstep( lumaMin, lumaMax, luma ), lumaPower ) * lumaScale, 1.0 );
//Now ramp from dst to ( dst + luma ) by alpha
gl_FragColor = vec4( mix( dst, dst + vec3( luma ), alpha ).rgb, 1.0 );
}My code which attaches the two files to one program is here:
Code:
_mixProgram.attachFile( PATH( shaderFolder() + "gaussian_combiner_lib.fs" ), glsl::Program::Fragment );
_mixProgram.attachFile( PATH( shaderFolder() + _mixProgramPath ), glsl::Program::Fragment );
_mixProgram.link();The implementation of the method glsl::Program::attachFile ( and dependant other methods ) is here:
Code:
void Program::attachFile( const std::string &file, shader_type type )
{
try
{
attachString( read( file ), type );
}
catch ( const Exception &e )
{
throw Exception( "error compiling file: \"" + file + "\"", e.error );
}
}
void Program::attachString( const std::string &programString, shader_type type )
{
glError();
const char *dataStr = programString.c_str();
GLhandleARB shader = 0;
switch( type )
{
case Vertex: shader = glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB ); break;
case Fragment: shader = glCreateShaderObjectARB( GL_FRAGMENT_SHADER_ARB ); break;
}
glShaderSourceARB( shader, 1, (const GLcharARB **)(&dataStr), NULL );
std::string error;
if ( !compile( shader, error ))
{
throw Exception( "compile error", error );
}
if ( !_program )
{
_program = glCreateProgramObjectARB();
}
glError();
glAttachObjectARB( _program, shader );
glDeleteObjectARB( shader );
glError();
}
void Program::link( void )
{
glError();
glLinkProgramARB( _program );
std::string error;
if ( infoLog( _program, error ))
{
throw Exception( "link error", error );
}
GLint linked;
glGetObjectParameterivARB( _program, GL_OBJECT_LINK_STATUS_ARB, &linked );
_linked = linked != 0;
glError();
}
std::string Program::read( const std::string &filename )
{
using namespace std;
fstream file( filename.c_str(), ios::in | ios::binary | ios::ate );
long size = file.tellg();
file.seekg(0, ios::beg);
if (size <= 0)
{
throw Exception( "glsl::Program::read", "Couldn't open file: \"" + filename + "\"" );
}
char *buf = new char[size + 1];
memset(buf, '\0', size + 1); //be damn certain about null terminator
file.read(buf, size);
file.close();
string text(buf);
delete [] buf;
return text;
}
bool Program::infoLog( GLhandleARB obj, std::string &log )
{
GLint infologLength = 0;
GLsizei charsWritten = 0;
char *infoLog;
glGetObjectParameterivARB( obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
&infologLength);
if (infologLength > 0)
{
infoLog = new char[ infologLength ];
glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
log = infoLog;
delete [] infoLog;
return true;
}
return false;
}So, can anybody help me? Is it even possible to define a "library" which defines methods which other files can call?
For what it's worth, my glsl code works if I define it all in one file, I just want to eliminate redundant code... since I have a lot of filters which do the same stuff and might as well recycle one library of functions.
can you not just read in both files, concatenate them and then send that to be compiled as a shader program?
Sir, e^iπ + 1 = 0, hence God exists; reply!
Technically, yes, but I was under the impression that GLSL's attach/compile/link cycle was designed for exactly this sort of usage...
Unfortunately, linking multiple shaders together into one program is not often done, and therefore not well-tested. When I tried to do this originally, I had serious issues on both NVidia/Linux and Mac OS X. Unfortunately, I no longer have access to the bug number to know whether that particular issue was fixed... though my recollection is that it was.
I've written code for linking multiple shaders into one program here: http://onesadcookie.com/trac/browser/Kiloplane/shader.c though I don't know if I've ever tested it. Might be worth a look, anyway.
I've written code for linking multiple shaders into one program here: http://onesadcookie.com/trac/browser/Kiloplane/shader.c though I don't know if I've ever tested it. Might be worth a look, anyway.
Well, your code's doing the same thing as mine, as far as I can tell. The only difference is that I free my shader object immediately after attaching it to the program, whereas you free it when the program is deleted. I'd be surprised if that makes any difference.
Well, I'm just going to have to live with cut-n-paste boilerplate...
Well, I'm just going to have to live with cut-n-paste boilerplate...
Oh, I think I know what your problem might be -- a lack of a function prototype for the functions declared in other shaders
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| OpenAL - Ogg files vs Caf files | Fred9000 | 8 | 11,763 |
Aug 23, 2011 08:01 PM Last Post: ipeku |
|
| ios/mac shader - shared glsl source | OptimisticMonkey | 2 | 4,412 |
Jun 17, 2011 08:59 AM Last Post: OptimisticMonkey |
|
| Multiple render targets in GLSL... glFragData[] | TomorrowPlusX | 5 | 8,901 |
Oct 17, 2008 01:36 PM Last Post: OneSadCookie |
|
| GLSL and multi file linking | TomorrowPlusX | 4 | 2,921 |
Jun 16, 2008 03:48 PM Last Post: OneSadCookie |
|
| Problem linking GLSL | Ilyasim | 4 | 3,330 |
Dec 18, 2007 12:46 PM Last Post: OneSadCookie |
|

