OpenWalnut  1.4.0
WGEOffscreenRenderPass.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include <string>
00026 
00027 
00028 #include <osg/Texture>
00029 #include <osg/Texture2D>
00030 
00031 #include "core/common/WLogger.h"
00032 #include "../WGETextureHud.h"
00033 
00034 #include "WGEOffscreenRenderPass.h"
00035 
00036 WGEOffscreenRenderPass::WGEOffscreenRenderPass( size_t textureWidth, size_t textureHeight, int num ):
00037     WGECamera(),
00038     m_width( textureWidth ),
00039     m_height( textureHeight ),
00040     m_fbo( new osg::FrameBufferObject() ),
00041     m_hud( NULL )
00042 {
00043     // initialize members
00044     setClearColor( osg::Vec4( 0.0, 0.0, 0.0, 0.0 ) );
00045     setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00046     setReferenceFrame( osg::Transform::RELATIVE_RF );
00047     setRenderTargetImplementation( WGECamera::FRAME_BUFFER_OBJECT );
00048     setRenderOrder( WGECamera::PRE_RENDER, num );
00049 }
00050 
00051 WGEOffscreenRenderPass::WGEOffscreenRenderPass( size_t textureWidth, size_t textureHeight, osg::ref_ptr< WGETextureHud > hud, std::string name,
00052                                                 int num ):
00053     WGECamera(),
00054     m_width( textureWidth ),
00055     m_height( textureHeight ),
00056     m_fbo( new osg::FrameBufferObject() ),
00057     m_hud( hud ),
00058     m_name( name )
00059 {
00060     // initialize members
00061     setClearColor( osg::Vec4( 0.0, 0.0, 0.0, 0.0 ) );
00062     setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00063     setReferenceFrame( osg::Transform::RELATIVE_RF );
00064     setRenderTargetImplementation( WGECamera::FRAME_BUFFER_OBJECT );
00065     setRenderOrder( WGECamera::PRE_RENDER, num );
00066 }
00067 
00068 WGEOffscreenRenderPass::~WGEOffscreenRenderPass()
00069 {
00070     // cleanup
00071 }
00072 
00073 void WGEOffscreenRenderPass::attach( BufferComponent buffer, osg::ref_ptr< osg::Texture2D > texture )
00074 {
00075     m_fbo->setAttachment( buffer, osg::FrameBufferAttachment( texture ) );
00076 
00077     if( m_hud )
00078     {
00079         m_hud->addTexture( new WGETextureHud::WGETextureHudEntry( texture, m_name + " - " + getBufferName( buffer ) ) );
00080     }
00081 
00082     // allow mipmap generation, but set desired levels to 0. Allow the user to set this higher
00083     texture->setUseHardwareMipMapGeneration( true );
00084     texture->setNumMipmapLevels( 0 );
00085 
00086     // attach
00087     WGECamera::attach( buffer, texture, 0, 0, true );
00088 }
00089 
00090 void WGEOffscreenRenderPass::attach( BufferComponent buffer, osg::ref_ptr< osg::Image > image )
00091 {
00092     WGECamera::attach( buffer, image );
00093 }
00094 
00095 osg::ref_ptr< osg::Texture2D > WGEOffscreenRenderPass::attach( BufferComponent buffer, GLint internalFormat )
00096 {
00097     osg::ref_ptr< osg::Texture2D > tex;
00098     if( buffer == DEPTH_BUFFER )   // depth buffers need a special texture type (else: FBO status = 0x8cd6 (FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT))
00099     {
00100         tex = createTexture( GL_DEPTH_COMPONENT );
00101     }
00102     else
00103     {
00104 #if defined(__APPLE__)
00105         if( internalFormat != GL_RGBA )
00106         {
00107             wlog::warn( "WGEOffscreenRenderPass::attach:" ) <<
00108                 "Changing internal format to GL_RGBA because the original format is not supported on Mac OSX.";
00109         }
00110         tex = createTexture( GL_RGBA );           // on MacOS X, only RGBA textures work as attachment for FBO's
00111 #else
00112         tex = createTexture( internalFormat );
00113 #endif
00114     }
00115     attach( buffer, tex );
00116     return tex;
00117 }
00118 
00119 void WGEOffscreenRenderPass::detach( BufferComponent buffer )
00120 {
00121     // remove the texture from HUD if existing
00122     if( m_hud && WGECamera::getBufferAttachmentMap().count( buffer ) )
00123     {
00124         m_hud->removeTexture( WGECamera::getBufferAttachmentMap()[ buffer ]._texture );
00125     }
00126 
00127     m_fbo->setAttachment( buffer, osg::FrameBufferAttachment() );
00128 
00129     WGECamera::detach( buffer );
00130 }
00131 
00132 osg::ref_ptr< osg::Texture2D > WGEOffscreenRenderPass::createTexture( GLint internalFormat )
00133 {
00134     osg::ref_ptr< osg::Texture2D > tex = new osg::Texture2D;
00135     tex->setTextureSize( m_width, m_height );
00136     tex->setInternalFormat( internalFormat );
00137 
00138     switch( internalFormat )
00139     {
00140     case GL_R16F:
00141         tex->setSourceType( GL_HALF_FLOAT );
00142         tex->setSourceFormat( GL_RED );
00143         break;
00144     case GL_R32F:
00145         tex->setSourceType( GL_FLOAT );
00146         tex->setSourceFormat( GL_RED );
00147         break;
00148 
00149 // Those ifdef's where introduced, as otherwise OW would not compile on older platforms where no newer OpenGL is available.
00150 #ifdef GL_RGB16F
00151     case GL_RGB16F:
00152         tex->setSourceType( GL_HALF_FLOAT );
00153         tex->setSourceFormat( GL_RGB );
00154         break;
00155 #endif
00156 #ifdef GL_RGBA16F
00157     case GL_RGBA16F:
00158         tex->setSourceType( GL_HALF_FLOAT );
00159         tex->setSourceFormat( GL_RGBA );
00160         break;
00161 #endif
00162 #ifdef GL_RGB32F
00163      case GL_RGB32F:
00164         tex->setSourceType( GL_FLOAT );
00165         tex->setSourceFormat( GL_RGB );
00166         break;
00167 #endif
00168 #ifdef GL_RGBA32F
00169      case GL_RGBA32F:
00170         tex->setSourceType( GL_FLOAT );
00171         tex->setSourceFormat( GL_RGBA );
00172         break;
00173 #endif
00174 
00175     default:
00176         // keep default format and type
00177         break;
00178     }
00179 
00180     // setup interpolation
00181     tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR );
00182     tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
00183 
00184     // do repeat the texture
00185     tex->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
00186     tex->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
00187 
00188     return tex;
00189 }
00190 
00191 std::string WGEOffscreenRenderPass::getName() const
00192 {
00193     return m_name;
00194 }
00195 
00196 size_t WGEOffscreenRenderPass::getTextureWidth() const
00197 {
00198     return m_width;
00199 }
00200 
00201 size_t WGEOffscreenRenderPass::getTextureHeight() const
00202 {
00203     return m_height;
00204 }
00205 
00206 void WGEOffscreenRenderPass::addUniform( osg::ref_ptr< osg::Uniform > uniform )
00207 {
00208     this->getOrCreateStateSet()->addUniform( uniform );
00209 }
00210 
00211 std::string WGEOffscreenRenderPass::getBufferName( BufferComponent buffer )
00212 {
00213     switch( buffer )
00214     {
00215         case DEPTH_BUFFER:
00216             return "Depth";
00217         case STENCIL_BUFFER:
00218             return "Stencil";
00219         case PACKED_DEPTH_STENCIL_BUFFER:
00220             return "Depth+Stencil";
00221         case COLOR_BUFFER:
00222             return "Color 0";
00223         case COLOR_BUFFER0:
00224             return "Color 0";
00225         case COLOR_BUFFER1:
00226             return "Color 1";
00227         case COLOR_BUFFER2:
00228             return "Color 2";
00229         case COLOR_BUFFER3:
00230             return "Color 3";
00231         case COLOR_BUFFER4:
00232             return "Color 4";
00233         case COLOR_BUFFER5:
00234             return "Color 5";
00235         case COLOR_BUFFER6:
00236             return "Color 6";
00237         case COLOR_BUFFER7:
00238             return "Color 7";
00239         case COLOR_BUFFER8:
00240             return "Color 8";
00241         case COLOR_BUFFER9:
00242             return "Color 9";
00243         case COLOR_BUFFER10:
00244             return "Color 10";
00245         case COLOR_BUFFER11:
00246             return "Color 11";
00247         case COLOR_BUFFER12:
00248             return "Color 12";
00249         case COLOR_BUFFER13:
00250             return "Color 13";
00251         case COLOR_BUFFER14:
00252             return "Color 14";
00253         case COLOR_BUFFER15:
00254             return "Color 15";
00255         default:
00256             return "Unknown";
00257     }
00258 }
00259