コード例 #1
0
ファイル: Shader.cpp プロジェクト: GuoXinxiao/meshlab
void GPU::Shader::Release()
{
    if( m_Id )
    {
        if( m_VertPg.Id() )
        {
            glDetachObjectARB( m_Id, m_VertPg.Id() );
            m_VertPg.Release();
        }
        if( m_FragPg.Id() )
        {
            glDetachObjectARB( m_Id, m_FragPg.Id() );
            m_FragPg.Release();
        }
        if( m_GeomPg.Id() )
        {
            glDetachObjectARB( m_Id, m_GeomPg.Id() );
            m_GeomPg.Release();
        }

        glDeleteObjectARB( m_Id );
        m_Id = 0;

        m_Uniforms.clear();
        m_Attributes.clear();
    }
}
コード例 #2
0
ファイル: tr_gamma.c プロジェクト: belstgut/etlegacy
void R_ShutdownGamma(void)
{
	if (gammaProgram.program)
	{
		if (gammaProgram.vertexShader)
		{
			glDetachObjectARB(gammaProgram.program, gammaProgram.vertexShader);
			qglDeleteObjectARB(gammaProgram.vertexShader);
		}

		if (gammaProgram.fragmentShader)
		{
			glDetachObjectARB(gammaProgram.program, gammaProgram.fragmentShader);
			qglDeleteObjectARB(gammaProgram.fragmentShader);
		}

		qglDeleteObjectARB(gammaProgram.program);
		Com_Memset(&gammaProgram, 0, sizeof(shaderProgram_t));
	}

	if (screenImage)
	{
		screenImage = NULL;
	}
}
コード例 #3
0
ファイル: Shader.cpp プロジェクト: BSkin/MTG
Shader * Shader::loadShader(string name)
{
	Shader * s = new Shader();
	
	for (int i = 0; i < 5; i++) name.pop_back();
	s->name = name;

	string vertPath = name + ".vert";
	string fragPath = name + ".frag";

	//Start with a handle for the shader program...
	GLhandleARB shaderProgramHandle = glCreateProgramObjectARB ();

	//glBindAttribLocation (shaderProgramHandle, 0, "mg_vertex");
	//glBindAttribLocation (shaderProgramHandle, 1, "uv");
	// use glGetAttribLocation  instead

	GLhandleARB vertObject = makeShader(vertPath.c_str(), GL_VERTEX_SHADER);
	GLhandleARB fragObject = makeShader(fragPath.c_str(), GL_FRAGMENT_SHADER);
	glAttachObjectARB(shaderProgramHandle, vertObject);
	glAttachObjectARB(shaderProgramHandle, fragObject);

	glLinkProgramARB (shaderProgramHandle);
	
	//Find out if compilation worked and return the program handle if it did...
	int status; glGetObjectParameterivARB (shaderProgramHandle, GL_OBJECT_LINK_STATUS_ARB, &status);
	if (status != 0) 
	{
		//return shaderProgramHandle; //Everything OK...
		s->shaderProgram = shaderProgramHandle;
		s->vertexShader = vertObject;
		s->fragmentShader = fragObject;

		return s;
	}

	//It didn't, so log error information...
	//::log ("\nFailed to link shader \"%s\"...", name.c_str ());
	int length = 0; 
	glGetObjectParameterivARB (shaderProgramHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
	glBindFragDataLocation(shaderProgramHandle, 0, "outColour");

	const long MAXIMUM_LOG_STRING = 1024; char logString [MAXIMUM_LOG_STRING];
	GLsizei messageLength = min (length, MAXIMUM_LOG_STRING);
	if (messageLength > 0) {
		glGetInfoLogARB (shaderProgramHandle, messageLength, 0, logString);
	}

	//and detach what was previously attached and discard the program handle that was obtained...
	glDetachObjectARB(shaderProgramHandle, fragObject);
	glDetachObjectARB(shaderProgramHandle, vertObject);

	glDeleteObjectARB (shaderProgramHandle); //Should also detach the attached handles...

	return NULL;
}
コード例 #4
0
ファイル: r_shaders.c プロジェクト: inequation/ac130
static inline void r_destroy_program(uint prog, uint vs, uint fs) {
	OPENGL_EVENT_BEGIN(0, __PRETTY_FUNCTION__);

	glDetachObjectARB(prog, vs);
	glDetachObjectARB(prog, fs);
	glDeleteObjectARB(vs);
	glDeleteObjectARB(fs);
	glDeleteObjectARB(prog);

	OPENGL_EVENT_END();
}
コード例 #5
0
ファイル: GLSLLoader.cpp プロジェクト: SHIYUENING/topace
void ClearShaderObject(GLhandleARB GLSL_PO,GLhandleARB Attach_VS,GLhandleARB Attach_TC,GLhandleARB Attach_TE,GLhandleARB Attach_GS,GLhandleARB Attach_PS)
{
	if(glIsProgram(GLSL_PO)!=GL_FALSE)
	{
		if(glIsShader(Attach_VS)!=GL_FALSE){ glDetachObjectARB(GLSL_PO,Attach_VS);}
		if(glIsShader(Attach_TC)!=GL_FALSE){ glDetachObjectARB(GLSL_PO,Attach_TC);}
		if(glIsShader(Attach_TE)!=GL_FALSE){ glDetachObjectARB(GLSL_PO,Attach_TE);}
		if(glIsShader(Attach_GS)!=GL_FALSE){ glDetachObjectARB(GLSL_PO,Attach_GS);}
		if(glIsShader(Attach_PS)!=GL_FALSE){ glDetachObjectARB(GLSL_PO,Attach_PS);}
		glDeleteObjectARB(GLSL_PO);
	}
}
コード例 #6
0
void
ShaderModeData::FreeResources()
{
    // Free the program.
    if(GLSL_shaders_setup)
    {
        glDetachObjectARB(p, v);
        glDetachObjectARB(p, f);
        glDeleteObjectARB(v);
        glDeleteObjectARB(f);
        glDeleteObjectARB(p);
        GLSL_shaders_setup = false;
    }
}
コード例 #7
0
ファイル: C4Shader.cpp プロジェクト: 772/openclonk
void C4Shader::Clear()
{
#ifndef USE_CONSOLE
	if (!hProg) return;
	// Need to be detached, then deleted
	glDetachObjectARB(hProg, hFrag);
	glDetachObjectARB(hProg, hVert);
	glDeleteObjectARB(hFrag);
	glDeleteObjectARB(hVert);
	glDeleteObjectARB(hProg);
	hFrag = hVert = hProg = 0;
	// Clear uniform data
	delete[] pUniforms; pUniforms = NULL;
	iUniformCount = 0;
#endif
}
コード例 #8
0
ファイル: Shader.cpp プロジェクト: GuoXinxiao/meshlab
GPU::Shader& GPU::Shader::DetachGeomPg()
{
    if( m_Id && m_GeomPg.IsInstantiated() )
        glDetachObjectARB( m_Id, m_GeomPg.Id() );
    m_GeomPg.Release();
    return *this;
}
コード例 #9
0
ファイル: GLUtil.cpp プロジェクト: galexcode/Triumph
GLuint GLUtil::CreateShaderProgram(GLuint *shaderList, int nShaders) {
	if (nShaders > 0) {
		GLuint program = glCreateProgramObjectARB();
		
		// attach list of compiled shaders to the shader program
		for(size_t iLoop = 0; iLoop < nShaders; iLoop++)
			glAttachObjectARB(program, shaderList[iLoop]);
		
		//glBindAttribLocationARB(*program, 0, "position");
		
		glLinkProgramARB(program);
		
		// debugging
		if (true)
		{
		    GLchar *strInfoLog = new GLchar[1000];
		    GLsizei nChars;
		    glGetInfoLogARB(program, 999, &nChars, strInfoLog);
		    strInfoLog[999] = '\0';
		    
		    if (nChars != 0) {
		        Console::getInstance()->message(CONSOLE_MSG_SYS, "GLSL Linker: %s", strInfoLog);
		    }
		    delete[] strInfoLog;
		}
		
		// the shaders are no longer needed by the program once compiled
		for(size_t iLoop = 0; iLoop < nShaders; iLoop++)
		    glDetachObjectARB(program, shaderList[iLoop]);
		
		return program;
	}
	return 0;
    
}
コード例 #10
0
/*
 * link - Link the shader object.
 *
 * return - bool
 */
bool ShaderObject::link(void) {
    if (linked) {
        std::cout << "**warning** Object is already linked, trying to link again" << std::endl;
        for (int i = 0; i < shaderList.size(); i++) {
            glDetachObjectARB(shaderObject, shaderList[i]->getProgramObject());
            CHECK_GL_ERROR();
        }
    }
    for (int i = 0; i < shaderList.size(); i++) {
        glAttachObjectARB(shaderObject, shaderList[i]->getProgramObject());
        CHECK_GL_ERROR();
    }
    int linkStatus;
    glLinkProgramARB(shaderObject);
    CHECK_GL_ERROR();
    glGetObjectParameterivARB(shaderObject, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
    CHECK_GL_ERROR();
    if (linkStatus) {
        linked = true;
        return true;
    } else {
        std::cout << "**linker error**" << std::endl;
    }
    return false;
} // end link()
コード例 #11
0
ファイル: shaders.c プロジェクト: leonlee/tome
static int program_detach(lua_State *L)
{
	shader_type *p = (shader_type*)lua_touserdata(L, 1);
	GLuint *s = (GLuint*)auxiliar_checkclass(L, "gl{shader}", 2);

	glDetachObjectARB(p->shader, *s);

	return 0;
}
コード例 #12
0
ファイル: ofxShader.cpp プロジェクト: Joe-Z/OF_FractalTerrain
void ofxShader::unload() {
	if (vertexShader) {
		glDetachObjectARB(shader, vertexShader);
		glDeleteObjectARB(vertexShader);
		vertexShader = NULL;
	}

	if (fragmentShader) {
		glDetachObjectARB(shader, fragmentShader);
		glDeleteObjectARB(fragmentShader);
		fragmentShader = NULL;
	}

	if (shader) {
		glDeleteObjectARB(shader);
		shader = NULL;
	}
}
コード例 #13
0
void ofxShader::unload() {
	if(bLoaded) {
		if (vertexShader) {
			glDetachObjectARB(shader, vertexShader);
			glDeleteObjectARB(vertexShader);
			vertexShader = 0;
		}
		if (fragmentShader) {
			glDetachObjectARB(shader, fragmentShader);
			glDeleteObjectARB(fragmentShader);
			fragmentShader = 0;
		}
		if (shader) {
			glDeleteObjectARB(shader);
			shader = 0;
		}
	}
	bLoaded = false;
}
コード例 #14
0
ファイル: shaders.cpp プロジェクト: gorkinovich/IGr
	//--------------------------------------------------------------------------------------
	// Método para liberar un programa de la memoria de la tarjeta.
	//--------------------------------------------------------------------------------------
	void CShaderProgram::Release (void)
	{
		if(this->vertex.GetHandle())
		{
			glDetachObjectARB(this->program, this->vertex.GetHandle());
			this->vertex.Release();
		}

		if(this->fragment.GetHandle())
		{
			glDetachObjectARB(this->program, this->fragment.GetHandle());
			this->fragment.Release();
		}
		
		if(this->program)
		{
			glDeleteObjectARB(this->program);
			this->program = 0;
		}
	}
コード例 #15
0
ファイル: ccShader.cpp プロジェクト: eile/trunk
void ccShaderARB::reset()
{
    if (prog>0)
    {
        if (vert)
            glDetachObjectARB(prog, vert);
        if (frag)
            glDetachObjectARB(prog, frag);
        glDeleteObjectARB(prog);
    }
    prog=0;

    if (vert)
        glDeleteObjectARB(vert);
    vert=0;

    if (frag)
        glDeleteObjectARB(frag);
    frag=0;
}
コード例 #16
0
ファイル: GlProgram.cpp プロジェクト: KeckCAVES/crusta
void GlProgram::
removeShader(ShaderHandle& handle)
{
    //remove the shader from the program
    glDetachObjectARB(program, *handle);
    //delete the shader
    glDeleteObjectARB(*handle);
    shaders.erase(handle);
    //invalidate the handle
    handle = shaders.end();
}
コード例 #17
0
ファイル: GLShader.cpp プロジェクト: jrevote/3DA-Vrui
GLShader::~GLShader(void)
	{
	if(programObject!=0)
		{
		/* Detach all shaders from the shader program: */
		for(HandleList::iterator vsoIt=vertexShaderObjects.begin();vsoIt!=vertexShaderObjects.end();++vsoIt)
			glDetachObjectARB(programObject,*vsoIt);
		for(HandleList::iterator fsoIt=fragmentShaderObjects.begin();fsoIt!=fragmentShaderObjects.end();++fsoIt)
			glDetachObjectARB(programObject,*fsoIt);
		
		/* Delete the shader program: */
		glDeleteObjectARB(programObject);
		}
	
	/* Delete all shaders: */
	for(HandleList::iterator vsoIt=vertexShaderObjects.begin();vsoIt!=vertexShaderObjects.end();++vsoIt)
		glDeleteObjectARB(*vsoIt);
	for(HandleList::iterator fsoIt=fragmentShaderObjects.begin();fsoIt!=fragmentShaderObjects.end();++fsoIt)
		glDeleteObjectARB(*fsoIt);
	}
コード例 #18
0
ファイル: GLSLLoader.cpp プロジェクト: SHIYUENING/topace
void CGLSLLoader::ClearShader(void)
{
	if(!g_PO)
		return;
	if(glIsProgram(g_PO)!=GL_FALSE)
	{
		if(glIsShader(g_VS)!=GL_FALSE){ glDetachObjectARB(g_PO,g_VS); glDeleteObjectARB(g_VS);}
		if(glIsShader(g_TC)!=GL_FALSE){ glDetachObjectARB(g_PO,g_TC); glDeleteObjectARB(g_TC);}
		if(glIsShader(g_TE)!=GL_FALSE){ glDetachObjectARB(g_PO,g_TE); glDeleteObjectARB(g_TE);}
		if(glIsShader(g_GS)!=GL_FALSE){ glDetachObjectARB(g_PO,g_GS); glDeleteObjectARB(g_GS);}
		if(glIsShader(g_PS)!=GL_FALSE){ glDetachObjectARB(g_PO,g_PS); glDeleteObjectARB(g_PS);}
		glDeleteObjectARB(g_PS);
	}
	g_VS=0;
	g_TC=0;
	g_TE=0;
	g_GS=0;
	g_PS=0;
	g_PO=0;
}
コード例 #19
0
ファイル: shader.cpp プロジェクト: file-citas/sfs_testsuite
void shader::reload()
{
	GLenum err;
	//std::cerr << "reloading " << vert << ", " << frag << std::endl;
	glDetachObjectARB(shaderobj, vertexshader);
	glDetachObjectARB(shaderobj, fragmentshader);

	vertexshader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
	fragmentshader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

	char * source;
	source = GetSource(vert);
	glShaderSourceARB(vertexshader, 1, (const GLcharARB**)&source, NULL);

	source = GetSource(frag);
	glShaderSourceARB(fragmentshader, 1, (const GLcharARB**)&source, NULL);

	// compile the fragment and vertex shader
	glCompileShader(vertexshader);
	glCompileShader(fragmentshader);

	// attach shaders to shader obj
	glAttachObjectARB(shaderobj, vertexshader);
	glAttachObjectARB(shaderobj, fragmentshader);

	// link the shader obj and check status
	glLinkProgramARB(shaderobj);
	printInfoLog(shaderobj);

	//t_tex = 0;
	for(size_t i=0; i<value.size(); i++)
	{
		if(type.at(i)=='t') continue;//n_tex++;
		setUniform(i,value.at(i));
	}

	if((err=glGetError())!=0) {
		printf("\n%s: %d\n", __func__, __LINE__);
		exit(1);
	}
}
コード例 #20
0
ファイル: moShaderGLSL.cpp プロジェクト: inaes-tic/tv-moldeo
MOboolean moShaderGLSL::Finish()
{
    if (m_VertexShader != 0)
    {
        glDetachObjectARB(m_ProgramObject, m_VertexShader);
        m_VertexShader = 0;
    }
    if (m_FragmentShader != 0)
    {
        glDetachObjectARB(m_ProgramObject, m_FragmentShader);
        m_FragmentShader = 0;
    }

    if(m_ProgramObject != 0)
    {
        glDeleteObjectARB(m_ProgramObject);
        m_ProgramObject = 0;
    }

    return moShader::Finish();
}
コード例 #21
0
/*
 * ~ShaderObject - Destructor for ShaderObject.
 */
ShaderObject::~ShaderObject(void) {
    if (linkerLog != 0)
        free(linkerLog);
    for (int i = 0; i < shaderList.size(); i++) {
        glDetachObjectARB(shaderObject, shaderList[i]->getProgramObject());
        CHECK_GL_ERROR();
        if (manageMemory)
            delete shaderList[i];
    }
    glDeleteObjectARB(shaderObject);
    CHECK_GL_ERROR();
} // end ~ShaderObject()
コード例 #22
0
CShaderMngr::~CShaderMngr(void)
{
	for (auto iter = m_Shaders.begin();  iter != m_Shaders.end(); iter++) {
		glDetachObjectARB(iter->second->nProgID, iter->second->nShaderID);
		glDeleteObjectARB(iter->second->nProgID);
		glDeleteObjectARB(iter->second->nShaderID);

		delete iter->second;
	}

	m_Shaders.clear();
}
コード例 #23
0
GLGeometryShader::~GLGeometryShader(void)
	{
	if(programObject!=0)
		{
		/* Detach all geometry shaders from the shader program: */
		for(HandleList::iterator gsoIt=geometryShaderObjects.begin();gsoIt!=geometryShaderObjects.end();++gsoIt)
			glDetachObjectARB(programObject,*gsoIt);
		}
	
	/* Delete all geometry shaders: */
	for(HandleList::iterator gsoIt=geometryShaderObjects.begin();gsoIt!=geometryShaderObjects.end();++gsoIt)
		glDeleteObjectARB(*gsoIt);
	}
コード例 #24
0
ShaderProgram::~ShaderProgram()
{
	Uniform::Iter ui = uniforms.begin();
	for (; ui != uniforms.end(); ++ui) {
		delete ui->second;
	}
	Shader::Iter si = shaders.begin();
	for (; si != shaders.end(); ++si) {
		glDetachObjectARB(handle, (*si)->getHandle());
		delete *si;
	}
	glDeleteObjectARB(handle);
}
コード例 #25
0
ファイル: GlProgram.cpp プロジェクト: KeckCAVES/crusta
void GlProgram::
clear()
{
    //detach all the shaders from the program
    for (ShaderHandle it=shaders.begin(); it!=shaders.end(); ++it)
        glDetachObjectARB(program, *it);
    //delete the program
    glDeleteObjectARB(program);
    
    //delete all the shaders
    for (ShaderHandle it=shaders.begin(); it!=shaders.end(); ++it)
        glDeleteObjectARB(*it);
    shaders.clear();
}
コード例 #26
0
ファイル: GLShader.cpp プロジェクト: PengfeiXuAI/Sandbox
void GLShader::reset(void)
	{
	/* Check if the program has already been linked: */
	if(programObject!=0)
		{
		/* Detach all shaders from the shader program: */
		for(HandleList::iterator vsoIt=vertexShaderObjects.begin();vsoIt!=vertexShaderObjects.end();++vsoIt)
			glDetachObjectARB(programObject,*vsoIt);
		for(HandleList::iterator fsoIt=fragmentShaderObjects.begin();fsoIt!=fragmentShaderObjects.end();++fsoIt)
			glDetachObjectARB(programObject,*fsoIt);
		
		/* Delete the shader program: */
		glDeleteObjectARB(programObject);
		programObject=0;
		}
	
	/* Delete all shaders: */
	for(HandleList::iterator vsoIt=vertexShaderObjects.begin();vsoIt!=vertexShaderObjects.end();++vsoIt)
		glDeleteObjectARB(*vsoIt);
	vertexShaderObjects.clear();
	for(HandleList::iterator fsoIt=fragmentShaderObjects.begin();fsoIt!=fragmentShaderObjects.end();++fsoIt)
		glDeleteObjectARB(*fsoIt);
	fragmentShaderObjects.clear();
	}
コード例 #27
0
ファイル: glslShader.cpp プロジェクト: Neill3d/MoBu
bool GLSLShader::ReCompileShaders( const char* vertex_file, const char* fragment_file )
{
	FILE *fp = nullptr;
	/*
	fopen_s(&fp, vertex_file, "r");
	if (fp)
	{
		if (vertex) 
			if (!LoadShader( vertex, fp ) ) {
				fclose(fp);
				return false;
			}
		fclose(fp);
	}
	*/
	fopen_s(&fp, fragment_file, "r");
	if (fp)
	{
	
		if (fragment)

			glDetachObjectARB( programObj, fragment );
			glDeleteObjectARB( fragment );


			fragment = glCreateShaderObjectARB( GL_FRAGMENT_SHADER_ARB );
			if (!LoadShader( fragment, fp ) ) {
				fclose(fp);
				return false;
			}
			fclose(fp);

			// attach shader to program object
			glAttachObjectARB( programObj, fragment );

			GLint linked;
			// link the program object and print out the info log
			glLinkProgramARB( programObj );

			glGetObjectParameterivARB( programObj, GL_OBJECT_LINK_STATUS_ARB, &linked );
			loadlog( programObj );

			return (linked != 0);
	}

	return true;
}
コード例 #28
0
ファイル: GLSLShader.cpp プロジェクト: mhdsedighi/SOFA
///	This function frees all of our shader data
void GLSLShader::Release()
{
    for (std::map<GLint,GLhandleARB>::const_iterator it = m_hShaders.begin(), itend = m_hShaders.end(); it != itend; ++it)
    {
        GLhandleARB shader = it->second;
        if (shader && m_hProgramObject)
            glDetachObjectARB(m_hProgramObject, shader);
        if (shader)
            glDeleteObjectARB(shader);
    }
    m_hShaders.clear();

    // If our program object pointer is valid, free it
    if(m_hProgramObject)
    {
        glDeleteObjectARB(m_hProgramObject);
        m_hProgramObject = 0;
    }
}
コード例 #29
0
ファイル: Shader.cpp プロジェクト: GuoXinxiao/meshlab
GPU::Shader& GPU::Shader::Attach( const PgObject &pg )
{
    PgObject *dst = NULL;

    switch( pg.Type() )
    {
        case GL_VERTEX_SHADER_ARB:   dst = &m_VertPg; break;
        case GL_FRAGMENT_SHADER_ARB: dst = &m_FragPg; break;
        case GL_GEOMETRY_SHADER_EXT: dst = &m_GeomPg; break;
    }

    if( dst )
    {
        if( m_Id && dst->IsInstantiated() )
            glDetachObjectARB( m_Id, dst->Id() );
        *dst = pg;
    }

    return *this;
}
コード例 #30
0
int main(int argc, char **argv)
{
   float r = 0.5, g = 0.5, b = 1, ratio = 0;
   int dir = 1;
   ALLEGRO_DISPLAY *display;
   ALLEGRO_BITMAP *mysha;
   ALLEGRO_BITMAP *buffer;

   const char *tinter_shader_src[] = {
      "uniform sampler2D backBuffer;",
      "uniform float r;",
      "uniform float g;",
      "uniform float b;",
      "uniform float ratio;",
      "void main() {",
      "	vec4 color;",
      "	float avg, dr, dg, db;",
      "	color = texture2D(backBuffer, gl_TexCoord[0].st);",
      "	avg = (color.r + color.g + color.b) / 3.0;",
      "	dr = avg * r;",
      "	dg = avg * g;",
      "	db = avg * b;",
      "	color.r = color.r - (ratio * (color.r - dr));",
      "	color.g = color.g - (ratio * (color.g - dg));",
      "	color.b = color.b - (ratio * (color.b - db));",
      "	gl_FragColor = color;",
      "}"
   };
   const int TINTER_LEN = 18;
   double start;
   GLint loc;

   (void)argc;
   (void)argv;

   if (!al_init()) {
      abort_example("Could not init Allegro\n");
   }

   al_install_keyboard();
   al_init_image_addon();

   al_set_new_display_flags(ALLEGRO_OPENGL);
   display = al_create_display(320, 200);
   if (!display) {
      abort_example("Error creating display\n");
   }

   mysha = al_load_bitmap("data/mysha.pcx");
   if (!mysha) {
      abort_example("Could not load image.\n");
   }

   buffer = al_create_bitmap(320, 200);

   if (!al_have_opengl_extension("GL_EXT_framebuffer_object")
      && !al_have_opengl_extension("GL_ARB_fragment_shader")) {
      abort_example("Fragment shaders not supported.\n");
   }

   tinter_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

   glShaderSourceARB(tinter_shader, TINTER_LEN, tinter_shader_src, NULL);
   glCompileShaderARB(tinter_shader);
   tinter = glCreateProgramObjectARB();
   glAttachObjectARB(tinter, tinter_shader);
   glLinkProgramARB(tinter);
   loc = glGetUniformLocationARB(tinter, "backBuffer");
   glUniform1iARB(loc, al_get_opengl_texture(buffer));

   start = al_get_time();

   while (1) {
      double now, diff;
      ALLEGRO_KEYBOARD_STATE state;
      al_get_keyboard_state(&state);
      if (al_key_down(&state, ALLEGRO_KEY_ESCAPE)) {
         break;
      }
      now = al_get_time();
      diff = now - start;
      start = now;
      ratio += diff * 0.5 * dir;
      if (dir < 0 && ratio < 0) {
         ratio = 0;
         dir = -dir;
      }
      else if (dir > 0 && ratio > 1) {
         ratio = 1;
         dir = -dir;
      }

      al_set_target_bitmap(buffer);

      glUseProgramObjectARB(tinter);
      loc = glGetUniformLocationARB(tinter, "ratio");
      glUniform1fARB(loc, ratio);
      loc = glGetUniformLocationARB(tinter, "r");
      glUniform1fARB(loc, r);
      loc = glGetUniformLocationARB(tinter, "g");
      glUniform1fARB(loc, g);
      loc = glGetUniformLocationARB(tinter, "b");
      glUniform1fARB(loc, b);
      al_draw_bitmap(mysha, 0, 0, 0);
      glUseProgramObjectARB(0);

      al_set_target_backbuffer(display);
      al_draw_bitmap(buffer, 0, 0, 0);
      al_flip_display();
      al_rest(0.001);
   }

   glDetachObjectARB(tinter, tinter_shader);
   glDeleteObjectARB(tinter_shader);

   al_uninstall_system();

   return 0;
}