void ShaderToyApp::draw() { // Bind textures. if( mChannel0 ) mChannel0->bind( 0 ); if( mChannel1 ) mChannel1->bind( 1 ); if( mChannel2 ) mChannel2->bind( 2 ); if( mChannel3 ) mChannel3->bind( 3 ); // Render the current shader to a frame buffer. if( mShaderCurrent && mBufferCurrent ) { gl::ScopedFramebuffer fbo( mBufferCurrent ); // Bind shader. gl::ScopedGlslProg shader( mShaderCurrent ); setUniforms(); // Clear buffer and draw full screen quad (flipped). gl::clear(); gl::drawSolidRect( Rectf( 0, (float)getWindowHeight(), (float)getWindowWidth(), 0 ) ); } // Render the next shader to a frame buffer. if( mShaderNext && mBufferNext ) { gl::ScopedFramebuffer fbo( mBufferNext ); // Bind shader. gl::ScopedGlslProg shader( mShaderNext ); setUniforms(); // Clear buffer and draw full screen quad (flipped). gl::clear(); gl::drawSolidRect( Rectf( 0, (float)getWindowHeight(), (float)getWindowWidth(), 0 ) ); } // Perform a cross-fade between the two shaders. double time = getElapsedSeconds() - mTransitionTime; double fade = math<double>::clamp( time / mTransitionDuration, 0.0, 1.0 ); if( fade <= 0.0 ) { // Transition has not yet started. Keep drawing current buffer. gl::draw( mBufferCurrent->getColorTexture(), getWindowBounds() ); } else if( fade < 1.0 ) { // Transition is in progress. // Use a transition shader to avoid having to draw one buffer on top of another. gl::ScopedTextureBind tex0( mBufferCurrent->getColorTexture(), 0 ); gl::ScopedTextureBind tex1( mBufferNext->getColorTexture(), 1 ); gl::ScopedGlslProg shader( mShaderTransition ); mShaderTransition->uniform( "iSrc", 0 ); mShaderTransition->uniform( "iDst", 1 ); mShaderTransition->uniform( "iFade", (float)fade ); gl::drawSolidRect( getWindowBounds() ); } else if( mShaderNext ) { // Transition is done. Swap shaders. gl::draw( mBufferNext->getColorTexture(), getWindowBounds() ); mShaderCurrent = mShaderNext; mShaderNext.reset(); mPathCurrent = mPathNext; mPathNext.clear(); getWindow()->setTitle( std::string( "ShaderToyApp - Showing " ) + mPathCurrent.filename().string() ); } else { // No transition in progress. gl::draw( mBufferCurrent->getColorTexture(), getWindowBounds() ); } }