#include "framebuffer.hpp" slop::Framebuffer::Framebuffer( int w, int h ) { glGenFramebuffers( 1, &fbuffer ); glBindFramebuffer( GL_FRAMEBUFFER, fbuffer ); glGenTextures( 1, &image ); glBindTexture( GL_TEXTURE_2D, image ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); // generate our vertex and uv buffers std::vector verts; std::vector uvs; verts.push_back( glm::vec2(1,1) ); uvs.push_back( glm::vec2( 1, 1 ) ); verts.push_back( glm::vec2(-1,-1) ); uvs.push_back( glm::vec2( 0, 0 ) ); verts.push_back( glm::vec2(-1,1) ); uvs.push_back( glm::vec2( 0, 1 ) ); verts.push_back( glm::vec2(-1,-1) ); uvs.push_back( glm::vec2( 0, 0 ) ); verts.push_back( glm::vec2(1,1) ); uvs.push_back( glm::vec2( 1, 1 ) ); verts.push_back( glm::vec2(1,-1) ); uvs.push_back( glm::vec2( 1, 0 ) ); glGenBuffers( 2, buffers ); glBindBuffer( GL_ARRAY_BUFFER, buffers[0] ); glBufferData( GL_ARRAY_BUFFER, verts.size() * sizeof( glm::vec2 ), &verts[0], GL_STATIC_DRAW ); glBindBuffer( GL_ARRAY_BUFFER, buffers[1] ); glBufferData( GL_ARRAY_BUFFER, uvs.size() * sizeof( glm::vec2 ), &uvs[0], GL_STATIC_DRAW ); vertCount = verts.size(); generatedDesktopImage = false; } void slop::Framebuffer::setShader( slop::Shader* shader ) { this->shader = shader; if ( shader->hasParameter( "desktop" ) && !generatedDesktopImage ) { // Try to keep the image from being changed under our feet. XGrabServer(x11->display); XImage* image = XGetImage( x11->display, x11->root, 0, 0, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ), 0xffffffff, ZPixmap ); XUngrabServer(x11->display); glEnable(GL_TEXTURE_2D); glGenTextures(1, &desktopImage); glBindTexture(GL_TEXTURE_2D, desktopImage); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ), 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(image->data[0]))); XDestroyImage( image ); generatedDesktopImage = true; } } slop::Framebuffer::~Framebuffer() { glDeleteTextures(1, &image); glDeleteFramebuffers(1,&fbuffer); glDeleteBuffers(2,buffers); } void slop::Framebuffer::resize( int w, int h ) { // Regenerate the image glDeleteTextures(1, &image); glBindTexture(GL_TEXTURE_2D, image); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Re-bind it to the framebuffer glBindFramebuffer( GL_FRAMEBUFFER, fbuffer ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); } void slop::Framebuffer::bind() { glBindFramebuffer( GL_FRAMEBUFFER, fbuffer ); } void slop::Framebuffer::unbind() { glBindFramebuffer( GL_FRAMEBUFFER, 0 ); } void slop::Framebuffer::draw(glm::vec2 mouse, float time, glm::vec4 color){ shader->bind(); shader->setParameter( "texture", 0 ); shader->setAttribute( "position", buffers[0], 2 ); shader->setAttribute( "uv", buffers[1], 2 ); if ( shader->hasParameter( "mouse" ) ) { shader->setParameter( "mouse", mouse ); } if ( shader->hasParameter( "color" ) ) { shader->setParameter( "color", color ); } if ( shader->hasParameter( "screenSize" ) ) { shader->setParameter( "screenSize", glm::vec2( WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ) )); } if ( shader->hasParameter( "time" ) ) { shader->setParameter( "time", time ); } glActiveTexture(GL_TEXTURE0); glBindTexture( GL_TEXTURE_2D, image ); if ( shader->hasParameter( "desktop" ) ) { shader->setParameter( "desktop", 1 ); glActiveTexture(GL_TEXTURE0 + 1); glBindTexture( GL_TEXTURE_2D, desktopImage ); } glEnable( GL_TEXTURE_2D ); glDrawArrays( GL_TRIANGLES, 0, vertCount ); glDisable( GL_TEXTURE_2D ); shader->unbind(); }