几何尺寸与公差论坛

 找回密码
 注册
查看: 2691|回复: 2

OpenCSG-1.0.2 sample

[复制链接]
发表于 2007-7-22 16:40:15 | 显示全部楼层 |阅读模式
1.RenderTexture.h
//------------------------------------------------------------------------------
// File : RenderTexture.h
//------------------------------------------------------------------------------
// Copyright (c) 2002-2004 Mark J. Harris
//---------------------------------------------------------------------------
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any
// damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any
// purpose, including commercial applications, and to alter it and
// redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you
//    must not claim that you wrote the original software. If you use
//    this software in a product, an acknowledgment in the product
//    documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and
//    must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
// -----------------------------------------------------------------------------
// Credits:
// Original RenderTexture code: Mark J. Harris
// Original Render-to-depth-texture support: Thorsten Scheuermann
// Linux Copy-to-texture: Eric Werness
// Various Bug Fixes: Daniel (Redge) Sperl
//                    Bill Baxter
//                    Florian Kirsch
//                    Andrew Wood
//
// -----------------------------------------------------------------------------
/**
* @file RenderTexture.h
*
* Interface definition for class RenderTexture.  A multi-format render to
* texture wrapper.
*/
#ifndef __RENDERTEXTURE2_HPP__
#define __RENDERTEXTURE2_HPP__
#include <GL/glew.h>
#ifdef _WIN32
#include <GL/wglew.h>
#else
#include <GL/glxew.h>
#endif
#include <string>
#include <vector>
/* The pixel format for the pbuffer is controlled by the mode string passed
* into the PBuffer constructor. This string can have the following attributes:
*
* To specify the pixel format, use the following syntax.
*   <channels>=<bits>
* <channels> must match one of the following.
*
* r      - r pixel format (for float buffer).
* rg     - rg pixel format (for float buffer).
* rgb          - rgb pixel format. 8 bit or 16/32 bit in float buffer mode
* rgba         - same as "rgb alpha" string
*
* <bits> can either be a scalar--meaning the same bit depth for each
* channel-- or a 2-, 3-, 4-component vector matching the specified number of
* channels. Vector components should be comma separated. An optional 'f'
* suffix on the bit depth specifies float components.  In this case <bits>
* must be either "32f" or "16f".  If <bits> is empty, the default 8 bits per
* channel will be used.
*   r=32f
*   rg=16f
*   rgb=8
*   rgb=5,6,5
*
* The following other attributes are supported.
*
* depth=n      - must have n-bit depth buffer, omit n for default (24 bits)
* stencil=n    - must have n-bit stencil buffer, omit n for default (8 bits)
* samples=n    - must support n-sample antialiasing (n can be 2 or 4)
* aux=n        - must have n AUX buffers
* doublebuffer - must support double buffered rendering
* singlebuffer - do not support double buffered rendering
*
* tex2D
* texRECT
* texCUBE  - must support binding pbuffer as texture to specified target
*          - binding the depth buffer is also supported by specifying
* depthTex2D
* depthTexRECT
* depthTexCUBE
*          - Both depth and color texture binding, may be specified, but
*            the targets must match!
*            For example: "tex2D depthTex2D" or "texRECT depthTexRECT"
*
* rtt
* ctt      - These mutually exclusive options specify the update method used
*            for render textures that support texture binding. "rtt"
*            indicates that render to texture will be used to update the
*            texture. "ctt" indicates that copy to texture will be used
*            (i.e. glCopyTexSubImage2D()). "rtt" is the default if neither is
*            specified, and one of the "tex*" options above is.
*
*
*---------------------------------------------------------------------------
*
* USAGE NOTES:
*
* * Texture Parameters:
*   The default texture wrap mode is GL_CLAMP_TO_EDGE for all textures, and
*   the default texture filtering modes (min and mag) are GL_NEAREST.
*   To change these parameters, simply bind the RenderTexture (using the
*   Bind() method), and set them the way you would for any GL texture object.
*   The same goes for depth textures.
*
* * Enabling Mipmapping:
*   This is similar to the texture parameters above.  When "rtt" is specified
*   in the mode string, "mipmap" must also be specified in order to enable
*   a mipmapped pbuffer.  Then, the mipmaps must be created by enabling the
*   GL_SGIS_GENERATE_MIPMAP texture parameter in the same way as above, and
*   the min filter mode must be set to a mipmap filter mode, as with any
*   mipmapped texture object.
*
* * Enabling Anisotropic Filtering  
*   As with the texture parameters above, except as in the following code:
*   glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, max);
*   glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, <value < max>);
*/
class RenderTexture
{
public: // enums
    enum UpdateMode
    {
        RT_RENDER_TO_TEXTURE,
        RT_COPY_TO_TEXTURE
    };
   
public: // interface
    // ctor / dtor
    RenderTexture(const char *strMode="rgb tex2D");
    ~RenderTexture();
   
    //! Call this once before use.  Set bShare to true to share lists, textures,
    //! and program objects between the render texture context and the
    //! current active GL context.
    bool Initialize(int width, int height,
                    bool shareObjects=true,
                    bool copyContext=false);
    // !Change the render texture format.
    bool Reset(const char* strMode,...);
    // !Change the size of the render texture.
    bool Resize(int width, int height);
   
    // !Begin drawing to the texture. (i.e. use as "output" texture)
    bool BeginCapture();
    // !Ends drawing to 'current', begins drawing to this RenderTexture
    bool BeginCapture(RenderTexture* current);
    // !End drawing to the texture.
    bool EndCapture();
   
    // !Bind the texture to the active texture unit for use as an "input" texture
    void Bind() const;
    // !Bind the depth texture to the active texture unit for use as an "input" texture
    void BindDepth() const;
    // !Associate the RTT texture with 'iBuffer' (default is WGL_FRONT_LEFT_ARB)
    bool BindBuffer( int iBuffer );
    //! Enables the texture target appropriate for this render texture.
    void EnableTextureTarget() const
    { if (_bInitialized) glEnable(_iTextureTarget); }
    //! Disables the texture target appropriate for this render texture.
    void DisableTextureTarget() const
    { if (_bInitialized) glDisable(_iTextureTarget); }
   
    //! Returns the texture ID.  Useful in Cg applications.
    unsigned int GetTextureID() const  { return _iTextureID; }
    //! Returns the depth texture ID.  Useful in Cg applications.
    unsigned int GetDepthTextureID() const { return _iDepthTextureID; }
    //! Returns the texture target this texture is bound to.
    unsigned int GetTextureTarget() const { return _iTextureTarget; }
    //! Conversion operator allows RenderTexture to be passed to GL calls
    operator unsigned int()const{return _iTextureID;}     
   
    //! Returns the width of the offscreen buffer.
    int GetWidth() const            { return _iWidth;  }
    //! Returns the width of the offscreen buffer.
    int GetHeight() const           { return _iHeight; }
    //! Returns the maximum S texture coordinate.
    int GetMaxS() const      { return IsRectangleTexture() ? _iWidth : 1; }                  
    //! Returns the maximum T texture coordinate.
    int GetMaxT() const      { return IsRectangleTexture() ? _iHeight : 1; }                  
   
    //! Returns the number of red bits allocated.
    int GetRedBits() const          { return _iNumColorBits[0]; }
    //! Returns the number of green bits allocated.
    int GetGreenBits() const        { return _iNumColorBits[1]; }
    //! Returns the number of blue bits allocated.
    int GetBlueBits() const         { return _iNumColorBits[2]; }
    //! Returns the number of alpha bits allocated.
    int GetAlphaBits() const        { return _iNumColorBits[3]; }
    //! Returns the number of depth bits allocated.
    int GetDepthBits() const        { return _iNumDepthBits; }
    //! Returns the number of stencil bits allocated.
    int GetStencilBits() const      { return _iNumStencilBits; }
   
    //! True if this RenderTexture has been properly initialized.
    bool IsInitialized() const      { return _bInitialized; }
    //! True if this is a texture and not just an offscreen buffer.
    bool IsTexture() const          { return _bIsTexture; }
    //! True if this is a depth texture and not just an offscreen buffer.
    bool IsDepthTexture() const     { return _bIsDepthTexture; }
    //! True if this is a floating point buffer / texture.
    bool IsFloatTexture() const     { return _bFloat; }
    //! True if this is a double-buffered pbuffer
    bool IsDoubleBuffered() const   { return _bDoubleBuffered; }
    //! True if this texture has non-power-of-two dimensions.
    bool IsRectangleTexture() const { return _bRectangle; }
    //! True if this texture has non-power-of-two dimensions.
    //! True if this pbuffer has a depth buffer.
    bool HasDepth() const           { return (_iNumDepthBits > 0); }
    //! True if this pbuffer has a stencil buffer.
    bool HasStencil() const         { return (_iNumStencilBits > 0); }
    //! True if this texture has mipmaps.
    bool IsMipmapped() const        { return _bMipmap; }
    /**
    * @fn IsPowerOfTwo(int n)
    * @brief Returns true if /param n is an integer power of 2.
    *
    * Taken from Steve Baker's Cute Code Collection.
    * http://www.sjbaker.org/steve/software/cute_code.html
    */
    static bool IsPowerOfTwo(int n) { return ((n&(n-1))==0); }

    /////////////////////////////////////////////////////////////////////////
    // This is the deprecated (old) interface.  It will likely be removed
    // in a future version, so it is recommended that you transition to the
    // new mode-string-based interface.
    RenderTexture(int width, int height,
                   bool bIsTexture = true,
                   bool bIsDepthTexture = false);
    //
    // Call this once before use.  Set bShare to true to share lists,
    // textures, and program objects between the render texture context
    // and the current active GL context. [deprecated]
    bool Initialize(bool bShare              = true,
                    bool bDepth              = false,
                    bool bStencil            = false,
                    bool bMipmap             = false,
                    bool bAnisoFilter        = false,
                    unsigned int iRBits      = 8,
                    unsigned int iGBits      = 8,
                    unsigned int iBBits      = 8,
                    unsigned int iABits      = 8,
// Only Win32 has RT now, so only make it default there
#ifdef _WIN32
                    UpdateMode   updateMode = RT_RENDER_TO_TEXTURE
#else
                    UpdateMode   updateMode = RT_COPY_TO_TEXTURE
#endif
                    );
    // !Change the render texture resolution. [deprecated]
    bool Reset(int iWidth, int iHeight);
    //
    /////////////////////////////////////////////////////////////////////////

protected: // methods
    bool         _Invalidate();
    typedef std::pair<std::string, std::string> KeyVal;
    void _ParseModeString(const char *modeString,
                          std::vector<int> &pixelFormatAttribs,
                          std::vector<int> &pbufferAttribs);
    std::vector<int> _ParseBitVector(std::string bitVector);
    KeyVal _GetKeyValuePair(std::string token);

    bool _VerifyExtensions();
    bool _InitializeTextures();
   
    void _MaybeCopyBuffer();
    bool _ReleaseBoundBuffers();
    bool _MakeCurrent();
    bool _BindDepthBuffer( ) const;
protected: // data
    int          _iWidth;     // width of the pbuffer
    int          _iHeight;    // height of the pbuffer
   
    bool         _bIsTexture;
    bool         _bIsDepthTexture;
    bool         _bHasARBDepthTexture; // [Redge]
   
    UpdateMode   _eUpdateMode;
        
    bool         _bInitialized;
   
    unsigned int _iNumAuxBuffers;
    bool         _bIsBufferBound;
    int          _iCurrentBoundBuffer;
   
    unsigned int _iNumComponents;
    unsigned int _iNumColorBits[4];
    unsigned int _iNumDepthBits;
    unsigned int _iNumStencilBits;
   
    bool         _bFloat;
    bool         _bDoubleBuffered;
    bool         _bPowerOf2;
    bool         _bRectangle;
    bool         _bMipmap;
   
    bool         _bShareObjects;
    bool         _bCopyContext;
   
#ifdef _WIN32
    HDC          _hDC;        // Handle to a device context.
    HGLRC        _hGLContext; // Handle to a GL context.
    HPBUFFERARB  _hPBuffer;   // Handle to a pbuffer.
   
    HDC          _hPreviousDC;
    HGLRC        _hPreviousContext;
#else
    Display     *_pDisplay;
    GLXContext   _hGLContext;
    GLXPbuffer   _hPBuffer;
   
    GLXDrawable  _hPreviousDrawable;
    GLXContext   _hPreviousContext;
#endif
   
    // Texture stuff
    GLenum       _iTextureTarget;
    unsigned int _iTextureID;
    unsigned int _iDepthTextureID;
   
    unsigned short* _pPoorDepthTexture; // [Redge]
    std::vector<int> _pixelFormatAttribs;
    std::vector<int> _pbufferAttribs;
private:
    // Using these could lead to some odd behavior
    RenderTexture(const RenderTexture&);
    RenderTexture& operator=(const RenderTexture&);
};
#endif //__RENDERTEXTURE2_HPP__
 楼主| 发表于 2007-7-22 16:40:57 | 显示全部楼层

回复: OpenCSG-1.0.2 sample

2.RenderTexture.cpp
//---------------------------------------------------------------------------
// File : RenderTexture.cpp
//---------------------------------------------------------------------------
// Copyright (c) 2002-2004 Mark J. Harris
//---------------------------------------------------------------------------
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any
// damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any
// purpose, including commercial applications, and to alter it and
// redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you
//    must not claim that you wrote the original software. If you use
//    this software in a product, an acknowledgment in the product
//    documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and
//    must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
// --------------------------------------------------------------------------
// Credits:
// Original RenderTexture class: Mark J. Harris
// Original Render to Depth Texture support: Thorsten Scheuermann
// Linux Copy-to-texture: Eric Werness
// Various Bug Fixes: Daniel (Redge) Sperl
//                    Bill Baxter
//                    Florian Kirsch
//
// --------------------------------------------------------------------------
/**
* @file RenderTexture.cpp
*
* Implementation of class RenderTexture.  A multi-format render to
* texture wrapper.
*/
#pragma warning(disable:4786)
#include "RenderTexture.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#ifdef _WIN32
#pragma comment(lib, "gdi32.lib") // required for GetPixelFormat()
#endif
using namespace std;
//---------------------------------------------------------------------------
// Function      : RenderTexture::RenderTexture
// Description  :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::RenderTexture()
* @brief Mode-string-based Constructor.
*/
RenderTexture::RenderTexture(const char *strMode)
:   _iWidth(0),
    _iHeight(0),
    _bIsTexture(false),
    _bIsDepthTexture(false),
    _bHasARBDepthTexture(true),            // [Redge]
#ifdef _WIN32
    _eUpdateMode(RT_RENDER_TO_TEXTURE),
#else
    _eUpdateMode(RT_COPY_TO_TEXTURE),
#endif
    _bInitialized(false),
    _iNumAuxBuffers(0),
    _bIsBufferBound(false),
    _iCurrentBoundBuffer(0),
    _iNumDepthBits(0),
    _iNumStencilBits(0),
    _bFloat(false),
    _bDoubleBuffered(false),
    _bPowerOf2(true),
    _bRectangle(false),
    _bMipmap(false),
    _bShareObjects(false),
    _bCopyContext(false),
#ifdef _WIN32
    _hDC(NULL),
    _hGLContext(NULL),
    _hPBuffer(NULL),
    _hPreviousDC(0),
    _hPreviousContext(0),
#else
    _pDisplay(NULL),
    _hGLContext(NULL),
    _hPBuffer(0),
    _hPreviousContext(0),
    _hPreviousDrawable(0),
#endif
    _iTextureTarget(GL_NONE),
    _iTextureID(0),
    _iDepthTextureID(0),
    _pPoorDepthTexture(0) // [Redge]
{
    _iNumColorBits[0] = _iNumColorBits[1] =
        _iNumColorBits[2] = _iNumColorBits[3] = 0;
#ifdef _WIN32
    _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
    _pixelFormatAttribs.push_back(true);
    _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
    _pixelFormatAttribs.push_back(true);
   
    _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
    _pbufferAttribs.push_back(true);
#else
    _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
    _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
    _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
    _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
#endif
    _ParseModeString(strMode, _pixelFormatAttribs, _pbufferAttribs);
#ifdef _WIN32
    _pixelFormatAttribs.push_back(0);
    _pbufferAttribs.push_back(0);
#else
    _pixelFormatAttribs.push_back(None);
#endif
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::~RenderTexture
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::~RenderTexture()
* @brief Destructor.
*/
RenderTexture::~RenderTexture()
{
    _Invalidate();
}

//---------------------------------------------------------------------------
// Function      : _wglGetLastError
// Description     :
//---------------------------------------------------------------------------
/**
* @fn wglGetLastError()
* @brief Returns the last windows error generated.
*/
#ifdef _WIN32
void _wglGetLastError()
{
#ifdef _DEBUG
   
    DWORD err = GetLastError();
    switch(err)
    {
    case ERROR_INVALID_PIXEL_FORMAT:
        fprintf(stderr,
                "RenderTexture Win32 Error:  ERROR_INVALID_PIXEL_FORMAT\n");
        break;
    case ERROR_NO_SYSTEM_RESOURCES:
        fprintf(stderr,
                "RenderTexture Win32 Error:  ERROR_NO_SYSTEM_RESOURCES\n");
        break;
    case ERROR_INVALID_DATA:
        fprintf(stderr,
                "RenderTexture Win32 Error:  ERROR_INVALID_DATA\n");
        break;
    case ERROR_INVALID_WINDOW_HANDLE:
        fprintf(stderr,
                "RenderTexture Win32 Error:  ERROR_INVALID_WINDOW_HANDLE\n");
        break;
    case ERROR_RESOURCE_TYPE_NOT_FOUND:
        fprintf(stderr,
                "RenderTexture Win32 Error:  ERROR_RESOURCE_TYPE_NOT_FOUND\n");
        break;
    case ERROR_SUCCESS:
        // no error
        break;
    default:
        LPVOID lpMsgBuf;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            err,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
            (LPTSTR) &lpMsgBuf,
            0,
            NULL);
        
        fprintf(stderr, "RenderTexture Win32 Error %d: %s\n", err, lpMsgBuf);
        LocalFree( lpMsgBuf );
        break;
    }
    SetLastError(0);
   
#endif // _DEBUG
}
#endif
//---------------------------------------------------------------------------
// Function      : PrintExtensionError
// Description     :
//---------------------------------------------------------------------------
/**
* @fn PrintExtensionError( char* strMsg, ... )
* @brief Prints an error about missing OpenGL extensions.
*/
void PrintExtensionError( char* strMsg, ... )
{
    fprintf(stderr,
            "Error: RenderTexture requires the following unsupported "
            "OpenGL extensions: \n");
    char strBuffer[512];
    va_list args;
    va_start(args, strMsg);
#ifdef _WIN32
    _vsnprintf( strBuffer, 512, strMsg, args );
#else
    vsnprintf( strBuffer, 512, strMsg, args );
#endif
    va_end(args);
   
    fprintf(stderr, strMsg);
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::Initialize
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::Initialize(int width, int height, bool shareObjects, bool copyContext);
* @brief Initializes the RenderTexture, sharing display lists and textures if specified.
*
* This function creates of the p-buffer.  It can only be called once a GL
* context has already been created.  
*/
bool RenderTexture::Initialize(int width, int height,
                                bool shareObjects       /* = true */,
                                bool copyContext        /* = false */)
{
    assert(width > 0 && height > 0);
    _iWidth = width; _iHeight = height;
    _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
    _bShareObjects = shareObjects;
    _bCopyContext  = copyContext;
    // Check if this is an NVXX GPU and verify necessary extensions.
    if (!_VerifyExtensions())
        return false;
   
    if (_bInitialized)
        _Invalidate();
#if _WIN32
    // Get the current context.
    HDC hdc = wglGetCurrentDC();
    if (NULL == hdc)
        _wglGetLastError();
    HGLRC hglrc = wglGetCurrentContext();
    if (NULL == hglrc)
        _wglGetLastError();
   
    int iFormat = 0;
    unsigned int iNumFormats;
   
    if (_bCopyContext)
    {
        // Get the pixel format for the on-screen window.
        iFormat = GetPixelFormat(hdc);
        if (iFormat == 0)
        {
            fprintf(stderr,
                    "RenderTexture Error: GetPixelFormat() failed.\n");
            return false;
        }
    }
    else
    {
        if (!wglChoosePixelFormatARB(hdc, &_pixelFormatAttribs[0], NULL,
                                     1, &iFormat, &iNumFormats))
        {
            fprintf(stderr,
                "RenderTexture Error: wglChoosePixelFormatARB() failed.\n");
            _wglGetLastError();
            return false;
        }
        if ( iNumFormats <= 0 )
        {
            fprintf(stderr,
                    "RenderTexture Error: Couldn't find a suitable "
                    "pixel format.\n");
            _wglGetLastError();
            return false;
        }
    }
   
    // Create the p-buffer.   
    _hPBuffer = wglCreatePbufferARB(hdc, iFormat, _iWidth, _iHeight,
                                    &_pbufferAttribs[0]);
    if (!_hPBuffer)
    {
        fprintf(stderr,
                "RenderTexture Error: wglCreatePbufferARB() failed.\n");
        _wglGetLastError();
        return false;
    }
   
    // Get the device context.
    _hDC = wglGetPbufferDCARB( _hPBuffer);
    if ( !_hDC )
    {
        fprintf(stderr,
                "RenderTexture Error: wglGetGetPbufferDCARB() failed.\n");
        _wglGetLastError();
        return false;
    }
   
    // Create a gl context for the p-buffer.
    if (_bCopyContext)
    {
        // Let's use the same gl context..
        // Since the device contexts are compatible (i.e. same pixelformat),
        // we should be able to use the same gl rendering context.
        _hGLContext = hglrc;
    }
    else
    {
        _hGLContext = wglCreateContext( _hDC );
        if ( !_hGLContext )
        {
            fprintf(stderr,
                    "RenderTexture Error: wglCreateContext() failed.\n");
            _wglGetLastError();
            return false;
        }
    }
   
    // Share lists, texture objects, and program objects.
    if( _bShareObjects )
    {
        if( !wglShareLists(hglrc, _hGLContext) )
        {
            fprintf(stderr,
                    "RenderTexture Error: wglShareLists() failed.\n");
            _wglGetLastError();
            return false;
        }
    }
   
    // Determine the actual width and height we were able to create.
    wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
    wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
   
    _bInitialized = true;
   
    // get the actual number of bits allocated:
    int attrib = WGL_RED_BITS_ARB;
    //int bits[6];
    int value;
    _iNumColorBits[0] =
        (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
        ? value : 0;
    attrib = WGL_GREEN_BITS_ARB;
    _iNumColorBits[1] =
        (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
        ? value : 0;
    attrib = WGL_BLUE_BITS_ARB;
    _iNumColorBits[2] =
        (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
        ? value : 0;
    attrib = WGL_ALPHA_BITS_ARB;
    _iNumColorBits[3] =
        (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
        ? value : 0;
    attrib = WGL_DEPTH_BITS_ARB;
    _iNumDepthBits =
        (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
        ? value : 0;
    attrib = WGL_STENCIL_BITS_ARB;
    _iNumStencilBits =
        (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
        ? value : 0;
    attrib = WGL_DOUBLE_BUFFER_ARB;
    _bDoubleBuffered =
        (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value))
        ? (value?true:false) : false;
   
#else // !_WIN32
    _pDisplay = glXGetCurrentDisplay();
    GLXContext context = glXGetCurrentContext();
    int screen = DefaultScreen(_pDisplay);
    XVisualInfo *visInfo;
   
    int iFormat = 0;
    int iNumFormats;
    int attrib = 0;
   
    GLXFBConfigSGIX *fbConfigs;
    int nConfigs;
    // [Andrew Wood]
    //Add in pbufferAttribs. Needed  to choose pixel format. (Especially for floating point)
    _pixelFormatAttribs.insert(_pixelFormatAttribs.begin(),
          _pbufferAttribs.begin(),_pbufferAttribs.end());
    // [/Andrew Wood]
   
    fbConfigs = glXChooseFBConfigSGIX(_pDisplay, screen,
                                      &_pixelFormatAttribs[0], &nConfigs);
    if (nConfigs == 0 || !fbConfigs)
    {
        fprintf(stderr,
            "RenderTexture Error: Couldn't find a suitable pixel format.\n");
        return false;
    }
   
    // Pick the first returned format that will return a pbuffer
    int i;
    for (i=0;i<nConfigs;i++)
    {
        _hPBuffer = glXCreateGLXPbufferSGIX(_pDisplay, fbConfigs,
                                            _iWidth, _iHeight, NULL);
        if (_hPBuffer)
        {
            _hGLContext = glXCreateContextWithConfigSGIX(_pDisplay,
                                                         fbConfigs,
                                                         GLX_RGBA_TYPE,
                                                         _bShareObjects ? context : NULL,
                                                         True);
            break;
        }
    }
   
    if (!_hPBuffer)
    {
        fprintf(stderr,
                "RenderTexture Error: glXCreateGLXPbufferSGIX() failed.\n");
        return false;
    }
   
    if(!_hGLContext)
    {
        // Try indirect
        _hGLContext = glXCreateContext(_pDisplay, visInfo,
                                       _bShareObjects ? context : NULL, False);
        if ( !_hGLContext )
        {
            fprintf(stderr,
                    "RenderTexture Error: glXCreateContext() failed.\n");
            return false;
        }
    }
   
    glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_WIDTH_SGIX,
                           (GLuint*)&_iWidth);
    glXQueryGLXPbufferSGIX(_pDisplay, _hPBuffer, GLX_HEIGHT_SGIX,
                           (GLuint*)&_iHeight);
   
    _bInitialized = true;
   
    // [Florian] Query the color format
    //XVisualInfo* visual = glXGetVisualFromFBConfigSGIX(_pDisplay, fbConfigs);
    // [Andrew Wood]
    int iResult = 0;
    glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_RENDER_TYPE, &iResult);
    if (iResult == GLX_RGBA_BIT)
    {
        _iNumColorBits[0] = (glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_RED_SIZE,   &iResult) == 0) ? iResult : 0;
        _iNumColorBits[1] = (glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_GREEN_SIZE, &iResult) == 0) ? iResult : 0;
        _iNumColorBits[2] = (glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_BLUE_SIZE,  &iResult) == 0) ? iResult : 0;
        _iNumColorBits[3] = (glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_ALPHA_SIZE, &iResult) == 0) ? iResult : 0;
        _iNumDepthBits =    (glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_DEPTH_SIZE, &iResult) == 0) ? iResult : 0;
        _iNumStencilBits =  (glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_STENCIL_SIZE, &iResult) == 0) ? iResult : 0;
        _bDoubleBuffered =  (glXGetFBConfigAttribSGIX(_pDisplay, fbConfigs, GLX_DOUBLEBUFFER, &iResult) == 0) ? (iResult?true:false) : false;
    }
    // [/Andrew Wood]
    //XFree(visual);
    // [/Florian]
#endif
#if defined(_DEBUG) | defined(DEBUG)
    fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
        _iWidth, _iHeight,
        _iNumColorBits[0], _iNumColorBits[1],
        _iNumColorBits[2], _iNumColorBits[3]);
    if (_iNumDepthBits) fprintf(stderr, " depth=%d", _iNumDepthBits);
    if (_iNumStencilBits) fprintf(stderr, " stencil=%d", _iNumStencilBits);
    if (_bDoubleBuffered) fprintf(stderr, " double buffered");
    fprintf(stderr, "\n");
#endif
   
    // Now that the pbuffer is created, allocate any texture objects needed,
    // and initialize them (for CTT updates only).  These must be allocated
    // in the context of the pbuffer, though, or the RT won't work without
    // wglShareLists.
#ifdef _WIN32
    if (false == wglMakeCurrent( _hDC, _hGLContext))
    {
        _wglGetLastError();
        return false;
    }
#else
    _hPreviousContext = glXGetCurrentContext();
    _hPreviousDrawable = glXGetCurrentDrawable();
   
    if (False == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
    {
        return false;
    }
#endif
   
    bool result = _InitializeTextures();   
#ifdef _WIN32
    BindBuffer(WGL_FRONT_LEFT_ARB);
    _BindDepthBuffer();
#endif
   
#ifdef _WIN32
    // make the previous rendering context current
    if (false == wglMakeCurrent( hdc, hglrc))
    {
        _wglGetLastError();
        return false;
    }
#else
    if (False == glXMakeCurrent(_pDisplay,
                                _hPreviousDrawable, _hPreviousContext))
    {
        return false;
    }
#endif
    return result;
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::_Invalidate
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_Invalidate()
* @brief Returns the pbuffer memory to the graphics device.
*
*/
bool RenderTexture::_Invalidate()
{
    _iNumColorBits[0] = _iNumColorBits[1] =
        _iNumColorBits[2] = _iNumColorBits[3] = 0;
    _iNumDepthBits = 0;
    _iNumStencilBits = 0;
   
    if (_bIsTexture)
        glDeleteTextures(1, &_iTextureID);
    if (_bIsDepthTexture)
    {
        // [Redge]
        if (!_bHasARBDepthTexture) delete[] _pPoorDepthTexture;
        // [/Redge]
        glDeleteTextures(1, &_iDepthTextureID);
    }
   
#if _WIN32
    if ( _hPBuffer )
    {
        // Check if we are currently rendering in the pbuffer
        if (wglGetCurrentContext() == _hGLContext)
            wglMakeCurrent(0,0);
        if (!_bCopyContext)
            wglDeleteContext( _hGLContext);
        wglReleasePbufferDCARB( _hPBuffer, _hDC);
        wglDestroyPbufferARB( _hPBuffer );
        _hPBuffer = 0;
        return true;
    }
#else
    if ( _hPBuffer )
    {
        if(glXGetCurrentContext() == _hGLContext)
            // XXX I don't know if this is right at all
            glXMakeCurrent(_pDisplay, _hPBuffer, 0);
        glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
        _hPBuffer = 0;
        return true;
    }
#endif
    // [WVB] do we need to call _ReleaseBoundBuffers() too?
    return false;
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::Reset
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::Reset()
* @brief Resets the resolution of the offscreen buffer.
*
* Causes the buffer to delete itself.  User must call Initialize() again
* before use.
*/
bool RenderTexture::Reset(const char *strMode, ...)
{
    _iWidth = 0; _iHeight = 0;
    _bIsTexture = false; _bIsDepthTexture = false,
    _bHasARBDepthTexture = true;
#ifdef _WIN32
    _eUpdateMode = RT_RENDER_TO_TEXTURE;
#else
    _eUpdateMode = RT_COPY_TO_TEXTURE;
#endif
    _bInitialized = false;
    _iNumAuxBuffers = 0;
    _bIsBufferBound = false;
    _iCurrentBoundBuffer = 0;
    _iNumDepthBits = 0; _iNumStencilBits = 0;
    _bDoubleBuffered = false;
    _bFloat = false; _bPowerOf2 = true;
    _bRectangle = false; _bMipmap = false;
    _bShareObjects = false; _bCopyContext = false;
    _iTextureTarget = GL_NONE; _iTextureID = 0;
    _iDepthTextureID = 0;
    _pPoorDepthTexture = 0;
    _pixelFormatAttribs.clear();
    _pbufferAttribs.clear();
    if (IsInitialized() && !_Invalidate())
    {
        fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
        return false;
    }
   
    _iNumColorBits[0] = _iNumColorBits[1] =
        _iNumColorBits[2] = _iNumColorBits[3] = 0;
#ifdef _WIN32
    _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
    _pixelFormatAttribs.push_back(true);
    _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
    _pixelFormatAttribs.push_back(true);
   
    _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
    _pbufferAttribs.push_back(true);
#else
    _pbufferAttribs.push_back(GLX_RENDER_TYPE_SGIX);
    _pbufferAttribs.push_back(GLX_RGBA_BIT_SGIX);
    _pbufferAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
    _pbufferAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
#endif
    va_list args;
    char strBuffer[256];
    va_start(args,strMode);
#ifdef _WIN32
    _vsnprintf( strBuffer, 256, strMode, args );
#else
    vsnprintf( strBuffer, 256, strMode, args );
#endif
    va_end(args);
    _ParseModeString(strBuffer, _pixelFormatAttribs, _pbufferAttribs);
#ifdef _WIN32
    _pixelFormatAttribs.push_back(0);
    _pbufferAttribs.push_back(0);
#else
    _pixelFormatAttribs.push_back(None);
#endif
    return true;
}
//------------------------------------------------------------------------------
// Function        : RenderTexture::Resize
// Description     :
//------------------------------------------------------------------------------
/**
* @fn RenderTexture::Resize(int iWidth, int iHeight)
* @brief Changes the size of the offscreen buffer.
*
* Like Reset() this causes the buffer to delete itself.  
* But unlike Reset(), this call re-initializes the RenderTexture.
* Note that Resize() will not work after calling Reset(), or before
* calling Initialize() the first time.
*/
bool RenderTexture::Resize(int iWidth, int iHeight)
{
    if (!_bInitialized) {
        fprintf(stderr, "RenderTexture::Resize(): must Initialize() first.\n");
        return false;
    }
    if (iWidth == _iWidth && iHeight == _iHeight) {
        return true;
    }
   
    // Do same basic work as _Invalidate, but don't reset all our flags
    if (_bIsTexture)
        glDeleteTextures(1, &_iTextureID);
    if (_bIsDepthTexture)
        glDeleteTextures(1, &_iDepthTextureID);
#ifdef _WIN32
    if ( _hPBuffer )
    {
        // Check if we are currently rendering in the pbuffer
        if (wglGetCurrentContext() == _hGLContext)
            wglMakeCurrent(0,0);
        if (!_bCopyContext)
            wglDeleteContext( _hGLContext);
        wglReleasePbufferDCARB( _hPBuffer, _hDC);
        wglDestroyPbufferARB( _hPBuffer );
        _hPBuffer = 0;
        return true;
    }
#else
    if ( _hPBuffer )
    {
        if(glXGetCurrentContext() == _hGLContext)
            // XXX I don't know if this is right at all
            glXMakeCurrent(_pDisplay, _hPBuffer, 0);
        glXDestroyGLXPbufferSGIX(_pDisplay, _hPBuffer);
        _hPBuffer = 0;
    }
#endif
    else {
        fprintf(stderr, "RenderTexture::Resize(): failed to resize.\n");
        return false;
    }
    _bInitialized = false;
    return Initialize(iWidth, iHeight, _bShareObjects, _bCopyContext);
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::BeginCapture
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::BeginCapture()
* @brief Activates rendering to the RenderTexture.
*/
bool RenderTexture::BeginCapture()
{
    if (!_bInitialized)
    {
        fprintf(stderr,
                "RenderTexture::BeginCapture(): Texture is not initialized!\n");
        return false;
    }
#ifdef _WIN32
    // cache the current context so we can reset it when EndCapture() is called.
    _hPreviousDC      = wglGetCurrentDC();
    if (NULL == _hPreviousDC)
        _wglGetLastError();
    _hPreviousContext = wglGetCurrentContext();
    if (NULL == _hPreviousContext)
        _wglGetLastError();
#else
    _hPreviousContext = glXGetCurrentContext();
    _hPreviousDrawable = glXGetCurrentDrawable();
#endif
    _ReleaseBoundBuffers();
    return _MakeCurrent();
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::EndCapture
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::EndCapture()
* @brief Ends rendering to the RenderTexture.
*/
bool RenderTexture::EndCapture()
{   
    if (!_bInitialized)
    {
        fprintf(stderr,
                "RenderTexture::EndCapture() : Texture is not initialized!\n");
        return false;
    }
    _MaybeCopyBuffer();
#ifdef _WIN32
    // make the previous rendering context current
    if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
    {
        _wglGetLastError();
        return false;
    }
#else
    if (False == glXMakeCurrent(_pDisplay, _hPreviousDrawable,
                                _hPreviousContext))
    {
        return false;
    }
#endif
    // rebind the textures to a buffers for RTT
    BindBuffer(_iCurrentBoundBuffer);
    _BindDepthBuffer();
    return true;
}
//---------------------------------------------------------------------------
// Function        : RenderTexture::BeginCapture(RenderTexture*)
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::BeginCapture(RenderTexture* other)
* @brief Ends capture of 'other', begins capture on 'this'
*
* When performing a series of operations where you modify one texture after
* another, it is more efficient to use this method instead of the equivalent
* 'EndCapture'/'BeginCapture' pair.  This method switches directly to the
* new context rather than changing to the default context, and then to the
* new context.
*
* RenderTexture doesn't have any mechanism for determining if
* 'current' really is currently active, so no error will be thrown
* if it is not.
*/
bool RenderTexture::BeginCapture(RenderTexture* current)
{
    bool bContextReset = false;
   
    if (current == this) {
        return true; // no switch necessary
    }
    if (!current) {
        // treat as normal Begin if current is 0.
        return BeginCapture();
    }
    if (!_bInitialized)
    {
        fprintf(stderr,
            "RenderTexture::BeginCapture(RenderTexture*): Texture is not initialized!\n");
        return false;
    }
    if (!current->_bInitialized)
    {
        fprintf(stderr,
            "RenderTexture::BeginCapture(RenderTexture): 'current' texture is not initialized!\n");
        return false;
    }
   
    // Sync current pbuffer with its CTT texture if necessary
    current->_MaybeCopyBuffer();
    // pass along the previous context so we can reset it when
    // EndCapture() is called.
#ifdef _WIN32
    _hPreviousDC      = current->_hPreviousDC;
    if (NULL == _hPreviousDC)
        _wglGetLastError();
    _hPreviousContext = current->_hPreviousContext;
    if (NULL == _hPreviousContext)
        _wglGetLastError();
#else
    _hPreviousContext = current->_hPreviousContext;
    _hPreviousDrawable = current->_hPreviousDrawable;
#endif   
    // Unbind textures before making context current
    if (!_ReleaseBoundBuffers())
      return false;
    // Make the pbuffer context current
    if (!_MakeCurrent())
        return false;
    // Rebind buffers of initial RenderTexture
    current->BindBuffer(_iCurrentBoundBuffer);
    current->_BindDepthBuffer();
   
    return true;
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::Bind
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::Bind()
* @brief Binds RGB texture.
*/
void RenderTexture::Bind() const
{
    if (_bInitialized && _bIsTexture)
    {
        glBindTexture(_iTextureTarget, _iTextureID);
    }   
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::BindDepth
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::BindDepth()
* @brief Binds depth texture.
*/
void RenderTexture::BindDepth() const
{
    if (_bInitialized && _bIsDepthTexture)
    {
        glBindTexture(_iTextureTarget, _iDepthTextureID);
    }
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::BindBuffer
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::BindBuffer()
* @brief Associate the RTT texture id with 'iBuffer' (e.g. WGL_FRONT_LEFT_ARB)
*/
bool RenderTexture::BindBuffer( int iBuffer )
{
    // Must bind the texture too
    if (_bInitialized && _bIsTexture)
    {
        glBindTexture(_iTextureTarget, _iTextureID);
        
#if _WIN32
        if (RT_RENDER_TO_TEXTURE == _eUpdateMode && _bIsTexture &&
            (!_bIsBufferBound || _iCurrentBoundBuffer != iBuffer))
        {
            if (FALSE == wglBindTexImageARB(_hPBuffer, iBuffer))
            {
                //  WVB: WGL API considers binding twice to the same buffer
                //  to be an error.  But we don't want to
                //_wglGetLastError();
                //return false;
                SetLastError(0);
            }
            _bIsBufferBound = true;
            _iCurrentBoundBuffer = iBuffer;
        }
#endif
    }   
    return true;
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::BindBuffer
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_BindDepthBuffer()
* @brief Associate the RTT depth texture id with the depth buffer
*/
bool RenderTexture::_BindDepthBuffer() const
{
#ifdef WIN32
    if (_bInitialized && _bIsDepthTexture &&
        RT_RENDER_TO_TEXTURE == _eUpdateMode)
    {
        glBindTexture(_iTextureTarget, _iDepthTextureID);
        if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
        {
            _wglGetLastError();
            return false;
        }
    }
#endif
    return true;
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::_ParseModeString
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_ParseModeString()
* @brief Parses the user-specified mode string for RenderTexture parameters.
*/
void RenderTexture::_ParseModeString(const char *modeString,
                                     vector<int> &pfAttribs,
                                     vector<int> &pbAttribs)
{
    if (!modeString || strcmp(modeString, "") == 0)
        return;
_iNumComponents = 0;
#ifdef _WIN32
    _eUpdateMode = RT_RENDER_TO_TEXTURE;
#else
    _eUpdateMode = RT_COPY_TO_TEXTURE;
#endif
   
    int  iDepthBits = 0;
    bool bHasStencil = false;
    bool bBind2D   = false;
    bool bBindRECT = false;
    bool bBindCUBE = false;
   
    char *mode = strdup(modeString);
   
    vector<string> tokens;
    char *buf = strtok(mode, " ");
    while (buf != NULL)
    {
        tokens.push_back(buf);
        buf = strtok(NULL, " ");
    }
    for (unsigned int i = 0; i < tokens.size(); i++)
    {
        string token = tokens;
        KeyVal kv = _GetKeyValuePair(token);
        
        
        if (kv.first == "rgb" && (_iNumComponents <= 1))
        {           
            if (kv.second.find("f") != kv.second.npos)
                _bFloat = true;
            vector<int> bitVec = _ParseBitVector(kv.second);
            if (bitVec.size() < 3) // expand the scalar to a vector
            {
                bitVec.push_back(bitVec[0]);
                bitVec.push_back(bitVec[0]);
            }
#ifdef _WIN32
            pfAttribs.push_back(WGL_RED_BITS_ARB);
            pfAttribs.push_back(bitVec[0]);
            pfAttribs.push_back(WGL_GREEN_BITS_ARB);
            pfAttribs.push_back(bitVec[1]);
            pfAttribs.push_back(WGL_BLUE_BITS_ARB);
            pfAttribs.push_back(bitVec[2]);
#else
            pfAttribs.push_back(GLX_RED_SIZE);
            pfAttribs.push_back(bitVec[0]);
            pfAttribs.push_back(GLX_GREEN_SIZE);
            pfAttribs.push_back(bitVec[1]);
            pfAttribs.push_back(GLX_BLUE_SIZE);
            pfAttribs.push_back(bitVec[2]);
#endif
   _iNumComponents += 3;
            continue;
        }
  else if (kv.first == "rgb")
            fprintf(stderr,
                    "RenderTexture Warning: mistake in components definition "
                    "(rgb + %d).\n",
                    _iNumComponents);
        
        if (kv.first == "rgba" && (_iNumComponents == 0))
        {
            if (kv.second.find("f") != kv.second.npos)
                _bFloat = true;
            vector<int> bitVec = _ParseBitVector(kv.second);
            if (bitVec.size() < 4) // expand the scalar to a vector
            {
                bitVec.push_back(bitVec[0]);
                bitVec.push_back(bitVec[0]);
                bitVec.push_back(bitVec[0]);
            }
#ifdef _WIN32
            pfAttribs.push_back(WGL_RED_BITS_ARB);
            pfAttribs.push_back(bitVec[0]);
            pfAttribs.push_back(WGL_GREEN_BITS_ARB);
            pfAttribs.push_back(bitVec[1]);
            pfAttribs.push_back(WGL_BLUE_BITS_ARB);
            pfAttribs.push_back(bitVec[2]);
            pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
            pfAttribs.push_back(bitVec[3]);
#else
            pfAttribs.push_back(GLX_RED_SIZE);
            pfAttribs.push_back(bitVec[0]);
            pfAttribs.push_back(GLX_GREEN_SIZE);
            pfAttribs.push_back(bitVec[1]);
            pfAttribs.push_back(GLX_BLUE_SIZE);
            pfAttribs.push_back(bitVec[2]);
            pfAttribs.push_back(GLX_ALPHA_SIZE);
            pfAttribs.push_back(bitVec[3]);
#endif
   _iNumComponents = 4;
            continue;
        }
  else if (kv.first == "rgba")
            fprintf(stderr,
                    "RenderTexture Warning: mistake in components definition "
                    "(rgba + %d).\n",
                    _iNumComponents);
        
        if (kv.first == "r" && (_iNumComponents <= 1))
        {
            if (kv.second.find("f") != kv.second.npos)
                _bFloat = true;
            vector<int> bitVec = _ParseBitVector(kv.second);
#ifdef _WIN32
            pfAttribs.push_back(WGL_RED_BITS_ARB);
            pfAttribs.push_back(bitVec[0]);
#else
            pfAttribs.push_back(GLX_RED_SIZE);
            pfAttribs.push_back(bitVec[0]);
#endif
   _iNumComponents++;
            continue;
        }
  else if (kv.first == "r")
            fprintf(stderr,
                    "RenderTexture Warning: mistake in components definition "
                    "(r + %d).\n",
                    _iNumComponents);
        if (kv.first == "rg" && (_iNumComponents <= 1))
        {
            if (kv.second.find("f") != kv.second.npos)
                _bFloat = true;
            vector<int> bitVec = _ParseBitVector(kv.second);
            if (bitVec.size() < 2) // expand the scalar to a vector
            {
                bitVec.push_back(bitVec[0]);
            }
#ifdef _WIN32
            pfAttribs.push_back(WGL_RED_BITS_ARB);
            pfAttribs.push_back(bitVec[0]);
            pfAttribs.push_back(WGL_GREEN_BITS_ARB);
            pfAttribs.push_back(bitVec[1]);
#else
            pfAttribs.push_back(GLX_RED_SIZE);
            pfAttribs.push_back(bitVec[0]);
            pfAttribs.push_back(GLX_GREEN_SIZE);
            pfAttribs.push_back(bitVec[1]);
#endif
   _iNumComponents += 2;
            continue;
        }
  else if (kv.first == "rg")
            fprintf(stderr,
                    "RenderTexture Warning: mistake in components definition "
                    "(rg + %d).\n",
                    _iNumComponents);
        if (kv.first == "depth")
        {
            if (kv.second == "")
                iDepthBits = 24;
            else
                iDepthBits = strtol(kv.second.c_str(), 0, 10);
            continue;
        }
        if (kv.first == "stencil")
        {
            bHasStencil = true;
#ifdef _WIN32
            pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
#else
            pfAttribs.push_back(GLX_STENCIL_SIZE);
#endif
            if (kv.second == "")
                pfAttribs.push_back(8);
            else
                pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
            continue;
        }
        if (kv.first == "samples")
        {
#ifdef _WIN32
            pfAttribs.push_back(WGL_SAMPLE_BUFFERS_ARB);
            pfAttribs.push_back(1);
            pfAttribs.push_back(WGL_SAMPLES_ARB);
            pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
#else
     pfAttribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
     pfAttribs.push_back(1);
     pfAttribs.push_back(GLX_SAMPLES_ARB);
            pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
#endif
            continue;
        }
        if (kv.first == "doublebuffer" || kv.first == "double")
        {
#ifdef _WIN32
            pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
            pfAttribs.push_back(true);
#else
            pfAttribs.push_back(GLX_DOUBLEBUFFER);
            pfAttribs.push_back(True);
#endif
            continue;
        }  
        // [Florian]
        if (kv.first == "singlebuffer" || kv.first == "single")
        {
#ifdef _WIN32
            pfAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
            pfAttribs.push_back(false);
#else
            pfAttribs.push_back(GLX_DOUBLEBUFFER);
            pfAttribs.push_back(False);
#endif
            continue;
        }
// [/Florian]
        if (kv.first == "aux")
        {
#ifdef _WIN32
            pfAttribs.push_back(WGL_AUX_BUFFERS_ARB);
#else
            pfAttribs.push_back(GLX_AUX_BUFFERS);
#endif
            if (kv.second == "")
                pfAttribs.push_back(0);
            else
                pfAttribs.push_back(strtol(kv.second.c_str(), 0, 10));
            continue;
        }
        
        if (token.find("tex") == 0)
        {            
            _bIsTexture = true;
            
            if ((kv.first == "texRECT") && GLEW_NV_texture_rectangle)
            {
                _bRectangle = true;
                bBindRECT = true;
            }
            else if (kv.first == "texCUBE")
            {
                bBindCUBE = true;
            }
            else
            {
                bBind2D = true;
            }
            continue;
        }
        if (token.find("depthTex") == 0)
        {
            _bIsDepthTexture = true;
            
            if ((kv.first == "depthTexRECT") && GLEW_NV_texture_rectangle)
            {
                _bRectangle = true;
                bBindRECT = true;
            }
            else if (kv.first == "depthTexCUBE")
            {
                bBindCUBE = true;
            }
            else
            {
                bBind2D = true;
            }
            continue;
        }
        if (kv.first == "mipmap")
        {
            _bMipmap = true;   
            continue;
        }
        if (kv.first == "rtt")
        {
            _eUpdateMode = RT_RENDER_TO_TEXTURE;
            continue;
        }
        
        if (kv.first == "ctt")
        {
            _eUpdateMode = RT_COPY_TO_TEXTURE;
            continue;
        }
        fprintf(stderr,
                "RenderTexture Error: Unknown pbuffer attribute: %s\n",
                token.c_str());
    }
    // Processing of some options must be last because of interactions.
    // Check for inconsistent texture targets
    if (_bIsTexture && _bIsDepthTexture && !(bBind2D ^ bBindRECT ^ bBindCUBE))
    {
        fprintf(stderr,
                "RenderTexture Warning: Depth and Color texture targets "
                "should match.\n");
    }
    // Apply default bit format if none specified
#ifdef _WIN32
    if (0 == _iNumComponents)
    {
        pfAttribs.push_back(WGL_RED_BITS_ARB);
        pfAttribs.push_back(8);
        pfAttribs.push_back(WGL_GREEN_BITS_ARB);
        pfAttribs.push_back(8);
        pfAttribs.push_back(WGL_BLUE_BITS_ARB);
        pfAttribs.push_back(8);
        pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
        pfAttribs.push_back(8);
        _iNumComponents = 4;
    }
#endif
    // Depth bits
    if (_bIsDepthTexture && !iDepthBits)
        iDepthBits = 24;
#ifdef _WIN32
    pfAttribs.push_back(WGL_DEPTH_BITS_ARB);
#else
    pfAttribs.push_back(GLX_DEPTH_SIZE);
#endif
    pfAttribs.push_back(iDepthBits); // default
   
    if (!bHasStencil)
    {
#ifdef _WIN32
        pfAttribs.push_back(WGL_STENCIL_BITS_ARB);
        pfAttribs.push_back(0);
#else
        pfAttribs.push_back(GLX_STENCIL_SIZE);
        pfAttribs.push_back(0);
#endif
    }
    if (_iNumComponents < 4)
    {
        // Can't do this right now -- on NVIDIA drivers, currently get
        // a non-functioning pbuffer if ALPHA_BITS=0 and
        // WGL_BIND_TO_TEXTURE_RGB_ARB=true
        
        //pfAttribs.push_back(WGL_ALPHA_BITS_ARB);
        //pfAttribs.push_back(0);
    }
#ifdef _WIN32
    if (!WGLEW_NV_render_depth_texture && _bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
    {
#if defined(DEBUG) || defined(_DEBUG)
        fprintf(stderr, "RenderTexture Warning: No support found for "
                "render to depth texture.\n");
#endif
        _bIsDepthTexture = false;
    }
#endif
   
    if ((_bIsTexture || _bIsDepthTexture) &&
        (RT_RENDER_TO_TEXTURE == _eUpdateMode))
    {
#ifdef _WIN32                  
        if (bBindRECT)
        {
            pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
            pbAttribs.push_back(WGL_TEXTURE_RECTANGLE_NV);
        }
        else if (bBindCUBE)
        {
            pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
            pbAttribs.push_back(WGL_TEXTURE_CUBE_MAP_ARB);
        }
        else if (bBind2D)
        {
            pbAttribs.push_back(WGL_TEXTURE_TARGET_ARB);
            pbAttribs.push_back(WGL_TEXTURE_2D_ARB);
        }
            
        if (_bMipmap)
        {
            pbAttribs.push_back(WGL_MIPMAP_TEXTURE_ARB);
            pbAttribs.push_back(true);
        }
#elif defined(DEBUG) || defined(_DEBUG)
        printf("RenderTexture Error: Render to Texture not "
               "supported in Linux\n");
#endif  
    }
    // Set the pixel type
    if (_bFloat)
    {
#ifdef _WIN32
        if (WGLEW_NV_float_buffer)
        {
            pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
            pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
            pfAttribs.push_back(WGL_FLOAT_COMPONENTS_NV);
            pfAttribs.push_back(true);
        }
        else
        {
            pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
            pfAttribs.push_back(WGL_TYPE_RGBA_FLOAT_ATI);
        }
#else
        if (GLXEW_NV_float_buffer)
        {
            pfAttribs.push_back(GLX_FLOAT_COMPONENTS_NV);
            pfAttribs.push_back(1);
        }
#endif
    }
    else
    {
#ifdef _WIN32
        pfAttribs.push_back(WGL_PIXEL_TYPE_ARB);
        pfAttribs.push_back(WGL_TYPE_RGBA_ARB);
#endif
    }
    // Set up texture binding for render to texture
    if (_bIsTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
    {
        
#ifdef _WIN32
        if (_bFloat)
        {
            if (WGLEW_NV_float_buffer)
            {
                switch(_iNumComponents)
                {
                case 1:
                    pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
                    pfAttribs.push_back(true);
                    
                    pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                    pbAttribs.push_back(WGL_TEXTURE_FLOAT_R_NV);
                    break;
                case 2:
                    pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
                    pfAttribs.push_back(true);
                    
                    pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                    pbAttribs.push_back(WGL_TEXTURE_FLOAT_RG_NV);
                    break;
                case 3:
                    pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
                    pfAttribs.push_back(true);
                    
                    pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                    pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGB_NV);
                    break;
                case 4:
                    pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
                    pfAttribs.push_back(true);
                    
                    pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                    pbAttribs.push_back(WGL_TEXTURE_FLOAT_RGBA_NV);
                    break;
                default:
                    fprintf(stderr,
                            "RenderTexture Warning: Bad number of components "
                            "(r=1,rg=2,rgb=3,rgba=4): %d.\n",
                            _iNumComponents);
                    break;
                }
            }
            else
            {
                if (4 == _iNumComponents)
                {
                    pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
                    pfAttribs.push_back(true);
                    
                    pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                    pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
                }
                else
                {
                    // standard ARB_render_texture only supports 3 or 4 channels
                    pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
                    pfAttribs.push_back(true);
                    
                    pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                    pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
                }
            }
            
        }
        else
        {
            switch(_iNumComponents)
            {
            case 3:
                pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGB_ARB);
                pfAttribs.push_back(true);
               
                pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                pbAttribs.push_back(WGL_TEXTURE_RGB_ARB);
                break;
            case 4:
                pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB);
                pfAttribs.push_back(true);
               
                pbAttribs.push_back(WGL_TEXTURE_FORMAT_ARB);
                pbAttribs.push_back(WGL_TEXTURE_RGBA_ARB);
                break;
            default:
                fprintf(stderr,
                        "RenderTexture Warning: Bad number of components "
                        "(r=1,rg=2,rgb=3,rgba=4): %d.\n", _iNumComponents);
                break;
            }
        }         
#elif defined(DEBUG) || defined(_DEBUG)
        fprintf(stderr,
                "RenderTexture Error: Render to Texture not supported in "
                "Linux\n");
#endif  
    }
        
    if (_bIsDepthTexture && (RT_RENDER_TO_TEXTURE == _eUpdateMode))
    {  
#ifdef _WIN32
        if (_bRectangle)
        {
            pfAttribs.push_back(WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV);
            pfAttribs.push_back(true);
        
            pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
            pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
        }
        else
        {
            pfAttribs.push_back(WGL_BIND_TO_TEXTURE_DEPTH_NV);
            pfAttribs.push_back(true);
        
            pbAttribs.push_back(WGL_DEPTH_TEXTURE_FORMAT_NV);
            pbAttribs.push_back(WGL_TEXTURE_DEPTH_COMPONENT_NV);
        }
#elif defined(DEBUG) || defined(_DEBUG)
        printf("RenderTexture Error: Render to Texture not supported in "
               "Linux\n");
#endif
    }
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::_GetKeyValuePair
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_GetKeyValuePair()
* @brief Parses expressions of the form "X=Y" into a pair (X,Y).
*/
RenderTexture::KeyVal RenderTexture::_GetKeyValuePair(string token)
{
    string::size_type pos = 0;
    if ((pos = token.find("=")) != token.npos)
    {
        string key = token.substr(0, pos);
        string value = token.substr(pos+1, token.length()-pos+1);
        return KeyVal(key, value);
    }
    else
        return KeyVal(token, "");
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::_ParseBitVector
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_ParseBitVector()
* @brief Parses expressions of the form "=r,g,b,a" into a vector: (r,g,b,a)
*/
vector<int> RenderTexture::_ParseBitVector(string bitVector)
{
    vector<string> pieces;
    vector<int> bits;
    if (bitVector == "")
    {
        bits.push_back(8);  // if a depth isn't specified, use default 8 bits
        return bits;
    }
    string::size_type pos = 0;
    string::size_type nextpos = 0;
    do
    {
        nextpos = bitVector.find_first_of(", \n", pos);
        pieces.push_back(string(bitVector, pos, nextpos - pos));
        pos = nextpos+1;
    } while (nextpos != bitVector.npos );
    for ( vector<string>::iterator it = pieces.begin(); it != pieces.end(); it++)
    {
        bits.push_back(strtol(it->c_str(), 0, 10));
    }
   
    return bits;
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::_VerifyExtensions
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_VerifyExtensions()
* @brief Checks that the necessary extensions are available based on RT mode.
*/
bool RenderTexture::_VerifyExtensions()
{
#ifdef _WIN32
    if (!WGLEW_ARB_pbuffer)
    {
        PrintExtensionError("WGL_ARB_pbuffer");
        return false;
    }
    if (!WGLEW_ARB_pixel_format)
    {
        PrintExtensionError("WGL_ARB_pixel_format");
        return false;
    }
    if (_bIsTexture && !WGLEW_ARB_render_texture)
    {
        PrintExtensionError("WGL_ARB_render_texture");
        return false;
    }
    if (_bRectangle && !GLEW_NV_texture_rectangle)
    {
        PrintExtensionError("GL_NV_texture_rectangle");
        return false;
    }
    if (_bFloat && !(GLEW_NV_float_buffer || WGLEW_ATI_pixel_format_float))
    {
        PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
        return false;
   
    }
    if (_bFloat && _bIsTexture && !(GLEW_NV_float_buffer || GLEW_ATI_texture_float))
    {
        PrintExtensionError("NV_float_buffer or ATI_texture_float");
    }
    if (_bIsDepthTexture && !GLEW_ARB_depth_texture)
    {
        // [Redge]
#if defined(_DEBUG) | defined(DEBUG)
        fprintf(stderr,
                "RenderTexture Warning: "
                "OpenGL extension GL_ARB_depth_texture not available.\n"
                "         Using glReadPixels() to emulate behavior.\n");
#endif   
        _bHasARBDepthTexture = false;
        //PrintExtensionError("GL_ARB_depth_texture");
        //return false;
        // [/Redge]
    }
    SetLastError(0);
#else
    if (!GLXEW_SGIX_pbuffer)
    {
        PrintExtensionError("GLX_SGIX_pbuffer");
        return false;
    }
    if (!GLXEW_SGIX_fbconfig)
    {
        PrintExtensionError("GLX_SGIX_fbconfig");
        return false;
    }
    if (_bIsDepthTexture && !GLEW_ARB_depth_texture)
    {
        PrintExtensionError("GL_ARB_depth_texture");
        return false;
    }
    if (_bFloat && _bIsTexture && !GLXEW_NV_float_buffer)
    {
        PrintExtensionError("GLX_NV_float_buffer");
        return false;
    }
    if (_eUpdateMode == RT_RENDER_TO_TEXTURE)
    {
        PrintExtensionError("Some GLX render texture extension: FIXME!");
        return false;
    }
#endif
  
    return true;
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::_InitializeTextures
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_InitializeTextures()
* @brief Initializes the state of textures used by the RenderTexture.
*/
bool RenderTexture::_InitializeTextures()
{
    // Determine the appropriate texture formats and filtering modes.
    if (_bIsTexture || _bIsDepthTexture)
    {
        if (_bRectangle && GLEW_NV_texture_rectangle)
            _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
        else
            _iTextureTarget = GL_TEXTURE_2D;
    }
    if (_bIsTexture)
    {
        glGenTextures(1, &_iTextureID);
        glBindTexture(_iTextureTarget, _iTextureID);  
        
        // Use clamp to edge as the default texture wrap mode for all tex
        glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        // Use NEAREST as the default texture filtering mode.
        glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        if (RT_COPY_TO_TEXTURE == _eUpdateMode)
        {
            GLuint iInternalFormat;
            GLuint iFormat;
            if (_bFloat)
            {                             
                if (_bMipmap)
                {
                    fprintf(stderr,
                        "RenderTexture Error: mipmapped float textures not "
                        "supported.\n");
                    return false;
                }
            
                switch(_iNumComponents)
                {
                case 1:
                    if (GLEW_NV_float_buffer)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
                    }
                    else if (GLEW_ATI_texture_float)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_LUMINANCE_FLOAT32_ATI :
                            GL_LUMINANCE_FLOAT16_ATI;
                    }
                    iFormat = GL_LUMINANCE;
                 break;
                case 2:
                    if (GLEW_NV_float_buffer)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
                    }
                    else if (GLEW_ATI_texture_float)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_LUMINANCE_ALPHA_FLOAT32_ATI :
                            GL_LUMINANCE_ALPHA_FLOAT16_ATI;
                    }
                    iFormat = GL_LUMINANCE_ALPHA;
                 break;
                case 3:
                    if (GLEW_NV_float_buffer)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
                    }
                    else if (GLEW_ATI_texture_float)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
                    }
                    iFormat = GL_RGB;
                    break;
                case 4:
                    if (GLEW_NV_float_buffer)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
                    }
                    else if (GLEW_ATI_texture_float)
                    {
                        iInternalFormat = (_iNumColorBits[0] > 16) ?
                            GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
                    }
                    iFormat = GL_RGBA;
                    break;
                default:
                    printf("RenderTexture Error: "
                           "Invalid number of components: %d\n",
                           _iNumComponents);
                    return false;
                }
            }
            else // non-float
            {                        
                if (4 == _iNumComponents)
                {
                    iInternalFormat = GL_RGBA8;
                    iFormat = GL_RGBA;
                }
                else
                {
                    iInternalFormat = GL_RGB8;
                    iFormat = GL_RGB;
                }
            }
        
            // Allocate the texture image (but pass it no data for now).
            glTexImage2D(_iTextureTarget, 0, iInternalFormat,
                         _iWidth, _iHeight, 0, iFormat, GL_FLOAT, NULL);
        }
    }
  
    if (_bIsDepthTexture)
    {
        glGenTextures(1, &_iDepthTextureID);
        glBindTexture(_iTextureTarget, _iDepthTextureID);  
        
        // Use clamp to edge as the default texture wrap mode for all tex
        glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        // Use NEAREST as the default texture filtering mode.
        glTexParameteri(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
               
        if (RT_COPY_TO_TEXTURE == _eUpdateMode)
        {
            // [Redge]
            if (_bHasARBDepthTexture)
            {
                // Allocate the texture image (but pass it no data for now).
                glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT,
                             _iWidth, _iHeight, 0, GL_DEPTH_COMPONENT,
                             GL_FLOAT, NULL);
            }
            else
            {
                // allocate memory for depth texture
                // Since this is slow, we warn the user in debug mode. (above)
                _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
                glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
                             _iWidth, _iHeight, 0, GL_LUMINANCE,
                             GL_UNSIGNED_SHORT, _pPoorDepthTexture);
            }
            // [/Redge]
        }
    }
    return true;
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::_MaybeCopyBuffer
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_MaybeCopyBuffer()
* @brief Does the actual copying for RenderTextures with RT_COPY_TO_TEXTURE
*/
void RenderTexture::_MaybeCopyBuffer()
{
#ifdef _WIN32
    if (RT_COPY_TO_TEXTURE == _eUpdateMode)
    {
        if (_bIsTexture)
        {
            glBindTexture(_iTextureTarget, _iTextureID);
            glCopyTexSubImage2D(_iTextureTarget,
                                0, 0, 0, 0, 0, _iWidth, _iHeight);
        }
        if (_bIsDepthTexture)
        {
            glBindTexture(_iTextureTarget, _iDepthTextureID);
            // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
            // [Redge]
            if (_bHasARBDepthTexture)
            {
                glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0,
                                    _iWidth, _iHeight);
            }
            else
            {
                // no 'real' depth texture available, so behavior has to be emulated
                // using glReadPixels (beware, this is (naturally) slow ...)
                glReadPixels(0, 0, _iWidth, _iHeight, GL_DEPTH_COMPONENT,
                             GL_UNSIGNED_SHORT, _pPoorDepthTexture);
                glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
                             _iWidth, _iHeight, 0, GL_LUMINANCE,
                             GL_UNSIGNED_SHORT, _pPoorDepthTexture);
            }
            // [/Redge]
        }
    }
   
#else
    if (_bIsTexture)
    {
      glBindTexture(_iTextureTarget, _iTextureID);
      glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
    }
    if (_bIsDepthTexture)
    {
      glBindTexture(_iTextureTarget, _iDepthTextureID);
      assert(_bHasARBDepthTexture);
      glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
    }
#endif
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::_ReleaseBoundBuffers
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_ReleaseBoundBuffers()
* @brief Releases buffer bindings on RenderTextures with RT_RENDER_TO_TEXTURE
*/
bool RenderTexture::_ReleaseBoundBuffers()
{
#ifdef _WIN32
    if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
    {
        glBindTexture(_iTextureTarget, _iTextureID);
        
        // release the pbuffer from the render texture object
        if (0 != _iCurrentBoundBuffer && _bIsBufferBound)
        {
            if (FALSE == wglReleaseTexImageARB(_hPBuffer, _iCurrentBoundBuffer))
            {
                _wglGetLastError();
                return false;
            }
            _bIsBufferBound = false;
        }
    }
   
    if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
    {
        glBindTexture(_iTextureTarget, _iDepthTextureID);
        
        // release the pbuffer from the render texture object
        if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
        {
            _wglGetLastError();
            return false;
        }
    }
   
#else
    // textures can't be bound in Linux
#endif
    return true;
}
//---------------------------------------------------------------------------
// Function      : RenderTexture::_MakeCurrent
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::_MakeCurrent()
* @brief Makes the RenderTexture's context current
*/
bool RenderTexture::_MakeCurrent()
{
#ifdef _WIN32
    // make the pbuffer's rendering context current.
    if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
    {
        _wglGetLastError();
        return false;
    }
#else
    if (false == glXMakeCurrent(_pDisplay, _hPBuffer, _hGLContext))
    {
        return false;
    }
#endif
    return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Begin Deprecated Interface
//
/////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
// Function      : RenderTexture::RenderTexture
// Description  :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::RenderTexture()
* @brief Constructor.
*/
RenderTexture::RenderTexture(int width, int height,
                               bool bIsTexture /* = true */,
                               bool bIsDepthTexture /* = false */)
:   _iWidth(width),
    _iHeight(height),
    _bIsTexture(bIsTexture),
    _bIsDepthTexture(bIsDepthTexture),
    _bHasARBDepthTexture(true),            // [Redge]
    _eUpdateMode(RT_RENDER_TO_TEXTURE),
    _bInitialized(false),
    _iNumAuxBuffers(0),
    _iCurrentBoundBuffer(0),
    _iNumDepthBits(0),
    _iNumStencilBits(0),
    _bDoubleBuffered(false),
    _bFloat(false),
    _bPowerOf2(true),
    _bRectangle(false),
    _bMipmap(false),
    _bShareObjects(false),
    _bCopyContext(false),
#ifdef _WIN32
    _hDC(NULL),
    _hGLContext(NULL),
    _hPBuffer(NULL),
    _hPreviousDC(0),
    _hPreviousContext(0),
#else
    _pDisplay(NULL),
    _hGLContext(NULL),
    _hPBuffer(0),
    _hPreviousContext(0),
    _hPreviousDrawable(0),
#endif
    _iTextureTarget(GL_NONE),
    _iTextureID(0),
    _iDepthTextureID(0),
    _pPoorDepthTexture(0) // [Redge]
{
    assert(width > 0 && height > 0);
#if defined DEBUG || defined _DEBUG
    fprintf(stderr,
            "RenderTexture Warning: Deprecated Contructor interface used.\n");
#endif
   
    _iNumColorBits[0] = _iNumColorBits[1] =
        _iNumColorBits[2] = _iNumColorBits[3] = 0;
    _bPowerOf2 = IsPowerOfTwo(width) && IsPowerOfTwo(height);
}
//------------------------------------------------------------------------------
// Function      : RenderTexture::Initialize
// Description     :
//------------------------------------------------------------------------------
/**
* @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
* @brief Initializes the RenderTexture, sharing display lists and textures if specified.
*
* This function actually does the creation of the p-buffer.  It can only be called
* once a GL context has already been created.  Note that if the texture is not
* power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
* will cause an error.
*/
bool RenderTexture::Initialize(bool         bShare       /* = true */,
                                bool         bDepth       /* = false */,
                                bool         bStencil     /* = false */,
                                bool         bMipmap      /* = false */,
                                bool         bAnisoFilter /* = false */,
                                unsigned int iRBits       /* = 8 */,
                                unsigned int iGBits       /* = 8 */,
                                unsigned int iBBits       /* = 8 */,
                                unsigned int iABits       /* = 8 */,
                                UpdateMode   updateMode   /* = RT_RENDER_TO_TEXTURE */)
{   
    if (0 == _iWidth || 0 == _iHeight)
        return false;
#if defined DEBUG || defined _DEBUG
    fprintf(stderr,
            "RenderTexture Warning: Deprecated Initialize() interface used.\n");
#endif   
    // create a mode string.
    string mode = "";
    if (bDepth)
        mode.append("depth ");
    if (bStencil)
        mode.append("stencil ");
    if (bMipmap)
        mode.append("mipmap ");
    if (iRBits + iGBits + iBBits + iABits > 0)
    {
        if (iRBits > 0)
            mode.append("r");
        if (iGBits > 0)
            mode.append("g");
        if (iBBits > 0)
            mode.append("b");
        if (iABits > 0)
            mode.append("a");
        mode.append("=");
        char bitVector[100];
        sprintf(bitVector,
            "%d%s,%d%s,%d%s,%d%s",
            iRBits, (iRBits >= 16) ? "f" : "",
            iGBits, (iGBits >= 16) ? "f" : "",
            iBBits, (iBBits >= 16) ? "f" : "",
            iABits, (iABits >= 16) ? "f" : "");
        mode.append(bitVector);
        mode.append(" ");
    }
    if (_bIsTexture)
    {
        if (GLEW_NV_texture_rectangle &&
            ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
              || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
            mode.append("texRECT ");
        else
            mode.append("tex2D ");
    }
    if (_bIsDepthTexture)
    {
        if (GLEW_NV_texture_rectangle &&
            ((!IsPowerOfTwo(_iWidth) || !IsPowerOfTwo(_iHeight))
              || iRBits >= 16 || iGBits > 16 || iBBits > 16 || iABits >= 16))
            mode.append("texRECT ");
        else
            mode.append("tex2D ");
    }
    if (RT_COPY_TO_TEXTURE == updateMode)
        mode.append("ctt");
    _pixelFormatAttribs.clear();
    _pbufferAttribs.clear();
#ifdef _WIN32
    _pixelFormatAttribs.push_back(WGL_DRAW_TO_PBUFFER_ARB);
    _pixelFormatAttribs.push_back(true);
    _pixelFormatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
    _pixelFormatAttribs.push_back(true);
   
    _pbufferAttribs.push_back(WGL_PBUFFER_LARGEST_ARB);
    _pbufferAttribs.push_back(true);
#else
    _pixelFormatAttribs.push_back(GLX_RENDER_TYPE_SGIX);
    _pixelFormatAttribs.push_back(GLX_RGBA_BIT_SGIX);
    _pixelFormatAttribs.push_back(GLX_DRAWABLE_TYPE_SGIX);
    _pixelFormatAttribs.push_back(GLX_PBUFFER_BIT_SGIX);
#endif
    _ParseModeString(mode.c_str(), _pixelFormatAttribs, _pbufferAttribs);
#ifdef _WIN32
    _pixelFormatAttribs.push_back(0);
    _pbufferAttribs.push_back(0);
#else
    _pixelFormatAttribs.push_back(None);
#endif
    Initialize(_iWidth, _iHeight, bShare);
   
    return true;
}

//---------------------------------------------------------------------------
// Function      : RenderTexture::Reset
// Description     :
//---------------------------------------------------------------------------
/**
* @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
* @brief Resets the resolution of the offscreen buffer.
*
* Causes the buffer to delete itself.  User must call Initialize() again
* before use.
*/
bool RenderTexture::Reset(int iWidth, int iHeight)
{
    fprintf(stderr,
            "RenderTexture Warning: Deprecated Reset() interface used.\n");
    if (!_Invalidate())
    {
        fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
        return false;
    }
    _iWidth     = iWidth;
    _iHeight    = iHeight;
   
    return true;
}
 楼主| 发表于 2007-7-22 16:43:51 | 显示全部楼层

回复: OpenCSG-1.0.2 sample

3.renderSCS.cpp
// OpenCSG - library for image-based CSG rendering for OpenGL
// Copyright (C) 2002-2004
// Hasso-Plattner-Institute at the University of Potsdam, Germany, and Florian Kirsch
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License,
// Version 2, as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// renderSCS.cpp
//
// stuff specific for the SCS algorithm
//
#include <opencsgConfig.h>
#include <opencsg.h>
#include "opencsgRender.h"
#include "batch.h"
#include "channelManager.h"
#include "occlusionQuery.h"
#include "openglHelper.h"
#include "primitiveHelper.h"
#include "scissorMemo.h"
#include <map>
namespace OpenCSG {
namespace {
ScissorMemo* scissor;
struct RenderData {
unsigned int stencilID_;
};
std::map<rimitive*, RenderData> renderInfo_;
RenderData* getRenderData(Primitive* primitive) {
RenderData* dta = &(renderInfo_.find(primitive))->second;
return dta;
}

class SCSChannelManager : public ChannelManagerForBatches {
public:
virtual void merge();
};
void SCSChannelManager::merge() {
setupProjectiveTexture();
glEnable(GL_ALPHA_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
std::vector<Channel> channels = occupied();
for (std::vector<Channel>::const_iterator c = channels.begin(); c!=channels.end(); ++c) {
setupTexEnv(*c);
scissor->recall(*c);
scissor->enable();
const std::vector<rimitive*> primitives = getPrimitives(*c);
for (std::vector<rimitive*>::const_iterator j = primitives.begin(); j != primitives.end(); ++j) {
glCullFace((*j)->getOperation() == Intersection ? GL_BACK : GL_FRONT);
RenderData* primitiveData = getRenderData(*j);
unsigned char id = primitiveData->stencilID_;
glAlphaFunc(GL_EQUAL, static_cast<float>(id) / 255.0f);
(*j)->render();
}
}
scissor->disable();
resetProjectiveTexture();
clear();
}
class IDGenerator {
public:
IDGenerator() { currentID_ = 0; };
unsigned int newID() { return ++currentID_; };
private:
unsigned int currentID_;
};
IDGenerator* IDGenerator_;
SCSChannelManager* channelMgr;
void renderIntersectedFront(const std::vector<rimitive*>& primitives) {
const int numberOfPrimitives = primitives.size();
glDepthMask(GL_TRUE);
// optimization for only one shape
if (numberOfPrimitives == 1) {
channelMgr->renderToChannel(true);
glDepthFunc(GL_GREATER);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
RenderData* primitiveData = getRenderData(primitives[0]);
GLubyte b = primitiveData->stencilID_; glColor4ub(b, b, b, b);
primitives[0]->render();
glDisable(GL_CULL_FACE);
glDepthFunc(GL_LESS);
return;
}
// draw furthest front face
channelMgr->renderToChannel(true);
glStencilMask(OpenGL::stencilMask);
glDepthFunc(GL_GREATER);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
{
for (std::vector<rimitive*>::const_iterator i = primitives.begin(); i != primitives.end(); ++i) {
RenderData* primitiveData = getRenderData(*i);
GLubyte b = primitiveData->stencilID_; glColor4ub(b, b, b, b);
(*i)->render();
}
}
// count back faces behind furthest front face
channelMgr->renderToChannel(false);
glStencilFunc(GL_ALWAYS, 0, OpenGL::stencilMask);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glEnable(GL_STENCIL_TEST);
glDepthMask(GL_FALSE);
glCullFace(GL_FRONT);
{
for (std::vector<rimitive*>::const_iterator i = primitives.begin(); i != primitives.end(); ++i) {
(*i)->render();
}
}
// where #back faces behind furthest front face != #intersected shapes
// ->reset fragment
channelMgr->renderToChannel(true);
glStencilFunc(GL_NOTEQUAL, numberOfPrimitives, OpenGL::stencilMask);
glDepthFunc(GL_ALWAYS);
glDepthRange(0.0, 0.0);
glDepthMask(GL_TRUE);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDisable(GL_CULL_FACE);
glColor4ub(0, 0, 0, 0);
OpenGL::drawQuad();
glDepthRange(0.0, 1.0);
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
}
void subtractPrimitives(std::vector<Batch>::const_iterator begin,
std::vector<Batch>::const_iterator end,
const unsigned int iterations) {
if (begin == end) {
return;
}
glStencilMask(OpenGL::stencilMask);
glEnable(GL_STENCIL_TEST);
glEnable(GL_CULL_FACE);
int stencilref = 0;
int sense = 1;
unsigned int changes = 0;
std::vector<Batch>::const_iterator i = begin;
do {
// create a distinct reference value
++stencilref;
if (stencilref == OpenGL::stencilMax) {
glClear(GL_STENCIL_BUFFER_BIT);
stencilref = 1;
}
channelMgr->renderToChannel(false);
glDepthFunc(GL_LESS);
glDepthMask(GL_FALSE);
glStencilFunc(GL_ALWAYS, stencilref, OpenGL::stencilMask);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glCullFace(GL_BACK);
{
for (Batch::const_iterator j = i->begin(); j != i->end(); ++j) {
(*j)->render();
}
}
// where front faces have been visible, render back faces
channelMgr->renderToChannel(true);
glDepthFunc(GL_GREATER);
glDepthMask(GL_TRUE);
glCullFace(GL_FRONT);
glStencilFunc(GL_EQUAL, stencilref, OpenGL::stencilMask);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
{
for (Batch::const_iterator j = i->begin(); j != i->end(); ++j) {
RenderData* primitiveData = getRenderData(*j);
GLubyte b = primitiveData->stencilID_; glColor4ub(b, b, b, b);
(*j)->render();
}
}
if (sense == 1) {
++i;
if (i == end) {
sense = 0;
--i; if (i == begin) break; // only one subtracted shape
--i;
++changes;
}
} else {
if (i == begin) {
sense = 1;
++i;
++changes;
} else {
--i;
}
}
} while (changes < iterations);
glDisable(GL_STENCIL_TEST);
}
void subtractPrimitivesWithOcclusionQueries(std::vector<Batch>::const_iterator begin,
std::vector<Batch>::const_iterator end) {
const unsigned int numberOfBatches = end - begin;
if (numberOfBatches == 0) {
return;
}
glStencilMask(OpenGL::stencilMask);
glEnable(GL_STENCIL_TEST);
glEnable(GL_CULL_FACE);
OpenGL::OcclusionQuery* occlusionTest = OpenGL::getOcclusionQuery();
std::vector<unsigned int> fragmentcount(numberOfBatches, 0);
int stencilref = 0;
std::vector<Batch>::const_iterator i = begin;
unsigned int shapesWithoutUpdate = 0;
unsigned int shapeCount = 0;
int idx=0;
do {
// create a distinct reference value
++stencilref;
if (stencilref == OpenGL::stencilMax) {
glClear(GL_STENCIL_BUFFER_BIT);
stencilref = 1;
}
channelMgr->renderToChannel(false);
glDepthFunc(GL_LESS);
glDepthMask(GL_FALSE);
glStencilFunc(GL_ALWAYS, stencilref, OpenGL::stencilMask);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glCullFace(GL_BACK);
occlusionTest->beginQuery();
{
for (Batch::const_iterator j = i->begin(); j != i->end(); ++j) {
(*j)->render();
}
}
occlusionTest->endQuery();
// the fragment count query could occur here, but benches show that
// the algorithm is faster if the query is delayed.
// where front faces have been visible, render back faces
channelMgr->renderToChannel(true);
glDepthFunc(GL_GREATER);
glDepthMask(GL_TRUE);
glCullFace(GL_FRONT);
glStencilFunc(GL_EQUAL, stencilref, OpenGL::stencilMask);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
{
for (Batch::const_iterator j = i->begin(); j != i->end(); ++j) {
RenderData* primitiveData = getRenderData(*j);
GLubyte b = primitiveData->stencilID_; glColor4ub(b, b, b, b);
(*j)->render();
}
}
unsigned int newFragmentCount = occlusionTest->getQueryResult();
if (newFragmentCount != fragmentcount[idx]) {
fragmentcount[idx] = newFragmentCount;
shapesWithoutUpdate = 0;
} else {
++shapesWithoutUpdate;
}
++i; ++idx; if (i == end) {
i = begin;
idx = 0;
}

++shapeCount;
if (shapeCount >= (numberOfBatches) * (numberOfBatches) - (numberOfBatches) + 1) break;
} while (shapesWithoutUpdate < numberOfBatches);
delete occlusionTest;
glDisable(GL_STENCIL_TEST);
}
void renderIntersectedBack(const std::vector<rimitive*>& primitives) {
// where a back face of intersected shape is in front of any subtracted shape
// mask fragment as invisible. Updating depth calues is not necessary, so when
// having IDs, this is kind of simple.
channelMgr->renderToChannel(true);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glDepthMask(GL_FALSE);
glDepthFunc(GL_LESS);
glColor4ub(0, 0, 0, 0);
for (std::vector<rimitive*>::const_iterator i = primitives.begin(); i != primitives.end(); ++i) {
(*i)->render();
}
glDepthMask(GL_TRUE);
}
} // unnamed namespace
void renderSCS(const std::vector<rimitive*>& primitives, DepthComplexityAlgorithm algorithm) {
renderInfo_.clear();
IDGenerator_ = new IDGenerator();
channelMgr = new SCSChannelManager;
scissor = new ScissorMemo;
std::vector<rimitive*> intersected;
std::vector<Primitive*> subtracted;
{
for (std::vector<Primitive*>::const_iterator itr = primitives.begin(); itr != primitives.end(); ++itr) {
{
RenderData dta;
dta.stencilID_ = IDGenerator_->newID();
renderInfo_.insert(std::make_pair(*itr, dta));
}
Operation operation= (*itr)->getOperation();
if (operation == Intersection) {
intersected.push_back(*itr);
} else if (operation == Subtraction) {
subtracted.push_back(*itr);
}
}
}
Batcher subtractedBatches(subtracted);
scissor->setIntersected(intersected);
scissor->setCurrent(intersected);
unsigned int depthComplexity = 0;
if (algorithm == DepthComplexitySampling) {
scissor->enable();
glClear(GL_STENCIL_BUFFER_BIT);
depthComplexity =
std::min(OpenGL::calcMaxDepthComplexity(subtracted, scissor->getCurrentArea()),
subtractedBatches.size());
}
channelMgr->request();
channelMgr->renderToChannel(true);

scissor->enable();
scissor->store(channelMgr->current());
glDepthMask(GL_TRUE);
glStencilMask(OpenGL::stencilMask);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearDepth(0.0); // near clipping plane! essential for algorithm!
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClearDepth(1.0);
renderIntersectedFront(intersected);
switch (algorithm) {
case NoDepthComplexitySampling:
subtractPrimitives(subtractedBatches.begin(), subtractedBatches.end(), subtractedBatches.size());
break;
case OcclusionQuery:
subtractPrimitivesWithOcclusionQueries(subtractedBatches.begin(), subtractedBatches.end());
break;
case DepthComplexitySampling:
subtractPrimitives(subtractedBatches.begin(), subtractedBatches.end(), depthComplexity);
break;
}
renderIntersectedBack(intersected);
scissor->disable();
channelMgr->store(channelMgr->current(), primitives, 0);
channelMgr->free();
delete scissor;
delete channelMgr;
delete IDGenerator_;
}
} // namespace OpenCSG
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|小黑屋|几何尺寸与公差论坛

GMT+8, 2024-5-7 21:57 , Processed in 0.113287 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表