⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rendertexture.cpp

📁 PDE simulator on GPU.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
// File : RenderTexture.cpp
//------------------------------------------------------------------------------
// Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its 
// documentation for any purpose is hereby granted without fee, provided that 
// the above copyright notice appear in all copies and that both that copyright 
// notice and this permission notice appear in supporting documentation. 
// Binaries may be compiled with this software without any royalties or 
// restrictions. 
//
// The author(s) and The University of North Carolina at Chapel Hill make no 
// representations about the suitability of this software for any purpose. 
// It is provided "as is" without express or implied warranty.
//
// -----------------------------------------------------------------------------
// 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
//
// -----------------------------------------------------------------------------
/**
 * @file RenderTexture.cpp
 * 
 * Implementation of class RenderTexture.  A multi-format render to 
 * texture wrapper.
 */

#include "stdafx.h"

#include "RenderTexture.h"
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>

//------------------------------------------------------------------------------
// Function     	  : IsPowerOfTwo
// Description	    : 
//------------------------------------------------------------------------------
/**
 * @fn IsPowerOfTwo(int n)
 * @brief Returns true if /param n is an integer power of 2.
 * 
 * Taken from Steve Baker's Cute Code Collection.
 */ 
bool IsPowerOfTwo(int n)
{
  return ((n&(n-1))==0);
}

//------------------------------------------------------------------------------
// Function      : RenderTexture::RenderTexture
// Description	 : 
//------------------------------------------------------------------------------
/**
 * @fn RenderTexture::RenderTexture()
 * @brief Constructor.
 */ 
RenderTexture::RenderTexture(int iWidth, int iHeight, bool bIsTexture /* = true */,
							 bool bIsDepthTexture /* = false */)
: _iWidth(iWidth), 
  _iHeight(iHeight), 
  _bIsTexture(bIsTexture),
  _bIsDepthTexture(bIsDepthTexture),
  _bHasArbDepthTexture(true),            // [Redge]
  _eUpdateMode(RT_RENDER_TO_TEXTURE),
  _bInitialized(false),
  _bFloat(false),
  _bRectangle(false),
  _bHasDepth(false),
  _bHasStencil(false),
  _bMipmap(false),
  _bAnisoFilter(false),
#ifdef _WIN32
  _hDC(NULL), 
  _hGLContext(NULL), 
  _hPBuffer(NULL),
  _hPreviousDC(0),
  _hPreviousContext(0),
#else
  _pDpy(NULL),
  _hGLContext(NULL),
  _hPBuffer(0),
  _hPreviousContext(0),
  _hPreviousDrawable(0),
#endif
  _iTextureTarget(GL_NONE),
  _iTextureID(0),
  _pPoorDepthTexture(0) // [Redge]
{
  assert(iWidth > 0 && iHeight > 0);
  _iBits[0] = _iBits[1] = _iBits[2] = _iBits[3] = 0;
  _bRectangle = !(IsPowerOfTwo(iWidth) && IsPowerOfTwo(iHeight));
}


//------------------------------------------------------------------------------
// 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 RenderTexture::_wglGetLastError()
{
#ifdef _DEBUG

  DWORD err = GetLastError();
  switch(err)
  {
  case ERROR_INVALID_PIXEL_FORMAT:
    fprintf(stderr, "Win32 Error:  ERROR_INVALID_PIXEL_FORMAT\n");
    break;
  case ERROR_NO_SYSTEM_RESOURCES:
    fprintf(stderr, "Win32 Error:  ERROR_NO_SYSTEM_RESOURCES\n");
    break;
  case ERROR_INVALID_DATA:
    fprintf(stderr, "Win32 Error:  ERROR_INVALID_DATA\n");
    break;
  case ERROR_INVALID_WINDOW_HANDLE:
    fprintf(stderr, "Win32 Error:  ERROR_INVALID_WINDOW_HANDLE\n");
    break;
  case ERROR_RESOURCE_TYPE_NOT_FOUND:
    fprintf(stderr, "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, "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);

  exit(1);
}


//------------------------------------------------------------------------------
// Function     	  : RenderTexture::Initialize
// Description	    : 
//------------------------------------------------------------------------------
/**
 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, bool bAnisoFilter, 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
 * or aniso filtering 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 */)
{
#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 (_bIsDepthTexture && !GLEW_ARB_depth_texture)
  {
    // [Redge]
#if defined(_DEBUG) | defined(DEBUG)
    fprintf(stderr, "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)
  {
    PrintExtensionError("I don't know");
    return false;
  }
  if (updateMode == RT_RENDER_TO_TEXTURE)
  {
    PrintExtensionError("Some GLX render texture extension");
  }
#endif

  if (_bInitialized)
    _Invalidate();
 
  _bFloat = (iRBits > 8 || iGBits > 8 || iBBits > 8 || iABits > 8);
  
  bool bNVIDIA = true;
#ifdef _WIN32
  if (_bFloat && !GLEW_NV_float_buffer)
  {
    bNVIDIA = false;
    if (!WGLEW_ATI_pixel_format_float)
    {
      PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
      return false;
    }
  }
  if (_bFloat && _bIsTexture && !bNVIDIA && !GLEW_ATI_texture_float)
  {
	  PrintExtensionError("NV_float_buffer or ATI_texture_float");
  }
#else
  if (_bFloat && _bIsTexture && !GLXEW_NV_float_buffer)
  {
    PrintExtensionError("GLX_NV_float_buffer");
    return false;
  }
#endif  
  if (!_bFloat && !GLEW_NV_texture_rectangle)
  {
    bNVIDIA = false;
  }
  
  _bRectangle = _bRectangle || (_bFloat && bNVIDIA);

  if(_bIsDepthTexture)
    _bHasDepth  = true;    // we need depth for a depth texture...
  else
    _bHasDepth  = bDepth;

  _bHasStencil  = bStencil;
  _bMipmap      = false;   // until it is enabled.
  _bAnisoFilter = false;   // until it is enabled.
  _eUpdateMode  = updateMode;

  GLuint iWGLTextureTarget = 0;
  GLuint iBindTarget = 0;
  GLuint iTextureFormat = 0;
  GLuint iDepthBindTarget = 0;
  GLuint iDepthTextureFormat = 0;

  if (_bIsTexture)
    glGenTextures(1, &_iTextureID);
  if (_bIsDepthTexture)
    glGenTextures(1, &_iDepthTextureID);
  
  // Determine the appropriate texture formats and filtering modes.
  if (_bIsTexture)
  {
    if (_bFloat)
    {      
      if (!bNVIDIA && _bRectangle)
      {
        fprintf(stderr, 
                "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
        return false;
      }

      if (bNVIDIA)
        _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
      else
        _iTextureTarget = GL_TEXTURE_2D;
    
      glBindTexture(_iTextureTarget, _iTextureID);  
    
      // We'll use clamp to edge as the default texture wrap mode for all tex types
      glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
      glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
      if (bMipmap)
      {
        fprintf(stderr, 
                "RenderTexture Error: float textures do not support mipmaps\n");
        return false;
      }

      if (RT_COPY_TO_TEXTURE == _eUpdateMode)
      {
        GLuint iInternalFormat;
        GLuint iFormat;
        if (iABits > 0)
        {
          if (bNVIDIA)
            iInternalFormat = (iABits > 16) ? GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
          else
            iInternalFormat = (iABits > 16) ? GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
          iFormat = GL_RGBA;
        }
        else if (iBBits > 0)
        {
          if (bNVIDIA)
            iInternalFormat = (iBBits > 16) ? GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
          else
            iInternalFormat = (iBBits > 16) ? GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
          iFormat = GL_RGB;
        }
        else if (iGBits > 0)
        {
          if (bNVIDIA)
            iInternalFormat = (iGBits > 16) ? GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
          else
            iInternalFormat = (iGBits > 16) ? GL_LUMINANCE_ALPHA_FLOAT32_ATI : 
                                              GL_LUMINANCE_ALPHA_FLOAT16_ATI;
          iFormat = GL_LUMINANCE_ALPHA;
        }
        else 
        {
          if (bNVIDIA)
            iInternalFormat = (iRBits > 16) ? GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
          else
            iInternalFormat = (iRBits > 16) ? GL_LUMINANCE_FLOAT32_ATI : 
                                              GL_LUMINANCE_FLOAT16_ATI;
          iFormat = GL_LUMINANCE;
        }
        // Allocate the texture image (but pass it no data for now).
        glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight, 
                     0, iFormat, GL_FLOAT, NULL);
      }
      else
      {
#ifdef _WIN32 
        if (bNVIDIA)
          iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
        else
          iWGLTextureTarget = WGL_TEXTURE_2D_ARB;

        if (iABits > 0) 
        { 
          if (bNVIDIA)
          {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -