[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]
|
---|
| 242 | #if defined(_DEBUG) | defined(DEBUG)
|
---|
| 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);
|
---|
| 252 | #else
|
---|
| 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 | }
|
---|
| 272 | #endif
|
---|
| 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 | }
|
---|
| 294 | #else
|
---|
| 295 | if (_bFloat && _bIsTexture && !GLXEW_NV_float_buffer)
|
---|
| 296 | {
|
---|
| 297 | PrintExtensionError("GLX_NV_float_buffer");
|
---|
| 298 | return false;
|
---|
| 299 | }
|
---|
| 300 | #endif
|
---|
| 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 | }
|
---|
| 463 | #else if defined(DEBUG) || defined(_DEBUG)
|
---|
| 464 | printf("RenderTexture Error: Render-to-Texture not supported in Linux\n");
|
---|
| 465 | #endif
|
---|
| 466 | }
|
---|
| 467 | }
|
---|
| 468 | else
|
---|
| 469 | {
|
---|
| 470 | if (!_bRectangle)
|
---|
| 471 | {
|
---|
| 472 | _iTextureTarget = GL_TEXTURE_2D;
|
---|
| 473 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 474 |
|
---|
| 475 | // We'll use clamp to edge as the default texture wrap mode for all tex types
|
---|
| 476 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
| 477 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
| 478 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
---|
| 479 |
|
---|
| 480 | if (bMipmap)
|
---|
| 481 | {
|
---|
| 482 | _bMipmap = true;
|
---|
| 483 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
---|
| 484 |
|
---|
| 485 | // Generate mipmap automatically if supported
|
---|
| 486 | if (GLEW_SGIS_generate_mipmap)
|
---|
| 487 | {
|
---|
| 488 | glTexParameteri( _iTextureTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
---|
| 489 | }
|
---|
| 490 | else
|
---|
| 491 | {
|
---|
| 492 | PrintExtensionError("GL_SGIS_generate_mipmap");
|
---|
| 493 | }
|
---|
| 494 | }
|
---|
| 495 | else
|
---|
| 496 | {
|
---|
| 497 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
---|
| 498 | }
|
---|
| 499 |
|
---|
| 500 | // Set anisotropic filter to the max ratio
|
---|
| 501 | if (bAnisoFilter)
|
---|
| 502 | {
|
---|
| 503 | if (GLEW_EXT_texture_filter_anisotropic)
|
---|
| 504 | {
|
---|
| 505 | _bAnisoFilter = true;
|
---|
| 506 | float rMaxAniso;
|
---|
| 507 | glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &rMaxAniso);
|
---|
| 508 | glTexParameterf( _iTextureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, rMaxAniso);
|
---|
| 509 | }
|
---|
| 510 | }
|
---|
| 511 |
|
---|
| 512 | if (RT_COPY_TO_TEXTURE == _eUpdateMode)
|
---|
| 513 | {
|
---|
| 514 | GLuint iInternalFormat;
|
---|
| 515 | GLuint iFormat;
|
---|
| 516 | if (iABits > 0)
|
---|
| 517 | {
|
---|
| 518 | iInternalFormat = GL_RGBA8;
|
---|
| 519 | iFormat = GL_RGBA;
|
---|
| 520 | }
|
---|
| 521 | else
|
---|
| 522 | {
|
---|
| 523 | iInternalFormat = GL_RGB8;
|
---|
| 524 | iFormat = GL_RGB;
|
---|
| 525 | }
|
---|
| 526 | // Allocate the texture image (but pass it no data for now).
|
---|
| 527 | glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
|
---|
| 528 | 0, iFormat, GL_FLOAT, NULL);
|
---|
| 529 | }
|
---|
| 530 | else
|
---|
| 531 | {
|
---|
| 532 | #ifdef _WIN32
|
---|
| 533 | iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
|
---|
| 534 | if (iABits > 0)
|
---|
| 535 | {
|
---|
| 536 | iBindTarget = WGL_BIND_TO_TEXTURE_RGBA_ARB;
|
---|
| 537 | iTextureFormat = WGL_TEXTURE_RGBA_ARB;
|
---|
| 538 | }
|
---|
| 539 | else
|
---|
| 540 | {
|
---|
| 541 | iBindTarget = WGL_BIND_TO_TEXTURE_RGB_ARB;
|
---|
| 542 | iTextureFormat = WGL_TEXTURE_RGB_ARB;
|
---|
| 543 | }
|
---|
| 544 | #endif
|
---|
| 545 | }
|
---|
| 546 | }
|
---|
| 547 | else
|
---|
| 548 | {
|
---|
| 549 | if (!bNVIDIA)
|
---|
| 550 | {
|
---|
| 551 | fprintf(stderr,
|
---|
| 552 | "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
|
---|
| 553 | return false;
|
---|
| 554 | }
|
---|
| 555 |
|
---|
| 556 | _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
|
---|
| 557 |
|
---|
| 558 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 559 |
|
---|
| 560 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
| 561 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
| 562 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
---|
| 563 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
---|
| 564 |
|
---|
| 565 | if (bMipmap)
|
---|
| 566 | {
|
---|
| 567 |
|
---|
| 568 | fprintf(stderr,
|
---|
| 569 | "RenderTexture Error: rectangle textures do not support mipmaps\n");
|
---|
| 570 | return false;
|
---|
| 571 | }
|
---|
| 572 |
|
---|
| 573 | if (RT_COPY_TO_TEXTURE == _eUpdateMode)
|
---|
| 574 | {
|
---|
| 575 | GLuint iInternalFormat;
|
---|
| 576 | GLuint iFormat;
|
---|
| 577 | if (iABits > 0)
|
---|
| 578 | {
|
---|
| 579 | iInternalFormat = GL_RGBA8;
|
---|
| 580 | iFormat = GL_RGBA;
|
---|
| 581 | }
|
---|
| 582 | else
|
---|
| 583 | {
|
---|
| 584 | iInternalFormat = GL_RGB8;
|
---|
| 585 | iFormat = GL_RGB;
|
---|
| 586 | }
|
---|
| 587 | // Allocate the texture image (but pass it no data for now).
|
---|
| 588 | glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
|
---|
| 589 | 0, iFormat, GL_FLOAT, NULL);
|
---|
| 590 | }
|
---|
| 591 | else
|
---|
| 592 | {
|
---|
| 593 | #ifdef _WIN32
|
---|
| 594 | iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
|
---|
| 595 | if (iABits > 0)
|
---|
| 596 | {
|
---|
| 597 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV;
|
---|
| 598 | iTextureFormat = WGL_TEXTURE_RGBA_ARB;
|
---|
| 599 | }
|
---|
| 600 | else
|
---|
| 601 | {
|
---|
| 602 | iBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV;
|
---|
| 603 | iTextureFormat= WGL_TEXTURE_RGB_ARB;
|
---|
| 604 | }
|
---|
| 605 | #endif
|
---|
| 606 | }
|
---|
| 607 | }
|
---|
| 608 | }
|
---|
| 609 | }
|
---|
| 610 |
|
---|
| 611 | if (_bIsDepthTexture)
|
---|
| 612 | {
|
---|
| 613 | if (!bNVIDIA && _bRectangle)
|
---|
| 614 | {
|
---|
| 615 | fprintf(stderr,
|
---|
| 616 | "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
|
---|
| 617 | return false;
|
---|
| 618 | }
|
---|
| 619 |
|
---|
| 620 | if (!_iTextureTarget)
|
---|
| 621 | _iTextureTarget = _bRectangle ? GL_TEXTURE_RECTANGLE_NV : GL_TEXTURE_2D;
|
---|
| 622 |
|
---|
| 623 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 624 |
|
---|
| 625 | // We'll use clamp to edge as the default texture wrap mode for all tex types
|
---|
| 626 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
| 627 | glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
| 628 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
---|
| 629 | glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
---|
| 630 |
|
---|
| 631 | // user will need to set up hardware shadow mapping himself (using ARB_shadow)
|
---|
| 632 |
|
---|
| 633 | if (RT_COPY_TO_TEXTURE == _eUpdateMode)
|
---|
| 634 | {
|
---|
| 635 | // [Redge]
|
---|
| 636 | if (_bHasArbDepthTexture)
|
---|
| 637 | {
|
---|
| 638 | // Allocate the texture image (but pass it no data for now).
|
---|
| 639 | glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT, _iWidth, _iHeight,
|
---|
| 640 | 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
---|
| 641 | }
|
---|
| 642 | else
|
---|
| 643 | {
|
---|
| 644 | // allocate memory for depth texture
|
---|
| 645 | // Since this is slow, we warn the user in debug mode. (above)
|
---|
| 646 | _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
|
---|
| 647 | glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16, _iWidth, _iHeight,
|
---|
| 648 | 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
|
---|
| 649 | }
|
---|
| 650 | // [/Redge]
|
---|
| 651 | }
|
---|
| 652 | else // RENDER_TO_TEXTURE
|
---|
| 653 | {
|
---|
| 654 | #ifdef _WIN32
|
---|
| 655 | if(_bRectangle)
|
---|
| 656 | {
|
---|
| 657 | if (!iWGLTextureTarget) iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
|
---|
| 658 | iDepthBindTarget = WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV;
|
---|
| 659 | iDepthTextureFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV;
|
---|
| 660 | }
|
---|
| 661 | else
|
---|
| 662 | {
|
---|
| 663 | if (!iWGLTextureTarget) iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
|
---|
| 664 | iDepthBindTarget = WGL_BIND_TO_TEXTURE_DEPTH_NV;
|
---|
| 665 | iDepthTextureFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV;
|
---|
| 666 | }
|
---|
| 667 | #endif
|
---|
| 668 | }
|
---|
| 669 | }
|
---|
| 670 |
|
---|
| 671 | #if _WIN32
|
---|
| 672 | // Get the current context.
|
---|
| 673 | HDC hdc = wglGetCurrentDC();
|
---|
| 674 | if (NULL == hdc)
|
---|
| 675 | _wglGetLastError();
|
---|
| 676 | HGLRC hglrc = wglGetCurrentContext();
|
---|
| 677 | if (NULL == hglrc)
|
---|
| 678 | _wglGetLastError();
|
---|
| 679 |
|
---|
| 680 | int iFormat = 0;
|
---|
| 681 | unsigned int iNumFormats;
|
---|
| 682 | int attribChooseList[50];
|
---|
| 683 | int attribCreateList[50];
|
---|
| 684 | int attribChoose = 0;
|
---|
| 685 | int attribCreate = 0;
|
---|
| 686 |
|
---|
| 687 | // Setup the attrib list for wglChoosePixelFormat()
|
---|
| 688 |
|
---|
| 689 | attribChooseList[attribChoose++] = WGL_RED_BITS_ARB;
|
---|
| 690 | attribChooseList[attribChoose++] = iRBits;
|
---|
| 691 | attribChooseList[attribChoose++] = WGL_GREEN_BITS_ARB;
|
---|
| 692 | attribChooseList[attribChoose++] = iGBits;
|
---|
| 693 | attribChooseList[attribChoose++] = WGL_BLUE_BITS_ARB;
|
---|
| 694 | attribChooseList[attribChoose++] = iBBits;
|
---|
| 695 | attribChooseList[attribChoose++] = WGL_ALPHA_BITS_ARB;
|
---|
| 696 | attribChooseList[attribChoose++] = iABits;
|
---|
| 697 | if (_bFloat)
|
---|
| 698 | {
|
---|
| 699 | if (bNVIDIA)
|
---|
| 700 | {
|
---|
| 701 | attribChooseList[attribChoose++] = WGL_FLOAT_COMPONENTS_NV;
|
---|
| 702 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 703 | }
|
---|
| 704 | else
|
---|
| 705 | {
|
---|
| 706 | attribChooseList[attribChoose++] = WGL_PIXEL_TYPE_ARB;
|
---|
| 707 | attribChooseList[attribChoose++] = WGL_TYPE_RGBA_FLOAT_ATI;
|
---|
| 708 | }
|
---|
| 709 | }
|
---|
| 710 |
|
---|
| 711 | attribChooseList[attribChoose++] = WGL_STENCIL_BITS_ARB;
|
---|
| 712 | attribChooseList[attribChoose++] = (bStencil) ? 8 : 0;
|
---|
| 713 | attribChooseList[attribChoose++] = WGL_DEPTH_BITS_ARB;
|
---|
| 714 | attribChooseList[attribChoose++] = (bDepth) ? 24 : 0;
|
---|
| 715 | attribChooseList[attribChoose++] = WGL_DRAW_TO_PBUFFER_ARB;
|
---|
| 716 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 717 |
|
---|
| 718 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 719 | {
|
---|
| 720 | attribChooseList[attribChoose++] = iBindTarget;
|
---|
| 721 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 722 | }
|
---|
| 723 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 724 | {
|
---|
| 725 | attribChooseList[attribChoose++] = iDepthBindTarget;
|
---|
| 726 | attribChooseList[attribChoose++] = GL_TRUE;
|
---|
| 727 | }
|
---|
| 728 |
|
---|
| 729 | attribChooseList[attribChoose++] = 0;
|
---|
| 730 |
|
---|
| 731 | // Setup the attrib list for wglCreatePbuffer()
|
---|
| 732 | if ((_bIsTexture || _bIsDepthTexture) && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 733 | {
|
---|
| 734 | attribCreateList[attribCreate++] = WGL_TEXTURE_TARGET_ARB;
|
---|
| 735 | attribCreateList[attribCreate++] = iWGLTextureTarget;
|
---|
| 736 | }
|
---|
| 737 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 738 | {
|
---|
| 739 | attribCreateList[attribCreate++] = WGL_TEXTURE_FORMAT_ARB;
|
---|
| 740 | attribCreateList[attribCreate++] = iTextureFormat;
|
---|
| 741 | /*attribCreateList[attribCreate++] = WGL_TEXTURE_TARGET_ARB;
|
---|
| 742 | attribCreateList[attribCreate++] = iWGLTextureTarget;*/
|
---|
| 743 | attribCreateList[attribCreate++] = WGL_MIPMAP_TEXTURE_ARB;
|
---|
| 744 | attribCreateList[attribCreate++] = (bMipmap) ? GL_TRUE : GL_FALSE;
|
---|
| 745 | }
|
---|
| 746 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 747 | {
|
---|
| 748 | attribCreateList[attribCreate++] = WGL_DEPTH_TEXTURE_FORMAT_NV;
|
---|
| 749 | attribCreateList[attribCreate++] = iDepthTextureFormat;
|
---|
| 750 | }
|
---|
| 751 | attribCreateList[attribCreate++] = WGL_PBUFFER_LARGEST_ARB;
|
---|
| 752 | attribCreateList[attribCreate++] = GL_FALSE;
|
---|
| 753 | attribCreateList[attribCreate++] = 0;
|
---|
| 754 |
|
---|
| 755 | if (!wglChoosePixelFormatARB( hdc, attribChooseList, NULL, 1, &iFormat, &iNumFormats))
|
---|
| 756 | {
|
---|
| 757 | fprintf(stderr,
|
---|
| 758 | "RenderTexture::Initialize() creation error: wglChoosePixelFormatARB() failed.\n");
|
---|
| 759 | _wglGetLastError();
|
---|
| 760 | return false;
|
---|
| 761 | }
|
---|
| 762 | if ( iNumFormats <= 0 )
|
---|
| 763 | {
|
---|
| 764 | fprintf(stderr,
|
---|
| 765 | "RenderTexture::Initialize() creation error: Couldn't find a suitable pixel format.\n");
|
---|
| 766 | _wglGetLastError();
|
---|
| 767 | return false;
|
---|
| 768 | }
|
---|
| 769 |
|
---|
| 770 | // Create the p-buffer.
|
---|
| 771 | _hPBuffer = wglCreatePbufferARB( hdc, iFormat, _iWidth, _iHeight, attribCreateList );
|
---|
| 772 | if (!_hPBuffer)
|
---|
| 773 | {
|
---|
| 774 | fprintf(stderr, "RenderTexture::Initialize() pbuffer creation error: wglCreatePbufferARB() failed\n");
|
---|
| 775 | _wglGetLastError();
|
---|
| 776 | return false;
|
---|
| 777 | }
|
---|
| 778 |
|
---|
| 779 | // Get the device context.
|
---|
| 780 | _hDC = wglGetPbufferDCARB( _hPBuffer);
|
---|
| 781 | if ( !_hDC )
|
---|
| 782 | {
|
---|
| 783 | fprintf(stderr,
|
---|
| 784 | "RenderTexture::Initialize() creation error: wglGetGetPbufferDCARB() failed\n");
|
---|
| 785 | _wglGetLastError();
|
---|
| 786 | return false;
|
---|
| 787 | }
|
---|
| 788 |
|
---|
| 789 | // Create a gl context for the p-buffer.
|
---|
| 790 |
|
---|
| 791 |
|
---|
| 792 | _hGLContext = wglCreateContext( _hDC );
|
---|
| 793 | if ( !_hGLContext )
|
---|
| 794 | {
|
---|
| 795 | fprintf(stderr, "RenderTexture::Initialize() creation error: wglCreateContext() failed\n");
|
---|
| 796 | _wglGetLastError();
|
---|
| 797 | return false;
|
---|
| 798 | }
|
---|
| 799 |
|
---|
| 800 | // Share lists, texture objects, and program objects.
|
---|
| 801 | if( bShare )
|
---|
| 802 | {
|
---|
| 803 | if( !wglShareLists(hglrc, _hGLContext) )
|
---|
| 804 | {
|
---|
| 805 | fprintf(stderr, "RenderTexture::Initialize() creation error: wglShareLists() failed\n" );
|
---|
| 806 | _wglGetLastError();
|
---|
| 807 | return false;
|
---|
| 808 | }
|
---|
| 809 | }
|
---|
| 810 |
|
---|
| 811 | // bind the pbuffer to the render texture object
|
---|
| 812 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 813 | {
|
---|
| 814 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 815 | if (wglBindTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB) == FALSE)
|
---|
| 816 | {
|
---|
| 817 | _wglGetLastError();
|
---|
| 818 | return false;
|
---|
| 819 | }
|
---|
| 820 | }
|
---|
| 821 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 822 | {
|
---|
| 823 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 824 | if (wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV) == FALSE)
|
---|
| 825 | {
|
---|
| 826 | _wglGetLastError();
|
---|
| 827 | return false;
|
---|
| 828 | }
|
---|
| 829 | }
|
---|
| 830 |
|
---|
| 831 | // Determine the actual width and height we were able to create.
|
---|
| 832 | wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
|
---|
| 833 | wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
|
---|
| 834 |
|
---|
| 835 | _bInitialized = true;
|
---|
| 836 |
|
---|
| 837 | // get the actual number of bits allocated:
|
---|
| 838 | int attrib = WGL_RED_BITS_ARB;
|
---|
| 839 | int value;
|
---|
| 840 | _iBits[0] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iRBits;
|
---|
| 841 | attrib = WGL_GREEN_BITS_ARB;
|
---|
| 842 | _iBits[1] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iGBits;
|
---|
| 843 | attrib = WGL_BLUE_BITS_ARB;
|
---|
| 844 | _iBits[2] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iBBits;
|
---|
| 845 | attrib = WGL_ALPHA_BITS_ARB;
|
---|
| 846 | _iBits[3] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iABits;
|
---|
| 847 | attrib = WGL_DEPTH_BITS_ARB;
|
---|
| 848 | _iBits[4] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : 0;
|
---|
| 849 | attrib = WGL_STENCIL_BITS_ARB;
|
---|
| 850 | _iBits[5] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : 0;
|
---|
| 851 |
|
---|
| 852 | #if defined(_DEBUG) | defined(DEBUG)
|
---|
| 853 | fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
|
---|
| 854 | _iWidth, _iHeight, _iBits[0], _iBits[1], _iBits[2], _iBits[3]);
|
---|
| 855 | if (_iBits[4]) fprintf(stderr, " depth=%d", _iBits[4]);
|
---|
| 856 | if (_iBits[5]) fprintf(stderr, " stencil=%d", _iBits[5]);
|
---|
| 857 | fprintf(stderr, "\n");
|
---|
| 858 | #endif
|
---|
| 859 | #else
|
---|
| 860 | _pDpy = glXGetCurrentDisplay();
|
---|
| 861 | GLXContext context = glXGetCurrentContext();
|
---|
| 862 | int screen = DefaultScreen(_pDpy);
|
---|
| 863 | XVisualInfo *visInfo;
|
---|
| 864 |
|
---|
| 865 | int iFormat = 0;
|
---|
| 866 | int iNumFormats;
|
---|
| 867 | int fbAttribs[50];
|
---|
| 868 | int attrib = 0;
|
---|
| 869 |
|
---|
| 870 | fbAttribs[attrib++] = GLX_RENDER_TYPE_SGIX;
|
---|
| 871 | fbAttribs[attrib++] = GLX_RGBA_BIT_SGIX;
|
---|
| 872 | fbAttribs[attrib++] = GLX_DRAWABLE_TYPE_SGIX;
|
---|
| 873 | fbAttribs[attrib++] = GLX_PBUFFER_BIT_SGIX;
|
---|
| 874 | fbAttribs[attrib++] = GLX_STENCIL_SIZE;
|
---|
| 875 | fbAttribs[attrib++] = (bStencil) ? 8 : 0;
|
---|
| 876 | fbAttribs[attrib++] = GLX_DEPTH_SIZE;
|
---|
| 877 | fbAttribs[attrib++] = (bDepth) ? 24 : 0;
|
---|
| 878 | if (_bFloat)
|
---|
| 879 | {
|
---|
| 880 | fbAttribs[attrib++] = GLX_RED_SIZE;
|
---|
| 881 | fbAttribs[attrib++] = iRBits;
|
---|
| 882 | fbAttribs[attrib++] = GLX_GREEN_SIZE;
|
---|
| 883 | fbAttribs[attrib++] = iGBits;
|
---|
| 884 | fbAttribs[attrib++] = GLX_BLUE_SIZE;
|
---|
| 885 | fbAttribs[attrib++] = iBBits;
|
---|
| 886 | fbAttribs[attrib++] = GLX_ALPHA_SIZE;
|
---|
| 887 | fbAttribs[attrib++] = iABits;
|
---|
| 888 | fbAttribs[attrib++] = GLX_FLOAT_COMPONENTS_NV;
|
---|
| 889 | fbAttribs[attrib++] = 1;
|
---|
| 890 | }
|
---|
| 891 | fbAttribs[attrib++] = None;
|
---|
| 892 |
|
---|
| 893 | GLXFBConfigSGIX *fbConfigs;
|
---|
| 894 | int nConfigs;
|
---|
| 895 |
|
---|
| 896 | fbConfigs = glXChooseFBConfigSGIX(_pDpy, screen, fbAttribs, &nConfigs);
|
---|
| 897 |
|
---|
| 898 | if (nConfigs == 0 || !fbConfigs) {
|
---|
| 899 | fprintf(stderr,
|
---|
| 900 | "RenderTexture::Initialize() creation error: Couldn't find a suitable pixel format\n");
|
---|
| 901 | return false;
|
---|
| 902 | }
|
---|
| 903 |
|
---|
| 904 | // Pick the first returned format that will return a pbuffer
|
---|
| 905 | for (int i=0;i<nConfigs;i++)
|
---|
| 906 | {
|
---|
| 907 | _hPBuffer = glXCreateGLXPbufferSGIX(_pDpy, fbConfigs[i], _iWidth, _iHeight, NULL);
|
---|
| 908 | if (_hPBuffer) {
|
---|
| 909 | _hGLContext = glXCreateContextWithConfigSGIX(_pDpy, fbConfigs[i], GLX_RGBA_TYPE, bShare?context:NULL, True);
|
---|
| 910 | break;
|
---|
| 911 | }
|
---|
| 912 | }
|
---|
| 913 |
|
---|
| 914 | if (!_hPBuffer)
|
---|
| 915 | {
|
---|
| 916 | fprintf(stderr, "RenderTexture::Initialize() pbuffer creation error: glXCreateGLXPbufferSGIX() failed\n");
|
---|
| 917 | return false;
|
---|
| 918 | }
|
---|
| 919 |
|
---|
| 920 | if(!_hGLContext)
|
---|
| 921 | {
|
---|
| 922 | // Try indirect
|
---|
| 923 | _hGLContext = glXCreateContext(_pDpy, visInfo, bShare?context:NULL, False);
|
---|
| 924 | if ( !_hGLContext )
|
---|
| 925 | {
|
---|
| 926 | fprintf(stderr, "RenderTexture::Initialize() creation error: glXCreateContext() failed\n");
|
---|
| 927 | return false;
|
---|
| 928 | }
|
---|
| 929 | }
|
---|
| 930 |
|
---|
| 931 | glXQueryGLXPbufferSGIX(_pDpy, _hPBuffer, GLX_WIDTH_SGIX, (GLuint*)&_iWidth);
|
---|
| 932 | glXQueryGLXPbufferSGIX(_pDpy, _hPBuffer, GLX_HEIGHT_SGIX, (GLuint*)&_iHeight);
|
---|
| 933 |
|
---|
| 934 | _bInitialized = true;
|
---|
| 935 |
|
---|
| 936 | // XXX Query the color format
|
---|
| 937 |
|
---|
| 938 | #endif
|
---|
| 939 |
|
---|
| 940 | return true;
|
---|
| 941 | }
|
---|
| 942 |
|
---|
| 943 | //------------------------------------------------------------------------------
|
---|
| 944 | // Function : RenderTexture::_Invalidate
|
---|
| 945 | // Description :
|
---|
| 946 | //------------------------------------------------------------------------------
|
---|
| 947 | /**
|
---|
| 948 | * @fn RenderTexture::_Invalidate()
|
---|
| 949 | * @brief Returns the pbuffer memory to the graphics device.
|
---|
| 950 | *
|
---|
| 951 | */
|
---|
| 952 | bool RenderTexture::_Invalidate()
|
---|
| 953 | {
|
---|
| 954 | _bFloat = false;
|
---|
| 955 | _bRectangle = false;
|
---|
| 956 | _bInitialized = false;
|
---|
| 957 | _bHasDepth = false;
|
---|
| 958 | _bHasStencil = false;
|
---|
| 959 | _bMipmap = false;
|
---|
| 960 | _bAnisoFilter = false;
|
---|
| 961 | _iBits[0] = _iBits[1] = _iBits[2] = _iBits[3] = 0;
|
---|
| 962 |
|
---|
| 963 | if (_bIsTexture)
|
---|
| 964 | glDeleteTextures(1, &_iTextureID);
|
---|
| 965 | if (_bIsDepthTexture) {
|
---|
| 966 | // [Redge]
|
---|
| 967 | if (!_bHasArbDepthTexture) delete[] _pPoorDepthTexture;
|
---|
| 968 | // [/Redge]
|
---|
| 969 | glDeleteTextures(1, &_iDepthTextureID);
|
---|
| 970 | }
|
---|
| 971 |
|
---|
| 972 | #if _WIN32
|
---|
| 973 | if ( _hPBuffer )
|
---|
| 974 | {
|
---|
| 975 | // Check if we are currently rendering in the pbuffer
|
---|
| 976 | if (wglGetCurrentContext() == _hGLContext)
|
---|
| 977 | wglMakeCurrent(0,0);
|
---|
| 978 | wglDeleteContext( _hGLContext);
|
---|
| 979 | wglReleasePbufferDCARB( _hPBuffer, _hDC);
|
---|
| 980 | wglDestroyPbufferARB( _hPBuffer );
|
---|
| 981 | _hPBuffer = 0;
|
---|
| 982 | return true;
|
---|
| 983 | }
|
---|
| 984 | #else
|
---|
| 985 | if ( _hPBuffer )
|
---|
| 986 | {
|
---|
| 987 | if(glXGetCurrentContext() == _hGLContext)
|
---|
| 988 | // XXX I don't know if this is right at all
|
---|
| 989 | glXMakeCurrent(_pDpy, _hPBuffer, 0);
|
---|
| 990 | glXDestroyGLXPbufferSGIX(_pDpy, _hPBuffer);
|
---|
| 991 | _hPBuffer = 0;
|
---|
| 992 | return true;
|
---|
| 993 | }
|
---|
| 994 | #endif
|
---|
| 995 | return false;
|
---|
| 996 | }
|
---|
| 997 |
|
---|
| 998 |
|
---|
| 999 | //------------------------------------------------------------------------------
|
---|
| 1000 | // Function : RenderTexture::Reset
|
---|
| 1001 | // Description :
|
---|
| 1002 | //------------------------------------------------------------------------------
|
---|
| 1003 | /**
|
---|
| 1004 | * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
|
---|
| 1005 | * @brief Resets the resolution of the offscreen buffer.
|
---|
| 1006 | *
|
---|
| 1007 | * Causes the buffer to delete itself. User must call Initialize() again
|
---|
| 1008 | * before use.
|
---|
| 1009 | */
|
---|
| 1010 | bool RenderTexture::Reset(int iWidth, int iHeight, bool bIsTexture /* = true */,
|
---|
| 1011 | bool bIsDepthTexture /* = false */)
|
---|
| 1012 | {
|
---|
| 1013 | if (!_Invalidate())
|
---|
| 1014 | {
|
---|
| 1015 | fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
|
---|
| 1016 | return false;
|
---|
| 1017 | }
|
---|
| 1018 | _iWidth = iWidth;
|
---|
| 1019 | _iHeight = iHeight;
|
---|
| 1020 | _bIsTexture = bIsTexture;
|
---|
| 1021 | _bIsDepthTexture = bIsDepthTexture;
|
---|
| 1022 |
|
---|
| 1023 | return true;
|
---|
| 1024 | }
|
---|
| 1025 |
|
---|
| 1026 |
|
---|
| 1027 | //------------------------------------------------------------------------------
|
---|
| 1028 | // Function : RenderTexture::BeginCapture
|
---|
| 1029 | // Description :
|
---|
| 1030 | //------------------------------------------------------------------------------
|
---|
| 1031 | /**
|
---|
| 1032 | * @fn RenderTexture::BeginCapture()
|
---|
| 1033 | * @brief Activates rendering to the RenderTexture.
|
---|
| 1034 | */
|
---|
| 1035 | bool RenderTexture::BeginCapture()
|
---|
| 1036 | {
|
---|
| 1037 | if (!_bInitialized)
|
---|
| 1038 | {
|
---|
| 1039 | fprintf(stderr, "RenderTexture::BeginCapture(): Texture is not initialized!\n");
|
---|
| 1040 | exit(1);
|
---|
| 1041 | return false;
|
---|
| 1042 | }
|
---|
| 1043 | #ifdef _WIN32
|
---|
| 1044 | // cache the current context so we can reset it when EndCapture() is called.
|
---|
| 1045 | _hPreviousDC = wglGetCurrentDC();
|
---|
| 1046 | if (NULL == _hPreviousDC)
|
---|
| 1047 | _wglGetLastError();
|
---|
| 1048 | _hPreviousContext = wglGetCurrentContext();
|
---|
| 1049 | if (NULL == _hPreviousContext)
|
---|
| 1050 | _wglGetLastError();
|
---|
| 1051 |
|
---|
| 1052 | if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1053 | {
|
---|
| 1054 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1055 |
|
---|
| 1056 | // release the pbuffer from the render texture object
|
---|
| 1057 | if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB))
|
---|
| 1058 | {
|
---|
| 1059 | _wglGetLastError();
|
---|
| 1060 | return false;
|
---|
| 1061 | }
|
---|
| 1062 | }
|
---|
| 1063 |
|
---|
| 1064 | if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1065 | {
|
---|
| 1066 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1067 |
|
---|
| 1068 | // release the pbuffer from the render texture object
|
---|
| 1069 | if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
|
---|
| 1070 | {
|
---|
| 1071 | _wglGetLastError();
|
---|
| 1072 | return false;
|
---|
| 1073 | }
|
---|
| 1074 | }
|
---|
| 1075 |
|
---|
| 1076 | // make the pbuffer's rendering context current.
|
---|
| 1077 | if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
|
---|
| 1078 | {
|
---|
| 1079 | _wglGetLastError();
|
---|
| 1080 | return false;
|
---|
| 1081 | }
|
---|
| 1082 | #else
|
---|
| 1083 | _hPreviousContext = glXGetCurrentContext();
|
---|
| 1084 | _hPreviousDrawable = glXGetCurrentDrawable();
|
---|
| 1085 |
|
---|
| 1086 | if (False == glXMakeCurrent(_pDpy, _hPBuffer, _hGLContext)) {
|
---|
| 1087 | return false;
|
---|
| 1088 | }
|
---|
| 1089 | #endif
|
---|
| 1090 |
|
---|
| 1091 | return true;
|
---|
| 1092 | }
|
---|
| 1093 |
|
---|
| 1094 |
|
---|
| 1095 | //------------------------------------------------------------------------------
|
---|
| 1096 | // Function : RenderTexture::EndCapture
|
---|
| 1097 | // Description :
|
---|
| 1098 | //------------------------------------------------------------------------------
|
---|
| 1099 | /**
|
---|
| 1100 | * @fn RenderTexture::EndCapture()
|
---|
| 1101 | * @brief Ends rendering to the RenderTexture.
|
---|
| 1102 | */
|
---|
| 1103 | bool RenderTexture::EndCapture()
|
---|
| 1104 | {
|
---|
| 1105 | bool bContextReset = false;
|
---|
| 1106 |
|
---|
| 1107 | if (!_bInitialized)
|
---|
| 1108 | {
|
---|
| 1109 | fprintf(stderr, "RenderTexture::EndCapture(): Texture is not initialized!\n");
|
---|
| 1110 | return false;
|
---|
| 1111 | }
|
---|
| 1112 | #ifdef _WIN32
|
---|
| 1113 | if (_bIsTexture)
|
---|
| 1114 | {
|
---|
| 1115 | if (RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1116 | {
|
---|
| 1117 | // make the previous rendering context current
|
---|
| 1118 | if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
|
---|
| 1119 | {
|
---|
| 1120 | _wglGetLastError();
|
---|
| 1121 | return false;
|
---|
| 1122 | }
|
---|
| 1123 | bContextReset = true;
|
---|
| 1124 |
|
---|
| 1125 | // [Redge] moved binding completely to Bind()
|
---|
| 1126 | // [Mark] Can't do that, because it makes things difficult for Cg users.
|
---|
| 1127 | // bind the pbuffer to the render texture object
|
---|
| 1128 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1129 | if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB))
|
---|
| 1130 | {
|
---|
| 1131 | _wglGetLastError();
|
---|
| 1132 | return false;
|
---|
| 1133 | }
|
---|
| 1134 | }
|
---|
| 1135 | else
|
---|
| 1136 | {
|
---|
| 1137 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1138 | glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
|
---|
| 1139 | }
|
---|
| 1140 | }
|
---|
| 1141 | if (_bIsDepthTexture)
|
---|
| 1142 | {
|
---|
| 1143 | if (RT_RENDER_TO_TEXTURE == _eUpdateMode)
|
---|
| 1144 | {
|
---|
| 1145 | // make the previous rendering context current
|
---|
| 1146 | if(!bContextReset)
|
---|
| 1147 | {
|
---|
| 1148 | if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
|
---|
| 1149 | {
|
---|
| 1150 | _wglGetLastError();
|
---|
| 1151 | return false;
|
---|
| 1152 | }
|
---|
| 1153 | bContextReset = true;
|
---|
| 1154 | }
|
---|
| 1155 |
|
---|
| 1156 | // [Redge] moved binding completely to Bind()
|
---|
| 1157 | // [Mark] Can't do that, because it makes things difficult for Cg users.
|
---|
| 1158 | // bind the pbuffer to the render texture object
|
---|
| 1159 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1160 | if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
|
---|
| 1161 | {
|
---|
| 1162 | _wglGetLastError();
|
---|
| 1163 | return false;
|
---|
| 1164 | }
|
---|
| 1165 | }
|
---|
| 1166 | else
|
---|
| 1167 | {
|
---|
| 1168 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1169 | // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
|
---|
| 1170 | // [Redge]
|
---|
| 1171 | if (_bHasArbDepthTexture)
|
---|
| 1172 | {
|
---|
| 1173 | glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
|
---|
| 1174 | }
|
---|
| 1175 | else
|
---|
| 1176 | {
|
---|
| 1177 | // no 'real' depth texture available, so behavior has to be emulated
|
---|
| 1178 | // using glReadPixels (beware, this is (naturally) slow ...)
|
---|
| 1179 | glReadPixels(0, 0, _iWidth, _iHeight,
|
---|
| 1180 | GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
|
---|
| 1181 | glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
|
---|
| 1182 | _iWidth, _iHeight,
|
---|
| 1183 | 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
|
---|
| 1184 | }
|
---|
| 1185 | // [/Redge]
|
---|
| 1186 | }
|
---|
| 1187 | }
|
---|
| 1188 |
|
---|
| 1189 | if(!bContextReset)
|
---|
| 1190 | {
|
---|
| 1191 | // make the previous rendering context current
|
---|
| 1192 | if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
|
---|
| 1193 | {
|
---|
| 1194 | _wglGetLastError();
|
---|
| 1195 | return false;
|
---|
| 1196 | }
|
---|
| 1197 | }
|
---|
| 1198 | #else
|
---|
| 1199 | assert(_bIsTexture);
|
---|
| 1200 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1201 | glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
|
---|
| 1202 |
|
---|
| 1203 | if(!bContextReset)
|
---|
| 1204 | {
|
---|
| 1205 | if (False == glXMakeCurrent(_pDpy, _hPreviousDrawable, _hPreviousContext))
|
---|
| 1206 | {
|
---|
| 1207 | return false;
|
---|
| 1208 | }
|
---|
| 1209 | }
|
---|
| 1210 | #endif
|
---|
| 1211 | return true;
|
---|
| 1212 | }
|
---|
| 1213 |
|
---|
| 1214 |
|
---|
| 1215 |
|
---|
| 1216 | //------------------------------------------------------------------------------
|
---|
| 1217 | // Function : RenderTexture::Bind
|
---|
| 1218 | // Description :
|
---|
| 1219 | //------------------------------------------------------------------------------
|
---|
| 1220 | /**
|
---|
| 1221 | * @fn RenderTexture::Bind()
|
---|
| 1222 | * @brief Binds RGB texture.
|
---|
| 1223 | */
|
---|
| 1224 | void RenderTexture::Bind() const
|
---|
| 1225 | {
|
---|
| 1226 | if (_bInitialized) {
|
---|
| 1227 | glBindTexture(_iTextureTarget, _iTextureID);
|
---|
| 1228 | }
|
---|
| 1229 | }
|
---|
| 1230 |
|
---|
| 1231 |
|
---|
| 1232 | //------------------------------------------------------------------------------
|
---|
| 1233 | // Function : RenderTexture::BindDepth
|
---|
| 1234 | // Description :
|
---|
| 1235 | //------------------------------------------------------------------------------
|
---|
| 1236 | /**
|
---|
| 1237 | * @fn RenderTexture::BindDepth()
|
---|
| 1238 | * @brief Binds depth texture.
|
---|
| 1239 | */
|
---|
| 1240 | void RenderTexture::BindDepth() const
|
---|
| 1241 | {
|
---|
| 1242 | if (_bInitialized && _bIsDepthTexture) {
|
---|
| 1243 | glBindTexture(_iTextureTarget, _iDepthTextureID);
|
---|
| 1244 | }
|
---|
| 1245 | }
|
---|