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 // _WIN32
|
---|
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 // _WIN32
|
---|
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 // _WIN32
|
---|
295 | if (_bFloat && _bIsTexture && !GLXEW_NV_float_buffer)
|
---|
296 | {
|
---|
297 | PrintExtensionError("GLX_NV_float_buffer");
|
---|
298 | return false;
|
---|
299 | }
|
---|
300 | #endif // _WIN32
|
---|
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 // _WIN32
|
---|
464 | #if defined(DEBUG) || defined(_DEBUG)
|
---|
465 | printf("RenderTexture Error: Render-to-Texture not supported in Linux\n");
|
---|
466 | #endif
|
---|
467 | #endif // _WIN32
|
---|
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 |
|
---|
854 | #if defined(_DEBUG) || defined(DEBUG)
|
---|
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
|
---|
861 | #else // _WIN32
|
---|
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 |
|
---|
940 | #endif // _WIN32
|
---|
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 | }
|
---|
986 | #else // _WIN32
|
---|
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 | }
|
---|
996 | #endif // _WIN32
|
---|
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 | }
|
---|
1084 | #else // _WIN32
|
---|
1085 | _hPreviousContext = glXGetCurrentContext();
|
---|
1086 | _hPreviousDrawable = glXGetCurrentDrawable();
|
---|
1087 |
|
---|
1088 | if (False == glXMakeCurrent(_pDpy, _hPBuffer, _hGLContext)) {
|
---|
1089 | return false;
|
---|
1090 | }
|
---|
1091 | #endif // _WIN32
|
---|
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 | }
|
---|
1200 | #else // _WIN32
|
---|
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 | }
|
---|
1212 | #endif // _WIN32
|
---|
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 | }
|
---|