[1940] | 1 | //------------------------------------------------------------------------------
|
---|
| 2 | // File : RenderTexture.cpp
|
---|
| 3 | //------------------------------------------------------------------------------
|
---|
| 4 | // Copyright 2002 Mark J. Harris and
|
---|
| 5 | // The University of North Carolina at Chapel Hill
|
---|
| 6 | //------------------------------------------------------------------------------
|
---|
| 7 | // Permission to use, copy, modify, distribute and sell this software and its
|
---|
| 8 | // documentation for any purpose is hereby granted without fee, provided that
|
---|
| 9 | // the above copyright notice appear in all copies and that both that copyright
|
---|
| 10 | // notice and this permission notice appear in supporting documentation.
|
---|
| 11 | // Binaries may be compiled with this software without any royalties or
|
---|
| 12 | // restrictions.
|
---|
| 13 | //
|
---|
| 14 | // The author(s) and The University of North Carolina at Chapel Hill make no
|
---|
| 15 | // representations about the suitability of this software for any purpose.
|
---|
| 16 | // It is provided "as is" without express or implied warranty.
|
---|
| 17 | //
|
---|
| 18 | // -----------------------------------------------------------------------------
|
---|
| 19 | // Credits:
|
---|
| 20 | // Original RenderTexture class: Mark J. Harris
|
---|
| 21 | // Original Render-to-depth-texture support: Thorsten Scheuermann
|
---|
| 22 | // Linux Copy-to-texture: Eric Werness
|
---|
| 23 | // Various Bug Fixes: Daniel (Redge) Sperl
|
---|
| 24 | // Bill Baxter
|
---|
| 25 | //
|
---|
| 26 | // -----------------------------------------------------------------------------
|
---|
| 27 | /**
|
---|
| 28 | * @file RenderTexture.cpp
|
---|
| 29 | *
|
---|
| 30 | * Implementation of class RenderTexture. A multi-format render to
|
---|
| 31 | * texture wrapper.
|
---|
| 32 | */
|
---|
| 33 | #include "RenderTexture.h"
|
---|
| 34 | #include <GL/glut.h>
|
---|
| 35 | #include <stdio.h>
|
---|
| 36 | #include <stdlib.h>
|
---|
| 37 | #include <stdarg.h>
|
---|
| 38 | #include <assert.h>
|
---|
| 39 |
|
---|
| 40 | //------------------------------------------------------------------------------
|
---|
| 41 | // Function : IsPowerOfTwo
|
---|
| 42 | // Description :
|
---|
| 43 | //------------------------------------------------------------------------------
|
---|
| 44 | /**
|
---|
| 45 | * @fn IsPowerOfTwo(int n)
|
---|
| 46 | * @brief Returns true if /param n is an integer power of 2.
|
---|
| 47 | *
|
---|
| 48 | * Taken from Steve Baker's Cute Code Collection.
|
---|
| 49 | */
|
---|
| 50 | bool IsPowerOfTwo(int n)
|
---|
| 51 | {
|
---|
| 52 | return ((n&(n-1))==0);
|
---|
| 53 | }
|
---|
| 54 |
|
---|
| 55 | //------------------------------------------------------------------------------
|
---|
| 56 | // Function : RenderTexture::RenderTexture
|
---|
| 57 | // Description :
|
---|
| 58 | //------------------------------------------------------------------------------
|
---|
| 59 | /**
|
---|
| 60 | * @fn RenderTexture::RenderTexture()
|
---|
| 61 | * @brief Constructor.
|
---|
| 62 | */
|
---|
| 63 | RenderTexture::RenderTexture(int iWidth, int iHeight, bool bIsTexture /* = true */,
|
---|
| 64 | bool bIsDepthTexture /* = false */)
|
---|
| 65 | : _iWidth(iWidth),
|
---|
| 66 | _iHeight(iHeight),
|
---|
| 67 | _bIsTexture(bIsTexture),
|
---|
| 68 | _bIsDepthTexture(bIsDepthTexture),
|
---|
| 69 | _bHasArbDepthTexture(true), // [Redge]
|
---|
| 70 | _eUpdateMode(RT_RENDER_TO_TEXTURE),
|
---|
| 71 | _bInitialized(false),
|
---|
| 72 | _bFloat(false),
|
---|
| 73 | _bRectangle(false),
|
---|
| 74 | _bHasDepth(false),
|
---|
| 75 | _bHasStencil(false),
|
---|
| 76 | _bMipmap(false),
|
---|
| 77 | _bAnisoFilter(false),
|
---|
| 78 | #ifdef _WIN32
|
---|
| 79 | _hDC(NULL),
|
---|
| 80 | _hGLContext(NULL),
|
---|
| 81 | _hPBuffer(NULL),
|
---|
| 82 | _hPreviousDC(0),
|
---|
| 83 | _hPreviousContext(0),
|
---|
| 84 | #else
|
---|
| 85 | _pDpy(NULL),
|
---|
| 86 | _hGLContext(NULL),
|
---|
| 87 | _hPBuffer(0),
|
---|
| 88 | _hPreviousContext(0),
|
---|
| 89 | _hPreviousDrawable(0),
|
---|
| 90 | #endif
|
---|
| 91 | _iTextureTarget(GL_NONE),
|
---|
| 92 | _iTextureID(0),
|
---|
| 93 | _pPoorDepthTexture(0) // [Redge]
|
---|
| 94 | {
|
---|
| 95 | assert(iWidth > 0 && iHeight > 0);
|
---|
| 96 | _iBits[0] = _iBits[1] = _iBits[2] = _iBits[3] = 0;
|
---|
| 97 | _bRectangle = !(IsPowerOfTwo(iWidth) && IsPowerOfTwo(iHeight));
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 |
|
---|
| 101 | //------------------------------------------------------------------------------
|
---|
| 102 | // Function : RenderTexture::~RenderTexture
|
---|
| 103 | // Description :
|
---|
| 104 | //------------------------------------------------------------------------------
|
---|
| 105 | /**
|
---|
| 106 | * @fn RenderTexture::~RenderTexture()
|
---|
| 107 | * @brief Destructor.
|
---|
| 108 | */
|
---|
| 109 | RenderTexture::~RenderTexture()
|
---|
| 110 | {
|
---|
| 111 | _Invalidate();
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 |
|
---|
| 115 | //------------------------------------------------------------------------------
|
---|
| 116 | // Function : wglGetLastError
|
---|
| 117 | // Description :
|
---|
| 118 | //------------------------------------------------------------------------------
|
---|
| 119 | /**
|
---|
| 120 | * @fn wglGetLastError()
|
---|
| 121 | * @brief Returns the last windows error generated.
|
---|
| 122 | */
|
---|
| 123 | #ifdef _WIN32
|
---|
| 124 | void RenderTexture::_wglGetLastError()
|
---|
| 125 | {
|
---|
| 126 | #ifdef _DEBUG
|
---|
| 127 |
|
---|
| 128 | DWORD err = GetLastError();
|
---|
| 129 | switch(err)
|
---|
| 130 | {
|
---|
| 131 | case ERROR_INVALID_PIXEL_FORMAT:
|
---|
| 132 | fprintf(stderr, "Win32 Error: ERROR_INVALID_PIXEL_FORMAT\n");
|
---|
| 133 | break;
|
---|
| 134 | case ERROR_NO_SYSTEM_RESOURCES:
|
---|
| 135 | fprintf(stderr, "Win32 Error: ERROR_NO_SYSTEM_RESOURCES\n");
|
---|
| 136 | break;
|
---|
| 137 | case ERROR_INVALID_DATA:
|
---|
| 138 | fprintf(stderr, "Win32 Error: ERROR_INVALID_DATA\n");
|
---|
| 139 | break;
|
---|
| 140 | case ERROR_INVALID_WINDOW_HANDLE:
|
---|
| 141 | fprintf(stderr, "Win32 Error: ERROR_INVALID_WINDOW_HANDLE\n");
|
---|
| 142 | break;
|
---|
| 143 | case ERROR_RESOURCE_TYPE_NOT_FOUND:
|
---|
| 144 | fprintf(stderr, "Win32 Error: ERROR_RESOURCE_TYPE_NOT_FOUND\n");
|
---|
| 145 | break;
|
---|
| 146 | case ERROR_SUCCESS:
|
---|
| 147 | // no error
|
---|
| 148 | break;
|
---|
| 149 | default:
|
---|
| 150 | LPVOID lpMsgBuf;
|
---|
| 151 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
---|
| 152 | FORMAT_MESSAGE_FROM_SYSTEM |
|
---|
| 153 | FORMAT_MESSAGE_IGNORE_INSERTS,
|
---|
| 154 | NULL,
|
---|
| 155 | err,
|
---|
| 156 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
---|
| 157 | (LPTSTR) &lpMsgBuf,
|
---|
| 158 | 0,
|
---|
| 159 | NULL);
|
---|
| 160 |
|
---|
| 161 | fprintf(stderr, "Win32 Error %d: %s\n", err, lpMsgBuf);
|
---|
| 162 | LocalFree( lpMsgBuf );
|
---|
| 163 | break;
|
---|
| 164 | }
|
---|
| 165 | SetLastError(0);
|
---|
| 166 |
|
---|
| 167 | #endif // _DEBUG
|
---|
| 168 | }
|
---|
| 169 | #endif
|
---|
| 170 |
|
---|
| 171 | //------------------------------------------------------------------------------
|
---|
| 172 | // Function : PrintExtensionError
|
---|
| 173 | // Description :
|
---|
| 174 | //------------------------------------------------------------------------------
|
---|
| 175 | /**
|
---|
| 176 | * @fn PrintExtensionError( char* strMsg, ... )
|
---|
| 177 | * @brief Prints an error about missing OpenGL extensions.
|
---|
| 178 | */
|
---|
| 179 | void PrintExtensionError( char* strMsg, ... )
|
---|
| 180 | {
|
---|
| 181 | fprintf(stderr, "Error: RenderTexture requires the following unsupported "
|
---|
| 182 | "OpenGL extensions: \n");
|
---|
| 183 | char strBuffer[512];
|
---|
| 184 | va_list args;
|
---|
| 185 | va_start(args, strMsg);
|
---|
| 186 | #ifdef _WIN32
|
---|
| 187 | _vsnprintf( strBuffer, 512, strMsg, args );
|
---|
| 188 | #else
|
---|
| 189 | vsnprintf( strBuffer, 512, strMsg, args );
|
---|
| 190 | #endif
|
---|
| 191 | va_end(args);
|
---|
| 192 |
|
---|
| 193 | fprintf(stderr, strMsg);
|
---|
| 194 |
|
---|
| 195 | exit(1);
|
---|
| 196 | }
|
---|
| 197 |
|
---|
| 198 |
|
---|
| 199 | //------------------------------------------------------------------------------
|
---|
| 200 | // Function : RenderTexture::Initialize
|
---|
| 201 | // Description :
|
---|
| 202 | //------------------------------------------------------------------------------
|
---|
| 203 | /**
|
---|
| 204 | * @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);
|
---|
| 205 | * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
|
---|
| 206 | *
|
---|
| 207 | * This function actually does the creation of the p-buffer. It can only be called
|
---|
| 208 | * once a GL context has already been created. Note that if the texture is not
|
---|
| 209 | * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
|
---|
| 210 | * or aniso filtering will cause an error.
|
---|
| 211 | */
|
---|
| 212 | bool RenderTexture::Initialize(bool bShare /* = true */,
|
---|
| 213 | bool bDepth /* = false */,
|
---|
| 214 | bool bStencil /* = false */,
|
---|
| 215 | bool bMipmap /* = false */,
|
---|
| 216 | bool bAnisoFilter /* = false */,
|
---|
| 217 | unsigned int iRBits /* = 8 */,
|
---|
| 218 | unsigned int iGBits /* = 8 */,
|
---|
| 219 | unsigned int iBBits /* = 8 */,
|
---|
| 220 | unsigned int iABits /* = 8 */,
|
---|
| 221 | UpdateMode updateMode /* = RT_RENDER_TO_TEXTURE */)
|
---|
| 222 | {
|
---|
| 223 | #ifdef _WIN32
|
---|
| 224 | if (!WGLEW_ARB_pbuffer)
|
---|
| 225 | {
|
---|
| 226 | PrintExtensionError("WGL_ARB_pbuffer");
|
---|
| 227 | return false;
|
---|
| 228 | }
|
---|
| 229 | if (!WGLEW_ARB_pixel_format)
|
---|
| 230 | {
|
---|
| 231 | PrintExtensionError("WGL_ARB_pixel_format");
|
---|
| 232 | return false;
|
---|
| 233 | }
|
---|
| 234 | if (_bIsTexture && !WGLEW_ARB_render_texture)
|
---|
| 235 | {
|
---|
| 236 | PrintExtensionError("WGL_ARB_render_texture");
|
---|
| 237 | return false;
|
---|
| 238 | }
|
---|
| 239 | if (_bIsDepthTexture && !GLEW_ARB_depth_texture)
|
---|
| 240 | {
|
---|
| 241 | // [Redge]
|
---|
[2575] | 242 | #if defined(_DEBUG) || defined(DEBUG)
|
---|
[1940] | 243 | fprintf(stderr, "Warning: OpenGL extension GL_ARB_depth_texture not available.\n"
|
---|
| 244 | " Using glReadPixels() to emulate behavior.\n");
|
---|
| 245 | #endif
|
---|
| 246 | _bHasArbDepthTexture = false;
|
---|
| 247 | //PrintExtensionError("GL_ARB_depth_texture");
|
---|
| 248 | //return false;
|
---|
| 249 | // [/Redge]
|
---|
| 250 | }
|
---|
| 251 | SetLastError(0);
|
---|
[2575] | 252 | #else // _WIN32
|
---|
[1940] | 253 | if (!GLXEW_SGIX_pbuffer)
|
---|
| 254 | {
|
---|
| 255 | PrintExtensionError("GLX_SGIX_pbuffer");
|
---|
| 256 | return false;
|
---|
| 257 | }
|
---|
| 258 | if (!GLXEW_SGIX_fbconfig)
|
---|
| 259 | {
|
---|
| 260 | PrintExtensionError("GLX_SGIX_fbconfig");
|
---|
| 261 | return false;
|
---|
| 262 | }
|
---|
| 263 | if (_bIsDepthTexture)
|
---|
| 264 | {
|
---|
| 265 | PrintExtensionError("I don't know");
|
---|
| 266 | return false;
|
---|
| 267 | }
|
---|
| 268 | if (updateMode == RT_RENDER_TO_TEXTURE)
|
---|
| 269 | {
|
---|
| 270 | PrintExtensionError("Some GLX render texture extension");
|
---|
| 271 | }
|
---|
[2575] | 272 | #endif // _WIN32
|
---|
[1940] | 273 |
|
---|
| 274 | if (_bInitialized)
|
---|
| 275 | _Invalidate();
|
---|
| 276 |
|
---|
| 277 | _bFloat = (iRBits > 8 || iGBits > 8 || iBBits > 8 || iABits > 8);
|
---|
| 278 |
|
---|
| 279 | bool bNVIDIA = true;
|
---|
| 280 | #ifdef _WIN32
|
---|
| 281 | if (_bFloat && !GLEW_NV_float_buffer)
|
---|
| 282 | {
|
---|
| 283 | bNVIDIA = false;
|
---|
| 284 | if (!WGLEW_ATI_pixel_format_float)
|
---|
| 285 | {
|
---|
| 286 | PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
|
---|
| 287 | return false;
|
---|
| 288 | }
|
---|
| 289 | }
|
---|
| 290 | if (_bFloat && _bIsTexture && !bNVIDIA && !GLEW_ATI_texture_float)
|
---|
| 291 | {
|
---|
| 292 | PrintExtensionError("NV_float_buffer or ATI_texture_float");
|
---|
| 293 | }
|
---|
[2575] | 294 | #else // _WIN32
|
---|
[1940] | 295 | if (_bFloat && _bIsTexture && !GLXEW_NV_float_buffer)
|
---|
| 296 | {
|
---|
| 297 | PrintExtensionError("GLX_NV_float_buffer");
|
---|
| 298 | return false;
|
---|
| 299 | }
|
---|
[2575] | 300 | #endif // _WIN32
|
---|
[1940] | 301 | if (!_bFloat && !GLEW_NV_texture_rectangle)
|
---|
| 302 | {
|
---|
| 303 | bNVIDIA = false;
|
---|
| 304 | }
|
---|
| 305 |
|
---|
| 306 | _bRectangle = _bRectangle || (_bFloat && bNVIDIA);
|
---|
| 307 |
|
---|
| 308 | if(_bIsDepthTexture)
|
---|
| 309 | _bHasDepth = true; // we need depth for a depth texture...
|
---|
| 310 | else
|
---|
| 311 | _bHasDepth = bDepth;
|
---|
| 312 |
|
---|
| 313 | _bHasStencil = bStencil;
|
---|
| 314 | _bMipmap = false; // until it is enabled.
|
---|
| 315 | _bAnisoFilter = false; // until it is enabled.
|
---|
| 316 | _eUpdateMode = updateMode;
|
---|
| 317 |
|
---|
| 318 | GLuint iWGLTextureTarget = 0;
|
---|
| 319 | GLuint iBindTarget = 0;
|
---|
| 320 | GLuint iTextureFormat = 0;
|
---|
| 321 | GLuint iDepthBindTarget = 0;
|
---|
| 322 | GLuint iDepthTextureFormat = 0;
|
---|
| 323 |
|
---|
| 324 | if (_bIsTexture)
|
---|
| 325 | glGenTextures(1, &_iTextureID);
|
---|
| 326 | if (_bIsDepthTexture)
|
---|
| 327 | glGenTextures(1, &_iDepthTextureID);
|
---|
| 328 |
|
---|
| 329 | // Determine the appropriate texture formats and filtering modes.
|
---|
| 330 | if (_bIsTexture)
|
---|
| 331 | {
|
---|
| 332 | if (_bFloat)
|
---|
| 333 | {
|
---|
| 334 | if (!bNVIDIA && _bRectangle)
|
---|
| 335 | {
|
---|
| 336 | fprintf(stderr,
|
---|
| 337 | "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
|
---|
| 338 | return false;
|
---|
| 339 | }
|
---|
| 340 |
|
---|
| 341 | if (bNVIDIA)
|
---|
| 342 | _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
|
---|
| 343 | else
|
---|
| 344 | _iTextureTarget = GL_TEXTURE_2D;
|
---|
| 345 |
|
---|
| 346 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 347 |
|
---|
| 348 | // We'll use clamp to edge as the default texture wrap mode for all tex types
|
---|
| 349 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
| 350 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
| 351 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
---|
| 352 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
---|
| 353 |
|
---|
| 354 | if (bMipmap)
|
---|
| 355 | {
|
---|
| 356 | fprintf(stderr,
|
---|
| 357 | "RenderTexture Error: float textures do not support mipmaps\n");
|
---|
| 358 | return false;
|
---|
| 359 | }
|
---|
| 360 |
|
---|
| 361 | if (RT_COPY_TO_TEXTURE == _eUpdateMode)
|
---|
| 362 | {
|
---|
| 363 | GLuint iInternalFormat;
|
---|
| 364 | GLuint iFormat;
|
---|
| 365 | if (iABits > 0)
|
---|
| 366 | {
|
---|
| 367 | if (bNVIDIA)
|
---|
| 368 | iInternalFormat = (iABits > 16) ? GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
|
---|
| 369 | else
|
---|
| 370 | iInternalFormat = (iABits > 16) ? GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
|
---|
| 371 | iFormat = GL_RGBA;
|
---|
| 372 | }
|
---|
| 373 | else if (iBBits > 0)
|
---|
| 374 | {
|
---|
| 375 | if (bNVIDIA)
|
---|
| 376 | iInternalFormat = (iBBits > 16) ? GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
|
---|
| 377 | else
|
---|
| 378 | iInternalFormat = (iBBits > 16) ? GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
|
---|
| 379 | iFormat = GL_RGB;
|
---|
| 380 | }
|
---|
| 381 | else if (iGBits > 0)
|
---|
| 382 | {
|
---|
| 383 | if (bNVIDIA)
|
---|
| 384 | iInternalFormat = (iGBits > 16) ? GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
|
---|
| 385 | else
|
---|
| 386 | iInternalFormat = (iGBits > 16) ? GL_LUMINANCE_ALPHA_FLOAT32_ATI :
|
---|
| 387 | GL_LUMINANCE_ALPHA_FLOAT16_ATI;
|
---|
| 388 | iFormat = GL_LUMINANCE_ALPHA;
|
---|
| 389 | }
|
---|
| 390 | else
|
---|
| 391 | {
|
---|
| 392 | if (bNVIDIA)
|
---|
| 393 | iInternalFormat = (iRBits > 16) ? GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
|
---|
| 394 | else
|
---|
| 395 | iInternalFormat = (iRBits > 16) ? GL_LUMINANCE_FLOAT32_ATI :
|
---|
| 396 | GL_LUMINANCE_FLOAT16_ATI;
|
---|
| 397 | iFormat = GL_LUMINANCE;
|
---|
| 398 | }
|
---|
| 399 | // Allocate the texture image (but pass it no data for now).
|
---|
| 400 | glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
|
---|
| 401 | 0, iFormat, GL_FLOAT, NULL);
|
---|
| 402 | }
|
---|
| 403 | else
|
---|
| 404 | {
|
---|
| 405 | #ifdef _WIN32
|
---|
| 406 | if (bNVIDIA)
|
---|
| 407 | iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
|
---|
| 408 | else
|
---|
| 409 | iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
|
---|
| 410 |
|
---|
| 411 | if (iABits > 0)
|
---|
| 412 | {
|
---|
| 413 | if (bNVIDIA)
|
---|
| 414 | {
|
---|
| 415 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV;
|
---|
| 416 | iTextureFormat = WGL_TEXTURE_FLOAT_RGBA_NV;
|
---|
| 417 | }
|
---|
| 418 | else
|
---|
| 419 | {
|
---|
| 420 | iBindTarget = WGL_BIND_TO_TEXTURE_RGBA_ARB;
|
---|
| 421 | iTextureFormat = WGL_TEXTURE_RGBA_ARB;
|
---|
| 422 | }
|
---|
| 423 | }
|
---|
| 424 | else if (iBBits > 0)
|
---|
| 425 | {
|
---|
| 426 | if (bNVIDIA)
|
---|
| 427 | {
|
---|
| 428 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV;
|
---|
| 429 | iTextureFormat = WGL_TEXTURE_FLOAT_RGB_NV;
|
---|
| 430 | }
|
---|
| 431 | else
|
---|
| 432 | {
|
---|
| 433 | iBindTarget = WGL_BIND_TO_TEXTURE_RGB_ARB;
|
---|
| 434 | iTextureFormat = WGL_TEXTURE_RGB_ARB;
|
---|
| 435 | }
|
---|
| 436 | }
|
---|
| 437 | else if (iGBits > 0)
|
---|
| 438 | {
|
---|
| 439 | if (bNVIDIA)
|
---|
| 440 | {
|
---|
| 441 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV;
|
---|
| 442 | iTextureFormat = WGL_TEXTURE_FLOAT_RG_NV;
|
---|
| 443 | }
|
---|
| 444 | else
|
---|
| 445 | {
|
---|
| 446 | iBindTarget = WGL_BIND_TO_TEXTURE_RGB_ARB;
|
---|
| 447 | iTextureFormat = WGL_TEXTURE_RGB_ARB;
|
---|
| 448 | }
|
---|
| 449 | }
|
---|
| 450 | else
|
---|
| 451 | {
|
---|
| 452 | if (bNVIDIA)
|
---|
| 453 | {
|
---|
| 454 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV;
|
---|
| 455 | iTextureFormat = WGL_TEXTURE_FLOAT_R_NV;
|
---|
| 456 | }
|
---|
| 457 | else
|
---|
| 458 | {
|
---|
| 459 | iBindTarget = WGL_BIND_TO_TEXTURE_RGB_ARB;
|
---|
| 460 | iTextureFormat = WGL_TEXTURE_RGB_ARB;
|
---|
| 461 | }
|
---|
| 462 | }
|
---|
[2575] | 463 | #else // _WIN32
|
---|
| 464 | #if defined(DEBUG) || defined(_DEBUG)
|
---|
[1940] | 465 | printf("RenderTexture Error: Render-to-Texture not supported in Linux\n");
|
---|
[2575] | 466 | #endif
|
---|
| 467 | #endif // _WIN32
|
---|
[1940] | 468 | }
|
---|
| 469 | }
|
---|
| 470 | else
|
---|
| 471 | {
|
---|
| 472 | if (!_bRectangle)
|
---|
| 473 | {
|
---|
| 474 | _iTextureTarget = GL_TEXTURE_2D;
|
---|
| 475 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 476 |
|
---|
| 477 | // We'll use clamp to edge as the default texture wrap mode for all tex types
|
---|
| 478 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
| 479 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
| 480 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
---|
| 481 |
|
---|
| 482 | if (bMipmap)
|
---|
| 483 | {
|
---|
| 484 | _bMipmap = true;
|
---|
| 485 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
---|
| 486 |
|
---|
| 487 | // Generate mipmap automatically if supported
|
---|
| 488 | if (GLEW_SGIS_generate_mipmap)
|
---|
| 489 | {
|
---|
| 490 | glTexParameteri( _iTextureTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
---|
| 491 | }
|
---|
| 492 | else
|
---|
| 493 | {
|
---|
| 494 | PrintExtensionError("GL_SGIS_generate_mipmap");
|
---|
| 495 | }
|
---|
| 496 | }
|
---|
| 497 | else
|
---|
| 498 | {
|
---|
| 499 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
---|
| 500 | }
|
---|
| 501 |
|
---|
| 502 | // Set anisotropic filter to the max ratio
|
---|
| 503 | if (bAnisoFilter)
|
---|
| 504 | {
|
---|
| 505 | if (GLEW_EXT_texture_filter_anisotropic)
|
---|
| 506 | {
|
---|
| 507 | _bAnisoFilter = true;
|
---|
| 508 | float rMaxAniso;
|
---|
| 509 | glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &rMaxAniso);
|
---|
| 510 | glTexParameterf( _iTextureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, rMaxAniso);
|
---|
| 511 | }
|
---|
| 512 | }
|
---|
| 513 |
|
---|
| 514 | if (RT_COPY_TO_TEXTURE == _eUpdateMode)
|
---|
| 515 | {
|
---|
| 516 | GLuint iInternalFormat;
|
---|
| 517 | GLuint iFormat;
|
---|
| 518 | if (iABits > 0)
|
---|
| 519 | {
|
---|
| 520 | iInternalFormat = GL_RGBA8;
|
---|
| 521 | iFormat = GL_RGBA;
|
---|
| 522 | }
|
---|
| 523 | else
|
---|
| 524 | {
|
---|
| 525 | iInternalFormat = GL_RGB8;
|
---|
| 526 | iFormat = GL_RGB;
|
---|
| 527 | }
|
---|
| 528 | // Allocate the texture image (but pass it no data for now).
|
---|
| 529 | glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
|
---|
| 530 | 0, iFormat, GL_FLOAT, NULL);
|
---|
| 531 | }
|
---|
| 532 | else
|
---|
| 533 | {
|
---|
| 534 | #ifdef _WIN32
|
---|
| 535 | iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
|
---|
| 536 | if (iABits > 0)
|
---|
| 537 | {
|
---|
| 538 | iBindTarget = WGL_BIND_TO_TEXTURE_RGBA_ARB;
|
---|
| 539 | iTextureFormat = WGL_TEXTURE_RGBA_ARB;
|
---|
| 540 | }
|
---|
| 541 | else
|
---|
| 542 | {
|
---|
| 543 | iBindTarget = WGL_BIND_TO_TEXTURE_RGB_ARB;
|
---|
| 544 | iTextureFormat = WGL_TEXTURE_RGB_ARB;
|
---|
| 545 | }
|
---|
| 546 | #endif
|
---|
| 547 | }
|
---|
| 548 | }
|
---|
| 549 | else
|
---|
| 550 | {
|
---|
| 551 | if (!bNVIDIA)
|
---|
| 552 | {
|
---|
| 553 | fprintf(stderr,
|
---|
| 554 | "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
|
---|
| 555 | return false;
|
---|
| 556 | }
|
---|
| 557 |
|
---|
| 558 | _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
|
---|
| 559 |
|
---|
| 560 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 561 |
|
---|
| 562 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
| 563 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
| 564 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
---|
| 565 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
---|
| 566 |
|
---|
| 567 | if (bMipmap)
|
---|
| 568 | {
|
---|
| 569 |
|
---|
| 570 | fprintf(stderr,
|
---|
| 571 | "RenderTexture Error: rectangle textures do not support mipmaps\n");
|
---|
| 572 | return false;
|
---|
| 573 | }
|
---|
| 574 |
|
---|
| 575 | if (RT_COPY_TO_TEXTURE == _eUpdateMode)
|
---|
| 576 | {
|
---|
| 577 | GLuint iInternalFormat;
|
---|
| 578 | GLuint iFormat;
|
---|
| 579 | if (iABits > 0)
|
---|
| 580 | {
|
---|
| 581 | iInternalFormat = GL_RGBA8;
|
---|
| 582 | iFormat = GL_RGBA;
|
---|
| 583 | }
|
---|
| 584 | else
|
---|
| 585 | {
|
---|
| 586 | iInternalFormat = GL_RGB8;
|
---|
| 587 | iFormat = GL_RGB;
|
---|
| 588 | }
|
---|
| 589 | // Allocate the texture image (but pass it no data for now).
|
---|
| 590 | glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
|
---|
| 591 | 0, iFormat, GL_FLOAT, NULL);
|
---|
| 592 | }
|
---|
| 593 | else
|
---|
| 594 | {
|
---|
| 595 | #ifdef _WIN32
|
---|
| 596 | iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
|
---|
| 597 | if (iABits > 0)
|
---|
| 598 | {
|
---|
| 599 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV;
|
---|
| 600 | iTextureFormat = WGL_TEXTURE_RGBA_ARB;
|
---|
| 601 | }
|
---|
| 602 | else
|
---|
| 603 | {
|
---|
| 604 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV;
|
---|
| 605 | iTextureFormat= WGL_TEXTURE_RGB_ARB;
|
---|
| 606 | }
|
---|
| 607 | #endif
|
---|
| 608 | }
|
---|
| 609 | }
|
---|
| 610 | }
|
---|
| 611 | }
|
---|
| 612 |
|
---|
| 613 | if (_bIsDepthTexture)
|
---|
| 614 | {
|
---|
| 615 | if (!bNVIDIA && _bRectangle)
|
---|
| 616 | {
|
---|
| 617 | fprintf(stderr,
|
---|
| 618 | "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
|
---|
| 619 | return false;
|
---|
| 620 | }
|
---|
| 621 |
|
---|
| 622 | if (!_iTextureTarget)
|
---|
| 623 | _iTextureTarget = _bRectangle ? GL_TEXTURE_RECTANGLE_NV : GL_TEXTURE_2D;
|
---|
| 624 |
|
---|
| 625 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 626 |
|
---|
| 627 | // We'll use clamp to edge as the default texture wrap mode for all tex types
|
---|
| 628 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
| 629 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
| 630 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
---|
| 631 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
---|
| 632 |
|
---|
| 633 | // user will need to set up hardware shadow mapping himself (using ARB_shadow)
|
---|
| 634 |
|
---|
| 635 | if (RT_COPY_TO_TEXTURE == _eUpdateMode)
|
---|
| 636 | {
|
---|
| 637 | // [Redge]
|
---|
| 638 | if (_bHasArbDepthTexture)
|
---|
| 639 | {
|
---|
| 640 | // Allocate the texture image (but pass it no data for now).
|
---|
| 641 | glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT, _iWidth, _iHeight,
|
---|
| 642 | 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
---|
| 643 | }
|
---|
| 644 | else
|
---|
| 645 | {
|
---|
| 646 | // allocate memory for depth texture
|
---|
| 647 | // Since this is slow, we warn the user in debug mode. (above)
|
---|
| 648 | _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
|
---|
| 649 | glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16, _iWidth, _iHeight,
|
---|
| 650 | 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
|
---|
| 651 | }
|
---|
| 652 | // [/Redge]
|
---|
| 653 | }
|
---|
| 654 | else // RENDER_TO_TEXTURE
|
---|
| 655 | {
|
---|
| 656 | #ifdef _WIN32
|
---|
| 657 | if(_bRectangle)
|
---|
| 658 | {
|
---|
| 659 | if (!iWGLTextureTarget) iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
|
---|
| 660 | iDepthBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV;
|
---|
| 661 | iDepthTextureFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV;
|
---|
| 662 | }
|
---|
| 663 | else
|
---|
| 664 | {
|
---|
| 665 | if (!iWGLTextureTarget) iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
|
---|
| 666 | iDepthBindTarget = WGL_BIND_TO_TEXTURE_DEPTH_NV;
|
---|
| 667 | iDepthTextureFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV;
|
---|
| 668 | }
|
---|
| 669 | #endif
|
---|
| 670 | }
|
---|
| 671 | }
|
---|
| 672 |
|
---|
| 673 | #if _WIN32
|
---|
| 674 | // Get the current context.
|
---|
| 675 | HDC hdc = wglGetCurrentDC();
|
---|
| 676 | if (NULL == hdc)
|
---|
| 677 | _wglGetLastError();
|
---|
| 678 | HGLRC hglrc = wglGetCurrentContext();
|
---|
| 679 | if (NULL == hglrc)
|
---|
| 680 | _wglGetLastError();
|
---|
| 681 |
|
---|
| 682 | int iFormat = 0;
|
---|
| 683 | unsigned int iNumFormats;
|
---|
| 684 | int attribChooseList[50];
|
---|
| 685 | int attribCreateList[50];
|
---|
| 686 | int attribChoose = 0;
|
---|
| 687 | int attribCreate = 0;
|
---|
| 688 |
|
---|
| 689 | // Setup the attrib list for wglChoosePixelFormat()
|
---|
| 690 |
|
---|
| 691 | attribChooseList[attribChoose++] = WGL_RED_BITS_ARB;
|
---|
| 692 | attribChooseList[attribChoose++] = iRBits;
|
---|
| 693 | attribChooseList[attribChoose++] = WGL_GREEN_BITS_ARB;
|
---|
| 694 | attribChooseList[attribChoose++] = iGBits;
|
---|
| 695 | attribChooseList[attribChoose++] = WGL_BLUE_BITS_ARB;
|
---|
| 696 | attribChooseList[attribChoose++] = iBBits;
|
---|
| 697 | attribChooseList[attribChoose++] = WGL_ALPHA_BITS_ARB;
|
---|
| 698 | attribChooseList[attribChoose++] = iABits;
|
---|
| 699 | if (_bFloat)
|
---|
| 700 | {
|
---|
| 701 | if (bNVIDIA)
|
---|
| 702 | {
|
---|
| 703 | attribChooseList[attribChoose++] = WGL_FLOAT_COMPONENTS_NV;
|
---|
| 704 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 705 | }
|
---|
| 706 | else
|
---|
| 707 | {
|
---|
| 708 | attribChooseList[attribChoose++] = WGL_PIXEL_TYPE_ARB;
|
---|
| 709 | attribChooseList[attribChoose++] = WGL_TYPE_RGBA_FLOAT_ATI;
|
---|
| 710 | }
|
---|
| 711 | }
|
---|
| 712 |
|
---|
| 713 | attribChooseList[attribChoose++] = WGL_STENCIL_BITS_ARB;
|
---|
| 714 | attribChooseList[attribChoose++] = (bStencil) ? 8 : 0;
|
---|
| 715 | attribChooseList[attribChoose++] = WGL_DEPTH_BITS_ARB;
|
---|
| 716 | attribChooseList[attribChoose++] = (bDepth) ? 24 : 0;
|
---|
| 717 | attribChooseList[attribChoose++] = WGL_DRAW_TO_PBUFFER_ARB;
|
---|
| 718 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 719 |
|
---|
| 720 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 721 | {
|
---|
| 722 | attribChooseList[attribChoose++] = iBindTarget;
|
---|
| 723 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 724 | }
|
---|
| 725 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 726 | {
|
---|
| 727 | attribChooseList[attribChoose++] = iDepthBindTarget;
|
---|
| 728 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 729 | }
|
---|
| 730 |
|
---|
| 731 | attribChooseList[attribChoose++] = 0;
|
---|
| 732 |
|
---|
| 733 | // Setup the attrib list for wglCreatePbuffer()
|
---|
| 734 | if ((_bIsTexture || _bIsDepthTexture) && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 735 | {
|
---|
| 736 | attribCreateList[attribCreate++] = WGL_TEXTURE_TARGET_ARB;
|
---|
| 737 | attribCreateList[attribCreate++] = iWGLTextureTarget;
|
---|
| 738 | }
|
---|
| 739 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 740 | {
|
---|
| 741 | attribCreateList[attribCreate++] = WGL_TEXTURE_FORMAT_ARB;
|
---|
| 742 | attribCreateList[attribCreate++] = iTextureFormat;
|
---|
| 743 | /*attribCreateList[attribCreate++] = WGL_TEXTURE_TARGET_ARB;
|
---|
| 744 | attribCreateList[attribCreate++] = iWGLTextureTarget;*/
|
---|
| 745 | attribCreateList[attribCreate++] = WGL_MIPMAP_TEXTURE_ARB;
|
---|
| 746 | attribCreateList[attribCreate++] = (bMipmap) ? GL_TRUE : GL_FALSE;
|
---|
| 747 | }
|
---|
| 748 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 749 | {
|
---|
| 750 | attribCreateList[attribCreate++] = WGL_DEPTH_TEXTURE_FORMAT_NV;
|
---|
| 751 | attribCreateList[attribCreate++] = iDepthTextureFormat;
|
---|
| 752 | }
|
---|
| 753 | attribCreateList[attribCreate++] = WGL_PBUFFER_LARGEST_ARB;
|
---|
| 754 | attribCreateList[attribCreate++] = GL_FALSE;
|
---|
| 755 | attribCreateList[attribCreate++] = 0;
|
---|
| 756 |
|
---|
| 757 | if (!wglChoosePixelFormatARB( hdc, attribChooseList, NULL, 1, &iFormat, &iNumFormats))
|
---|
| 758 | {
|
---|
| 759 | fprintf(stderr,
|
---|
| 760 | "RenderTexture::Initialize() creation error: wglChoosePixelFormatARB() failed.\n");
|
---|
| 761 | _wglGetLastError();
|
---|
| 762 | return false;
|
---|
| 763 | }
|
---|
| 764 | if ( iNumFormats <= 0 )
|
---|
| 765 | {
|
---|
| 766 | fprintf(stderr,
|
---|
| 767 | "RenderTexture::Initialize() creation error: Couldn't find a suitable pixel format.\n");
|
---|
| 768 | _wglGetLastError();
|
---|
| 769 | return false;
|
---|
| 770 | }
|
---|
| 771 |
|
---|
| 772 | // Create the p-buffer.
|
---|
| 773 | _hPBuffer = wglCreatePbufferARB( hdc, iFormat, _iWidth, _iHeight, attribCreateList );
|
---|
| 774 | if (!_hPBuffer)
|
---|
| 775 | {
|
---|
| 776 | fprintf(stderr, "RenderTexture::Initialize() pbuffer creation error: wglCreatePbufferARB() failed\n");
|
---|
| 777 | _wglGetLastError();
|
---|
| 778 | return false;
|
---|
| 779 | }
|
---|
| 780 |
|
---|
| 781 | // Get the device context.
|
---|
| 782 | _hDC = wglGetPbufferDCARB( _hPBuffer);
|
---|
| 783 | if ( !_hDC )
|
---|
| 784 | {
|
---|
| 785 | fprintf(stderr,
|
---|
| 786 | "RenderTexture::Initialize() creation error: wglGetGetPbufferDCARB() failed\n");
|
---|
| 787 | _wglGetLastError();
|
---|
| 788 | return false;
|
---|
| 789 | }
|
---|
| 790 |
|
---|
| 791 | // Create a gl context for the p-buffer.
|
---|
| 792 |
|
---|
| 793 |
|
---|
| 794 | _hGLContext = wglCreateContext( _hDC );
|
---|
| 795 | if ( !_hGLContext )
|
---|
| 796 | {
|
---|
| 797 | fprintf(stderr, "RenderTexture::Initialize() creation error: wglCreateContext() failed\n");
|
---|
| 798 | _wglGetLastError();
|
---|
| 799 | return false;
|
---|
| 800 | }
|
---|
| 801 |
|
---|
| 802 | // Share lists, texture objects, and program objects.
|
---|
| 803 | if( bShare )
|
---|
| 804 | {
|
---|
| 805 | if( !wglShareLists(hglrc, _hGLContext) )
|
---|
| 806 | {
|
---|
| 807 | fprintf(stderr, "RenderTexture::Initialize() creation error: wglShareLists() failed\n" );
|
---|
| 808 | _wglGetLastError();
|
---|
| 809 | return false;
|
---|
| 810 | }
|
---|
| 811 | }
|
---|
| 812 |
|
---|
| 813 | // bind the pbuffer to the render texture object
|
---|
| 814 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 815 | {
|
---|
| 816 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 817 | if (wglBindTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB) == FALSE)
|
---|
| 818 | {
|
---|
| 819 | _wglGetLastError();
|
---|
| 820 | return false;
|
---|
| 821 | }
|
---|
| 822 | }
|
---|
| 823 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 824 | {
|
---|
| 825 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 826 | if (wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV) == FALSE)
|
---|
| 827 | {
|
---|
| 828 | _wglGetLastError();
|
---|
| 829 | return false;
|
---|
| 830 | }
|
---|
| 831 | }
|
---|
| 832 |
|
---|
| 833 | // Determine the actual width and height we were able to create.
|
---|
| 834 | wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
|
---|
| 835 | wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
|
---|
| 836 |
|
---|
| 837 | _bInitialized = true;
|
---|
| 838 |
|
---|
| 839 | // get the actual number of bits allocated:
|
---|
| 840 | int attrib = WGL_RED_BITS_ARB;
|
---|
| 841 | int value;
|
---|
| 842 | _iBits[0] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iRBits;
|
---|
| 843 | attrib = WGL_GREEN_BITS_ARB;
|
---|
| 844 | _iBits[1] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iGBits;
|
---|
| 845 | attrib = WGL_BLUE_BITS_ARB;
|
---|
| 846 | _iBits[2] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iBBits;
|
---|
| 847 | attrib = WGL_ALPHA_BITS_ARB;
|
---|
| 848 | _iBits[3] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iABits;
|
---|
| 849 | attrib = WGL_DEPTH_BITS_ARB;
|
---|
| 850 | _iBits[4] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : 0;
|
---|
| 851 | attrib = WGL_STENCIL_BITS_ARB;
|
---|
| 852 | _iBits[5] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : 0;
|
---|
| 853 |
|
---|
[2575] | 854 | #if defined(_DEBUG) || defined(DEBUG)
|
---|
[1940] | 855 | fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
|
---|
| 856 | _iWidth, _iHeight, _iBits[0], _iBits[1], _iBits[2], _iBits[3]);
|
---|
| 857 | if (_iBits[4]) fprintf(stderr, " depth=%d", _iBits[4]);
|
---|
| 858 | if (_iBits[5]) fprintf(stderr, " stencil=%d", _iBits[5]);
|
---|
| 859 | fprintf(stderr, "\n");
|
---|
| 860 | #endif
|
---|
[2575] | 861 | #else // _WIN32
|
---|
[1940] | 862 | _pDpy = glXGetCurrentDisplay();
|
---|
| 863 | GLXContext context = glXGetCurrentContext();
|
---|
| 864 | int screen = DefaultScreen(_pDpy);
|
---|
| 865 | XVisualInfo *visInfo;
|
---|
| 866 |
|
---|
| 867 | int iFormat = 0;
|
---|
| 868 | int iNumFormats;
|
---|
| 869 | int fbAttribs[50];
|
---|
| 870 | int attrib = 0;
|
---|
| 871 |
|
---|
| 872 | fbAttribs[attrib++] = GLX_RENDER_TYPE_SGIX;
|
---|
| 873 | fbAttribs[attrib++] = GLX_RGBA_BIT_SGIX;
|
---|
| 874 | fbAttribs[attrib++] = GLX_DRAWABLE_TYPE_SGIX;
|
---|
| 875 | fbAttribs[attrib++] = GLX_PBUFFER_BIT_SGIX;
|
---|
| 876 | fbAttribs[attrib++] = GLX_STENCIL_SIZE;
|
---|
| 877 | fbAttribs[attrib++] = (bStencil) ? 8 : 0;
|
---|
| 878 | fbAttribs[attrib++] = GLX_DEPTH_SIZE;
|
---|
| 879 | fbAttribs[attrib++] = (bDepth) ? 24 : 0;
|
---|
| 880 | if (_bFloat)
|
---|
| 881 | {
|
---|
| 882 | fbAttribs[attrib++] = GLX_RED_SIZE;
|
---|
| 883 | fbAttribs[attrib++] = iRBits;
|
---|
| 884 | fbAttribs[attrib++] = GLX_GREEN_SIZE;
|
---|
| 885 | fbAttribs[attrib++] = iGBits;
|
---|
| 886 | fbAttribs[attrib++] = GLX_BLUE_SIZE;
|
---|
| 887 | fbAttribs[attrib++] = iBBits;
|
---|
| 888 | fbAttribs[attrib++] = GLX_ALPHA_SIZE;
|
---|
| 889 | fbAttribs[attrib++] = iABits;
|
---|
| 890 | fbAttribs[attrib++] = GLX_FLOAT_COMPONENTS_NV;
|
---|
| 891 | fbAttribs[attrib++] = 1;
|
---|
| 892 | }
|
---|
| 893 | fbAttribs[attrib++] = None;
|
---|
| 894 |
|
---|
| 895 | GLXFBConfigSGIX *fbConfigs;
|
---|
| 896 | int nConfigs;
|
---|
| 897 |
|
---|
| 898 | fbConfigs = glXChooseFBConfigSGIX(_pDpy, screen, fbAttribs, &nConfigs);
|
---|
| 899 |
|
---|
| 900 | if (nConfigs == 0 || !fbConfigs) {
|
---|
| 901 | fprintf(stderr,
|
---|
| 902 | "RenderTexture::Initialize() creation error: Couldn't find a suitable pixel format\n");
|
---|
| 903 | return false;
|
---|
| 904 | }
|
---|
| 905 |
|
---|
| 906 | // Pick the first returned format that will return a pbuffer
|
---|
| 907 | for (int i=0;i<nConfigs;i++)
|
---|
| 908 | {
|
---|
| 909 | _hPBuffer = glXCreateGLXPbufferSGIX(_pDpy, fbConfigs[i], _iWidth, _iHeight, NULL);
|
---|
| 910 | if (_hPBuffer) {
|
---|
| 911 | _hGLContext = glXCreateContextWithConfigSGIX(_pDpy, fbConfigs[i], GLX_RGBA_TYPE, bShare?context:NULL, True);
|
---|
| 912 | break;
|
---|
| 913 | }
|
---|
| 914 | }
|
---|
| 915 |
|
---|
| 916 | if (!_hPBuffer)
|
---|
| 917 | {
|
---|
| 918 | fprintf(stderr, "RenderTexture::Initialize() pbuffer creation error: glXCreateGLXPbufferSGIX() failed\n");
|
---|
| 919 | return false;
|
---|
| 920 | }
|
---|
| 921 |
|
---|
| 922 | if(!_hGLContext)
|
---|
| 923 | {
|
---|
| 924 | // Try indirect
|
---|
| 925 | _hGLContext = glXCreateContext(_pDpy, visInfo, bShare?context:NULL, False);
|
---|
| 926 | if ( !_hGLContext )
|
---|
| 927 | {
|
---|
| 928 | fprintf(stderr, "RenderTexture::Initialize() creation error: glXCreateContext() failed\n");
|
---|
| 929 | return false;
|
---|
| 930 | }
|
---|
| 931 | }
|
---|
| 932 |
|
---|
| 933 | glXQueryGLXPbufferSGIX(_pDpy, _hPBuffer, GLX_WIDTH_SGIX, (GLuint*)&_iWidth);
|
---|
| 934 | glXQueryGLXPbufferSGIX(_pDpy, _hPBuffer, GLX_HEIGHT_SGIX, (GLuint*)&_iHeight);
|
---|
| 935 |
|
---|
| 936 | _bInitialized = true;
|
---|
| 937 |
|
---|
| 938 | // XXX Query the color format
|
---|
| 939 |
|
---|
[2575] | 940 | #endif // _WIN32
|
---|
[1940] | 941 |
|
---|
| 942 | return true;
|
---|
| 943 | }
|
---|
| 944 |
|
---|
| 945 | //------------------------------------------------------------------------------
|
---|
| 946 | // Function : RenderTexture::_Invalidate
|
---|
| 947 | // Description :
|
---|
| 948 | //------------------------------------------------------------------------------
|
---|
| 949 | /**
|
---|
| 950 | * @fn RenderTexture::_Invalidate()
|
---|
| 951 | * @brief Returns the pbuffer memory to the graphics device.
|
---|
| 952 | *
|
---|
| 953 | */
|
---|
| 954 | bool RenderTexture::_Invalidate()
|
---|
| 955 | {
|
---|
| 956 | _bFloat = false;
|
---|
| 957 | _bRectangle = false;
|
---|
| 958 | _bInitialized = false;
|
---|
| 959 | _bHasDepth = false;
|
---|
| 960 | _bHasStencil = false;
|
---|
| 961 | _bMipmap = false;
|
---|
| 962 | _bAnisoFilter = false;
|
---|
| 963 | _iBits[0] = _iBits[1] = _iBits[2] = _iBits[3] = 0;
|
---|
| 964 |
|
---|
| 965 | if (_bIsTexture)
|
---|
| 966 | glDeleteTextures(1, &_iTextureID);
|
---|
| 967 | if (_bIsDepthTexture) {
|
---|
| 968 | // [Redge]
|
---|
| 969 | if (!_bHasArbDepthTexture) delete[] _pPoorDepthTexture;
|
---|
| 970 | // [/Redge]
|
---|
| 971 | glDeleteTextures(1, &_iDepthTextureID);
|
---|
| 972 | }
|
---|
| 973 |
|
---|
| 974 | #if _WIN32
|
---|
| 975 | if ( _hPBuffer )
|
---|
| 976 | {
|
---|
| 977 | // Check if we are currently rendering in the pbuffer
|
---|
| 978 | if (wglGetCurrentContext() == _hGLContext)
|
---|
| 979 | wglMakeCurrent(0,0);
|
---|
| 980 | wglDeleteContext( _hGLContext);
|
---|
| 981 | wglReleasePbufferDCARB( _hPBuffer, _hDC);
|
---|
| 982 | wglDestroyPbufferARB( _hPBuffer );
|
---|
| 983 | _hPBuffer = 0;
|
---|
| 984 | return true;
|
---|
| 985 | }
|
---|
[2575] | 986 | #else // _WIN32
|
---|
[1940] | 987 | if ( _hPBuffer )
|
---|
| 988 | {
|
---|
| 989 | if(glXGetCurrentContext() == _hGLContext)
|
---|
| 990 | // XXX I don't know if this is right at all
|
---|
| 991 | glXMakeCurrent(_pDpy, _hPBuffer, 0);
|
---|
| 992 | glXDestroyGLXPbufferSGIX(_pDpy, _hPBuffer);
|
---|
| 993 | _hPBuffer = 0;
|
---|
| 994 | return true;
|
---|
| 995 | }
|
---|
[2575] | 996 | #endif // _WIN32
|
---|
[1940] | 997 | return false;
|
---|
| 998 | }
|
---|
| 999 |
|
---|
| 1000 |
|
---|
| 1001 | //------------------------------------------------------------------------------
|
---|
| 1002 | // Function : RenderTexture::Reset
|
---|
| 1003 | // Description :
|
---|
| 1004 | //------------------------------------------------------------------------------
|
---|
| 1005 | /**
|
---|
| 1006 | * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
|
---|
| 1007 | * @brief Resets the resolution of the offscreen buffer.
|
---|
| 1008 | *
|
---|
| 1009 | * Causes the buffer to delete itself. User must call Initialize() again
|
---|
| 1010 | * before use.
|
---|
| 1011 | */
|
---|
| 1012 | bool RenderTexture::Reset(int iWidth, int iHeight, bool bIsTexture /* = true */,
|
---|
| 1013 | bool bIsDepthTexture /* = false */)
|
---|
| 1014 | {
|
---|
| 1015 | if (!_Invalidate())
|
---|
| 1016 | {
|
---|
| 1017 | fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
|
---|
| 1018 | return false;
|
---|
| 1019 | }
|
---|
| 1020 | _iWidth = iWidth;
|
---|
| 1021 | _iHeight = iHeight;
|
---|
| 1022 | _bIsTexture = bIsTexture;
|
---|
| 1023 | _bIsDepthTexture = bIsDepthTexture;
|
---|
| 1024 |
|
---|
| 1025 | return true;
|
---|
| 1026 | }
|
---|
| 1027 |
|
---|
| 1028 |
|
---|
| 1029 | //------------------------------------------------------------------------------
|
---|
| 1030 | // Function : RenderTexture::BeginCapture
|
---|
| 1031 | // Description :
|
---|
| 1032 | //------------------------------------------------------------------------------
|
---|
| 1033 | /**
|
---|
| 1034 | * @fn RenderTexture::BeginCapture()
|
---|
| 1035 | * @brief Activates rendering to the RenderTexture.
|
---|
| 1036 | */
|
---|
| 1037 | bool RenderTexture::BeginCapture()
|
---|
| 1038 | {
|
---|
| 1039 | if (!_bInitialized)
|
---|
| 1040 | {
|
---|
| 1041 | fprintf(stderr, "RenderTexture::BeginCapture(): Texture is not initialized!\n");
|
---|
| 1042 | exit(1);
|
---|
| 1043 | return false;
|
---|
| 1044 | }
|
---|
| 1045 | #ifdef _WIN32
|
---|
| 1046 | // cache the current context so we can reset it when EndCapture() is called.
|
---|
| 1047 | _hPreviousDC = wglGetCurrentDC();
|
---|
| 1048 | if (NULL == _hPreviousDC)
|
---|
| 1049 | _wglGetLastError();
|
---|
| 1050 | _hPreviousContext = wglGetCurrentContext();
|
---|
| 1051 | if (NULL == _hPreviousContext)
|
---|
| 1052 | _wglGetLastError();
|
---|
| 1053 |
|
---|
| 1054 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1055 | {
|
---|
| 1056 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1057 |
|
---|
| 1058 | // release the pbuffer from the render texture object
|
---|
| 1059 | if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB))
|
---|
| 1060 | {
|
---|
| 1061 | _wglGetLastError();
|
---|
| 1062 | return false;
|
---|
| 1063 | }
|
---|
| 1064 | }
|
---|
| 1065 |
|
---|
| 1066 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1067 | {
|
---|
| 1068 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1069 |
|
---|
| 1070 | // release the pbuffer from the render texture object
|
---|
| 1071 | if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
|
---|
| 1072 | {
|
---|
| 1073 | _wglGetLastError();
|
---|
| 1074 | return false;
|
---|
| 1075 | }
|
---|
| 1076 | }
|
---|
| 1077 |
|
---|
| 1078 | // make the pbuffer's rendering context current.
|
---|
| 1079 | if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
|
---|
| 1080 | {
|
---|
| 1081 | _wglGetLastError();
|
---|
| 1082 | return false;
|
---|
| 1083 | }
|
---|
[2575] | 1084 | #else // _WIN32
|
---|
[1940] | 1085 | _hPreviousContext = glXGetCurrentContext();
|
---|
| 1086 | _hPreviousDrawable = glXGetCurrentDrawable();
|
---|
| 1087 |
|
---|
| 1088 | if (False == glXMakeCurrent(_pDpy, _hPBuffer, _hGLContext)) {
|
---|
| 1089 | return false;
|
---|
| 1090 | }
|
---|
[2575] | 1091 | #endif // _WIN32
|
---|
[1940] | 1092 |
|
---|
| 1093 | return true;
|
---|
| 1094 | }
|
---|
| 1095 |
|
---|
| 1096 |
|
---|
| 1097 | //------------------------------------------------------------------------------
|
---|
| 1098 | // Function : RenderTexture::EndCapture
|
---|
| 1099 | // Description :
|
---|
| 1100 | //------------------------------------------------------------------------------
|
---|
| 1101 | /**
|
---|
| 1102 | * @fn RenderTexture::EndCapture()
|
---|
| 1103 | * @brief Ends rendering to the RenderTexture.
|
---|
| 1104 | */
|
---|
| 1105 | bool RenderTexture::EndCapture()
|
---|
| 1106 | {
|
---|
| 1107 | bool bContextReset = false;
|
---|
| 1108 |
|
---|
| 1109 | if (!_bInitialized)
|
---|
| 1110 | {
|
---|
| 1111 | fprintf(stderr, "RenderTexture::EndCapture(): Texture is not initialized!\n");
|
---|
| 1112 | return false;
|
---|
| 1113 | }
|
---|
| 1114 | #ifdef _WIN32
|
---|
| 1115 | if (_bIsTexture)
|
---|
| 1116 | {
|
---|
| 1117 | if (RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1118 | {
|
---|
| 1119 | // make the previous rendering context current
|
---|
| 1120 | if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
|
---|
| 1121 | {
|
---|
| 1122 | _wglGetLastError();
|
---|
| 1123 | return false;
|
---|
| 1124 | }
|
---|
| 1125 | bContextReset = true;
|
---|
| 1126 |
|
---|
| 1127 | // [Redge] moved binding completely to Bind()
|
---|
| 1128 | // [Mark] Can't do that, because it makes things difficult for Cg users.
|
---|
| 1129 | // bind the pbuffer to the render texture object
|
---|
| 1130 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1131 | if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB))
|
---|
| 1132 | {
|
---|
| 1133 | _wglGetLastError();
|
---|
| 1134 | return false;
|
---|
| 1135 | }
|
---|
| 1136 | }
|
---|
| 1137 | else
|
---|
| 1138 | {
|
---|
| 1139 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1140 | glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
|
---|
| 1141 | }
|
---|
| 1142 | }
|
---|
| 1143 | if (_bIsDepthTexture)
|
---|
| 1144 | {
|
---|
| 1145 | if (RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1146 | {
|
---|
| 1147 | // make the previous rendering context current
|
---|
| 1148 | if(!bContextReset)
|
---|
| 1149 | {
|
---|
| 1150 | if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
|
---|
| 1151 | {
|
---|
| 1152 | _wglGetLastError();
|
---|
| 1153 | return false;
|
---|
| 1154 | }
|
---|
| 1155 | bContextReset = true;
|
---|
| 1156 | }
|
---|
| 1157 |
|
---|
| 1158 | // [Redge] moved binding completely to Bind()
|
---|
| 1159 | // [Mark] Can't do that, because it makes things difficult for Cg users.
|
---|
| 1160 | // bind the pbuffer to the render texture object
|
---|
| 1161 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1162 | if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
|
---|
| 1163 | {
|
---|
| 1164 | _wglGetLastError();
|
---|
| 1165 | return false;
|
---|
| 1166 | }
|
---|
| 1167 | }
|
---|
| 1168 | else
|
---|
| 1169 | {
|
---|
| 1170 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1171 | // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
|
---|
| 1172 | // [Redge]
|
---|
| 1173 | if (_bHasArbDepthTexture)
|
---|
| 1174 | {
|
---|
| 1175 | glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
|
---|
| 1176 | }
|
---|
| 1177 | else
|
---|
| 1178 | {
|
---|
| 1179 | // no 'real' depth texture available, so behavior has to be emulated
|
---|
| 1180 | // using glReadPixels (beware, this is (naturally) slow ...)
|
---|
| 1181 | glReadPixels(0, 0, _iWidth, _iHeight,
|
---|
| 1182 | GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
|
---|
| 1183 | glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
|
---|
| 1184 | _iWidth, _iHeight,
|
---|
| 1185 | 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
|
---|
| 1186 | }
|
---|
| 1187 | // [/Redge]
|
---|
| 1188 | }
|
---|
| 1189 | }
|
---|
| 1190 |
|
---|
| 1191 | if(!bContextReset)
|
---|
| 1192 | {
|
---|
| 1193 | // make the previous rendering context current
|
---|
| 1194 | if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
|
---|
| 1195 | {
|
---|
| 1196 | _wglGetLastError();
|
---|
| 1197 | return false;
|
---|
| 1198 | }
|
---|
| 1199 | }
|
---|
[2575] | 1200 | #else // _WIN32
|
---|
[1940] | 1201 | assert(_bIsTexture);
|
---|
| 1202 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1203 | glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
|
---|
| 1204 |
|
---|
| 1205 | if(!bContextReset)
|
---|
| 1206 | {
|
---|
| 1207 | if (False == glXMakeCurrent(_pDpy, _hPreviousDrawable, _hPreviousContext))
|
---|
| 1208 | {
|
---|
| 1209 | return false;
|
---|
| 1210 | }
|
---|
| 1211 | }
|
---|
[2575] | 1212 | #endif // _WIN32
|
---|
[1940] | 1213 | return true;
|
---|
| 1214 | }
|
---|
| 1215 |
|
---|
| 1216 |
|
---|
| 1217 |
|
---|
| 1218 | //------------------------------------------------------------------------------
|
---|
| 1219 | // Function : RenderTexture::Bind
|
---|
| 1220 | // Description :
|
---|
| 1221 | //------------------------------------------------------------------------------
|
---|
| 1222 | /**
|
---|
| 1223 | * @fn RenderTexture::Bind()
|
---|
| 1224 | * @brief Binds RGB texture.
|
---|
| 1225 | */
|
---|
| 1226 | void RenderTexture::Bind() const
|
---|
| 1227 | {
|
---|
| 1228 | if (_bInitialized) {
|
---|
| 1229 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1230 | }
|
---|
| 1231 | }
|
---|
| 1232 |
|
---|
| 1233 |
|
---|
| 1234 | //------------------------------------------------------------------------------
|
---|
| 1235 | // Function : RenderTexture::BindDepth
|
---|
| 1236 | // Description :
|
---|
| 1237 | //------------------------------------------------------------------------------
|
---|
| 1238 | /**
|
---|
| 1239 | * @fn RenderTexture::BindDepth()
|
---|
| 1240 | * @brief Binds depth texture.
|
---|
| 1241 | */
|
---|
| 1242 | void RenderTexture::BindDepth() const
|
---|
| 1243 | {
|
---|
| 1244 | if (_bInitialized && _bIsDepthTexture) {
|
---|
| 1245 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1246 | }
|
---|
| 1247 | }
|
---|