📄 rendertexture.cpp
字号:
//------------------------------------------------------------------------------
// 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.
/**
* @file RenderTexture.cpp
*
* Implementation of class RenderTexture. A multi-format render to
* texture wrapper.
*/
#include "stdafx.h"
#include "Shadow.h"
#include "RenderTexture.h"
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
//------------------------------------------------------------------------------
// 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),
_eUpdateMode(RT_RENDER_TO_TEXTURE),
_bInitialized(false),
_bFloat(false),
_bRectangle(false),
_bHasDepth(false),
_bHasStencil(false),
_bMipmap(false),
_bAnisoFilter(false),
_hDC(NULL),
_hGLContext(NULL),
_hPBuffer(NULL),
_hPreviousDC(0),
_hPreviousContext(0),
_iTextureTarget(GL_NONE),
_iTextureID(0)
{
assert(iWidth > 0 && iHeight > 0);
_iBits[0] = _iBits[1] = _iBits[2] = _iBits[3] = 0;
}
//------------------------------------------------------------------------------
// Function : RenderTexture::~RenderTexture
// Description :
//------------------------------------------------------------------------------
/**
* @fn RenderTexture::~RenderTexture()
* @brief Destructor.
*/
RenderTexture::~RenderTexture()
{
_Invalidate();
}
// Check to see if the pbuffer was lost.
// If it was lost, destroy it and then recreate it.
void RenderTexture::HandleModeSwitch()
{
int lost = 0;
wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_LOST_ARB, &lost );
if ( lost )
{
this->~RenderTexture();
Initialize();
}
}
//------------------------------------------------------------------------------
// Function : wglGetLastError
// Description :
//------------------------------------------------------------------------------
/**
* @fn wglGetLastError()
* @brief Returns the last windows error generated.
*/
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
}
//------------------------------------------------------------------------------
// 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);
_vsnprintf( strBuffer, 512, strMsg, args );
va_end(args);
fprintf(stderr, strMsg);
}
//------------------------------------------------------------------------------
// 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::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 /* = false */,
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 (!extgl_Extensions.wgl.ARB_pbuffer)
{
PrintExtensionError("WGL_ARB_pbuffer");
return false;
}
if (!extgl_Extensions.wgl.ARB_pixel_format)
{
PrintExtensionError("WGL_ARB_pixel_format");
return false;
}
if (_bIsTexture && !extgl_Extensions.wgl.ARB_render_texture)
{
PrintExtensionError("WGL_ARB_render_texture");
return false;
}
if (_bIsDepthTexture && !extgl_Extensions.ARB_depth_texture)
{
PrintExtensionError("GL_ARB_depth_texture");
return false;
}
SetLastError(0);
if (_bInitialized)
_Invalidate();
_bFloat = (iRBits > 8 || iGBits > 8 || iBBits > 8 || iABits > 8);
bool bNVIDIA = true;
if (_bFloat && !extgl_Extensions.NV_float_buffer)
{
bNVIDIA = false;
if (!extgl_Extensions.wgl.ATI_pixel_format_float)
{
PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
return false;
}
}
if (_bFloat && _bIsTexture && !bNVIDIA && !extgl_Extensions.ATI_texture_float)
{
PrintExtensionError("NV_float_buffer or ATI_texture_float");
}
if (!_bFloat && !extgl_Extensions.NV_texture_rectangle)
{
bNVIDIA = false;
}
_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;
GLuint iBindTarget;
GLuint iTextureFormat;
GLuint iDepthBindTarget;
GLuint iDepthTextureFormat;
if (_bIsTexture)
glGenTextures(1, &_iTextureID);
if (_bIsDepthTexture)
glGenTextures(1, &_iDepthTextureID);
// Determine the appropriate texture formats and filtering modes.
if (_bIsTexture)
{
if (_bFloat)
{
if (!bNVIDIA && !(IsPowerOfTwo(_iWidth) && IsPowerOfTwo(_iHeight)))
{
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
{
if (bNVIDIA)
iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
else
iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
if (iABits > 0)
{
if (bNVIDIA)
{
iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -