In Resolume we're using a function to compile and convert outdated shaders, i'll attach it below. We do require shaders to be at least glsl #version 120 and where they're using generic vertex attributes though. If you want to read more about providing generic vertex attributes you can read here
http://www.opengl-tutorial.org/beginner ... -triangle/.
It pretty much comes down to not using the fixed function pipeline attributes like gl_Vertex and instead creating your own attributes which you provide using glVertexAttribPointer.
Code: Select all
ShaderCompiler::Result ShaderCompiler::compile( GLenum shaderType, const char* shaderSource )
{
std::string patchedSource( shaderSource );
/**
* These checks are here to make sure that shaders are in a state that's most easilly upgradable to glsl version 410.
* All of these things can already be updated inside an OpenGL 2.1 context. For example instead of gl_Vertex
* you should be using generic vertex attributes. Instead of gl_ModelViewProjectionMatrix you should be using
* the renderer's matrix stack and uniforms.
*/
rassert( strncmp( shaderSource, "#version ", 9 ) == 0 ); //Specify the shader version so that we can automatically convert it in the future.
rassert( patchedSource.find( "gl_Vertex" ) == std::string::npos ); //Use generic vertex attributes (vPosition)
rassert( patchedSource.find( "gl_Color" ) == std::string::npos ); //Use generic vertex attributes (vColor)
rassert( patchedSource.find( "gl_MultiTexCoord0" ) == std::string::npos ); //Use generic vertex attributes, forward from vertex to fragment shader (vUV1)
rassert( patchedSource.find( "gl_MultiTexCoord1" ) == std::string::npos ); //Use generic vertex attributes, forward from vertex to fragment shader (vUV2)
rassert( patchedSource.find( "gl_TexCoord" ) == std::string::npos ); //Use generic vertex attributes, forward from vertex to fragment shader (vUV1)
rassert( patchedSource.find( "gl_ModelViewProjectionMatrix" ) == std::string::npos ); //Use renderer's matrix stack and custom uniform (WorldViewProj)
rassert( patchedSource.find( "ftransform" ) == std::string::npos ); //Use renderer's matrix stack and custom uniform (WorldViewProj * vPosition)
bool usesMRT = patchedSource.find( "gl_FragData[1]" ) != std::string::npos || patchedSource.find( "gl_FragData[ 1 ]" ) != std::string::npos;
if( !usesMRT )
rassert( patchedSource.find( "gl_FragData" ) == std::string::npos ); //Use gl_FragColor if you aren't using MRT. This enables automatic conversion of this shader to #version 410
//For now always convert all outdated shaders, untill someone will update all the shaders to be version 410 natively.
if( strncmp( shaderSource, "#version 120", 12 ) == 0 )
{
replaceAll( patchedSource, "#version 120", "#version 410" );
//We do sometimes sample textures in the Vertex shader so replace both in fragment and vertex shaders
if( shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER )
{
replaceAll( patchedSource, "texture2D(", "texture(" );
replaceAll( patchedSource, "texture2DArray(", "texture(" );
replaceAll( patchedSource, "texture2DRect(", "texture(" );
}
if( shaderType == GL_VERTEX_SHADER )
{
replaceAll( patchedSource, "attribute", "in" );
replaceAll( patchedSource, "varying", "out" );
}
else if( shaderType == GL_FRAGMENT_SHADER )
{
replaceAll( patchedSource, "varying", "in" );
patchedSource.insert( patchedSource.find( "\n" ) + 1, "out vec4 fragColor0;\n" );
replaceAll( patchedSource, "gl_FragColor", "fragColor0" );
replaceAll( patchedSource, "gl_FragData[0]", "fragColor0" );
replaceAll( patchedSource, "gl_FragData[ 0 ]", "fragColor0" );
if( usesMRT )
{
patchedSource.insert( patchedSource.find( "\n" ) + 1, "out vec4 fragColor1;\n" );
replaceAll( patchedSource, "gl_FragData[1]", "fragColor1" );
replaceAll( patchedSource, "gl_FragData[ 1 ]", "fragColor1" );
}
}
}
//Defines support omitted
//Include support omitted
Result result;
result.id = glCreateShader( shaderType );
if( result.id == 0 )
{
result.infoLog = "glCreateShader Failed";
return result;
}
const char* shaderStr = patchedSource.c_str();
glShaderSource( result.id, 1, (const GLchar**)&shaderStr, NULL );
glCompileShader( result.id );
GLint compiled;
glGetShaderiv( result.id, GL_COMPILE_STATUS, &compiled );
if( !compiled )
{
//always get log, because it might contain warnings that would
//give us a clue why a shader won't work
GLint logLength;
glGetShaderiv( result.id, GL_INFO_LOG_LENGTH, &logLength );
if( logLength != 0 )
{
std::vector< GLchar > log( logLength + 1 );
memset( log.data(), 0, logLength + 1 );
glGetShaderInfoLog( result.id, logLength, NULL, log.data() );
result.infoLog = log.data();
}
else
{
result.infoLog = "No Driver ShaderError log available.";
}
glDeleteShader( result.id );
result.id = 0;
}
return result;
}