1 | /* |
---|
2 | ----------------------------------------------------------------------------- |
---|
3 | This source file is part of OGRE |
---|
4 | (Object-oriented Graphics Rendering Engine) |
---|
5 | For the latest info, see http://www.ogre3d.org |
---|
6 | |
---|
7 | Copyright (c) 2000-2006 Torus Knot Software Ltd |
---|
8 | Also see acknowledgements in Readme.html |
---|
9 | |
---|
10 | This program is free software; you can redistribute it and/or modify it under |
---|
11 | the terms of the GNU Lesser General Public License as published by the Free Software |
---|
12 | Foundation; either version 2 of the License, or (at your option) any later |
---|
13 | version. |
---|
14 | |
---|
15 | This program is distributed in the hope that it will be useful, but WITHOUT |
---|
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
---|
18 | |
---|
19 | You should have received a copy of the GNU Lesser General Public License along with |
---|
20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
---|
22 | http://www.gnu.org/copyleft/lesser.txt. |
---|
23 | |
---|
24 | You may alternatively use this source under the terms of a specific version of |
---|
25 | the OGRE Unrestricted License provided you have obtained such a license from |
---|
26 | Torus Knot Software Ltd.s |
---|
27 | ----------------------------------------------------------------------------- |
---|
28 | */ |
---|
29 | |
---|
30 | |
---|
31 | #include "OgreGLRenderSystem.h" |
---|
32 | #include "OgreRenderSystem.h" |
---|
33 | #include "OgreLogManager.h" |
---|
34 | #include "OgreStringConverter.h" |
---|
35 | #include "OgreLight.h" |
---|
36 | #include "OgreCamera.h" |
---|
37 | #include "OgreGLTextureManager.h" |
---|
38 | #include "OgreGLHardwareVertexBuffer.h" |
---|
39 | #include "OgreGLHardwareIndexBuffer.h" |
---|
40 | #include "OgreGLDefaultHardwareBufferManager.h" |
---|
41 | #include "OgreGLUtil.h" |
---|
42 | #include "OgreGLGpuProgram.h" |
---|
43 | #include "OgreGLGpuNvparseProgram.h" |
---|
44 | #include "ATI_FS_GLGpuProgram.h" |
---|
45 | #include "OgreGLGpuProgramManager.h" |
---|
46 | #include "OgreException.h" |
---|
47 | #include "OgreGLSLExtSupport.h" |
---|
48 | #include "OgreGLHardwareOcclusionQuery.h" |
---|
49 | #include "OgreGLContext.h" |
---|
50 | |
---|
51 | #include "OgreGLFBORenderTexture.h" |
---|
52 | #include "OgreGLPBRenderTexture.h" |
---|
53 | #include "OgreConfig.h" |
---|
54 | |
---|
55 | // Convenience macro from ARB_vertex_buffer_object spec |
---|
56 | #define VBO_BUFFER_OFFSET(i) ((char *)NULL + (i)) |
---|
57 | GLenum glewContextInit (Ogre::GLSupport *glSupport); |
---|
58 | |
---|
59 | namespace Ogre { |
---|
60 | |
---|
61 | // Callback function used when registering GLGpuPrograms |
---|
62 | GpuProgram* createGLArbGpuProgram(ResourceManager* creator, |
---|
63 | const String& name, ResourceHandle handle, |
---|
64 | const String& group, bool isManual, ManualResourceLoader* loader, |
---|
65 | GpuProgramType gptype, const String& syntaxCode) |
---|
66 | { |
---|
67 | GLArbGpuProgram* ret = new GLArbGpuProgram( |
---|
68 | creator, name, handle, group, isManual, loader); |
---|
69 | ret->setType(gptype); |
---|
70 | ret->setSyntaxCode(syntaxCode); |
---|
71 | return ret; |
---|
72 | } |
---|
73 | |
---|
74 | GpuProgram* createGLGpuNvparseProgram(ResourceManager* creator, |
---|
75 | const String& name, ResourceHandle handle, |
---|
76 | const String& group, bool isManual, ManualResourceLoader* loader, |
---|
77 | GpuProgramType gptype, const String& syntaxCode) |
---|
78 | { |
---|
79 | GLGpuNvparseProgram* ret = new GLGpuNvparseProgram( |
---|
80 | creator, name, handle, group, isManual, loader); |
---|
81 | ret->setType(gptype); |
---|
82 | ret->setSyntaxCode(syntaxCode); |
---|
83 | return ret; |
---|
84 | } |
---|
85 | |
---|
86 | GpuProgram* createGL_ATI_FS_GpuProgram(ResourceManager* creator, |
---|
87 | const String& name, ResourceHandle handle, |
---|
88 | const String& group, bool isManual, ManualResourceLoader* loader, |
---|
89 | GpuProgramType gptype, const String& syntaxCode) |
---|
90 | { |
---|
91 | |
---|
92 | ATI_FS_GLGpuProgram* ret = new ATI_FS_GLGpuProgram( |
---|
93 | creator, name, handle, group, isManual, loader); |
---|
94 | ret->setType(gptype); |
---|
95 | ret->setSyntaxCode(syntaxCode); |
---|
96 | return ret; |
---|
97 | } |
---|
98 | |
---|
99 | GLRenderSystem::GLRenderSystem() |
---|
100 | : mDepthWrite(true), mStencilMask(0xFFFFFFFF), mHardwareBufferManager(0), |
---|
101 | mGpuProgramManager(0), |
---|
102 | mGLSLProgramFactory(0), |
---|
103 | mRTTManager(0) |
---|
104 | { |
---|
105 | size_t i; |
---|
106 | |
---|
107 | LogManager::getSingleton().logMessage(getName() + " created."); |
---|
108 | |
---|
109 | // Get our GLSupport |
---|
110 | mGLSupport = getGLSupport(); |
---|
111 | |
---|
112 | for( i=0; i<MAX_LIGHTS; i++ ) |
---|
113 | mLights[i] = NULL; |
---|
114 | |
---|
115 | mWorldMatrix = Matrix4::IDENTITY; |
---|
116 | mViewMatrix = Matrix4::IDENTITY; |
---|
117 | |
---|
118 | initConfigOptions(); |
---|
119 | |
---|
120 | mColourWrite[0] = mColourWrite[1] = mColourWrite[2] = mColourWrite[3] = true; |
---|
121 | |
---|
122 | for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++) |
---|
123 | { |
---|
124 | // Dummy value |
---|
125 | mTextureCoordIndex[i] = 99; |
---|
126 | } |
---|
127 | |
---|
128 | for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++) |
---|
129 | { |
---|
130 | mTextureTypes[i] = 0; |
---|
131 | } |
---|
132 | |
---|
133 | mActiveRenderTarget = 0; |
---|
134 | mCurrentContext = 0; |
---|
135 | mMainContext = 0; |
---|
136 | |
---|
137 | mGLInitialized = false; |
---|
138 | |
---|
139 | mCurrentLights = 0; |
---|
140 | mMinFilter = FO_LINEAR; |
---|
141 | mMipFilter = FO_POINT; |
---|
142 | mCurrentVertexProgram = 0; |
---|
143 | mCurrentFragmentProgram = 0; |
---|
144 | |
---|
145 | mClipPlanes.reserve(6); |
---|
146 | |
---|
147 | } |
---|
148 | |
---|
149 | GLRenderSystem::~GLRenderSystem() |
---|
150 | { |
---|
151 | shutdown(); |
---|
152 | |
---|
153 | // Destroy render windows |
---|
154 | RenderTargetMap::iterator i; |
---|
155 | for (i = mRenderTargets.begin(); i != mRenderTargets.end(); ++i) |
---|
156 | { |
---|
157 | delete i->second; |
---|
158 | } |
---|
159 | mRenderTargets.clear(); |
---|
160 | |
---|
161 | delete mGLSupport; |
---|
162 | } |
---|
163 | |
---|
164 | const String& GLRenderSystem::getName(void) const |
---|
165 | { |
---|
166 | static String strName("OpenGL Rendering Subsystem"); |
---|
167 | return strName; |
---|
168 | } |
---|
169 | |
---|
170 | void GLRenderSystem::initConfigOptions(void) |
---|
171 | { |
---|
172 | mGLSupport->addConfig(); |
---|
173 | } |
---|
174 | |
---|
175 | ConfigOptionMap& GLRenderSystem::getConfigOptions(void) |
---|
176 | { |
---|
177 | return mGLSupport->getConfigOptions(); |
---|
178 | } |
---|
179 | |
---|
180 | void GLRenderSystem::setConfigOption(const String &name, const String &value) |
---|
181 | { |
---|
182 | mGLSupport->setConfigOption(name, value); |
---|
183 | } |
---|
184 | |
---|
185 | String GLRenderSystem::validateConfigOptions(void) |
---|
186 | { |
---|
187 | // XXX Return an error string if something is invalid |
---|
188 | return mGLSupport->validateConfig(); |
---|
189 | } |
---|
190 | |
---|
191 | RenderWindow* GLRenderSystem::initialise(bool autoCreateWindow, const String& windowTitle) |
---|
192 | { |
---|
193 | mGLSupport->start(); |
---|
194 | |
---|
195 | RenderWindow* autoWindow = mGLSupport->createWindow(autoCreateWindow, this, windowTitle); |
---|
196 | |
---|
197 | |
---|
198 | _setCullingMode( mCullingMode ); |
---|
199 | |
---|
200 | return autoWindow; |
---|
201 | } |
---|
202 | |
---|
203 | void GLRenderSystem::initGL(RenderTarget *primary) |
---|
204 | { |
---|
205 | // Set main and current context |
---|
206 | mMainContext = 0; |
---|
207 | primary->getCustomAttribute("GLCONTEXT", &mMainContext); |
---|
208 | mCurrentContext = mMainContext; |
---|
209 | |
---|
210 | // Set primary context as active |
---|
211 | if(mCurrentContext) |
---|
212 | mCurrentContext->setCurrent(); |
---|
213 | |
---|
214 | // Setup GLSupport |
---|
215 | mGLSupport->initialiseExtensions(); |
---|
216 | |
---|
217 | LogManager::getSingleton().logMessage("***************************"); |
---|
218 | LogManager::getSingleton().logMessage("*** GL Renderer Started ***"); |
---|
219 | LogManager::getSingleton().logMessage("***************************"); |
---|
220 | |
---|
221 | // Get extension function pointers |
---|
222 | glewContextInit(mGLSupport); |
---|
223 | |
---|
224 | // Check for hardware mipmapping support. |
---|
225 | if(GLEW_VERSION_1_4 || GLEW_SGIS_generate_mipmap) |
---|
226 | { |
---|
227 | mCapabilities->setCapability(RSC_AUTOMIPMAP); |
---|
228 | } |
---|
229 | |
---|
230 | // Check for blending support |
---|
231 | if(GLEW_VERSION_1_3 || |
---|
232 | GLEW_ARB_texture_env_combine || |
---|
233 | GLEW_EXT_texture_env_combine) |
---|
234 | { |
---|
235 | mCapabilities->setCapability(RSC_BLENDING); |
---|
236 | } |
---|
237 | |
---|
238 | // Check for Multitexturing support and set number of texture units |
---|
239 | if(GLEW_VERSION_1_3 || |
---|
240 | GLEW_ARB_multitexture) |
---|
241 | { |
---|
242 | GLint units; |
---|
243 | glGetIntegerv( GL_MAX_TEXTURE_UNITS, &units ); |
---|
244 | mFixedFunctionTextureUnits = units; |
---|
245 | |
---|
246 | if (GLEW_ARB_fragment_program) |
---|
247 | { |
---|
248 | // Also check GL_MAX_TEXTURE_IMAGE_UNITS_ARB since NV at least |
---|
249 | // only increased this on the FX/6x00 series |
---|
250 | GLint arbUnits; |
---|
251 | glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &arbUnits ); |
---|
252 | if (arbUnits > units) |
---|
253 | units = arbUnits; |
---|
254 | } |
---|
255 | |
---|
256 | mCapabilities->setNumTextureUnits(units); |
---|
257 | |
---|
258 | } |
---|
259 | else |
---|
260 | { |
---|
261 | // If no multitexture support then set one texture unit |
---|
262 | mCapabilities->setNumTextureUnits(1); |
---|
263 | } |
---|
264 | |
---|
265 | // Check for Anisotropy support |
---|
266 | if(GLEW_EXT_texture_filter_anisotropic) |
---|
267 | { |
---|
268 | mCapabilities->setCapability(RSC_ANISOTROPY); |
---|
269 | } |
---|
270 | |
---|
271 | // Check for DOT3 support |
---|
272 | if(GLEW_VERSION_1_3 || |
---|
273 | GLEW_ARB_texture_env_dot3 || |
---|
274 | GLEW_EXT_texture_env_dot3) |
---|
275 | { |
---|
276 | mCapabilities->setCapability(RSC_DOT3); |
---|
277 | } |
---|
278 | |
---|
279 | // Check for cube mapping |
---|
280 | if(GLEW_VERSION_1_3 || |
---|
281 | GLEW_ARB_texture_cube_map || |
---|
282 | GLEW_EXT_texture_cube_map) |
---|
283 | { |
---|
284 | mCapabilities->setCapability(RSC_CUBEMAPPING); |
---|
285 | } |
---|
286 | |
---|
287 | |
---|
288 | // Point sprites |
---|
289 | if (GLEW_VERSION_2_0 || |
---|
290 | GLEW_ARB_point_sprite) |
---|
291 | { |
---|
292 | mCapabilities->setCapability(RSC_POINT_SPRITES); |
---|
293 | } |
---|
294 | // Check for point parameters |
---|
295 | if(GLEW_VERSION_1_4 || |
---|
296 | GLEW_ARB_point_parameters || |
---|
297 | GLEW_EXT_point_parameters) |
---|
298 | { |
---|
299 | mCapabilities->setCapability(RSC_POINT_EXTENDED_PARAMETERS); |
---|
300 | } |
---|
301 | |
---|
302 | // Check for hardware stencil support and set bit depth |
---|
303 | GLint stencil; |
---|
304 | glGetIntegerv(GL_STENCIL_BITS,&stencil); |
---|
305 | |
---|
306 | if(stencil) |
---|
307 | { |
---|
308 | mCapabilities->setCapability(RSC_HWSTENCIL); |
---|
309 | mCapabilities->setStencilBufferBitDepth(stencil); |
---|
310 | } |
---|
311 | |
---|
312 | // Check for VBO support |
---|
313 | if(GLEW_VERSION_1_5 || GLEW_ARB_vertex_buffer_object) |
---|
314 | { |
---|
315 | // Some buggy driver claim that it is GL 1.5 compliant and |
---|
316 | // not support ARB_vertex_buffer_object |
---|
317 | if (!GLEW_ARB_vertex_buffer_object) |
---|
318 | { |
---|
319 | // Assign ARB functions same to GL 1.5 version since |
---|
320 | // interface identical |
---|
321 | glBindBufferARB = glBindBuffer; |
---|
322 | glBufferDataARB = glBufferData; |
---|
323 | glBufferSubDataARB = glBufferSubData; |
---|
324 | glDeleteBuffersARB = glDeleteBuffers; |
---|
325 | glGenBuffersARB = glGenBuffers; |
---|
326 | glGetBufferParameterivARB = glGetBufferParameteriv; |
---|
327 | glGetBufferPointervARB = glGetBufferPointerv; |
---|
328 | glGetBufferSubDataARB = glGetBufferSubData; |
---|
329 | glIsBufferARB = glIsBuffer; |
---|
330 | glMapBufferARB = glMapBuffer; |
---|
331 | glUnmapBufferARB = glUnmapBuffer; |
---|
332 | } |
---|
333 | |
---|
334 | mCapabilities->setCapability(RSC_VBO); |
---|
335 | |
---|
336 | mHardwareBufferManager = new GLHardwareBufferManager; |
---|
337 | } |
---|
338 | else |
---|
339 | { |
---|
340 | mHardwareBufferManager = new GLDefaultHardwareBufferManager; |
---|
341 | } |
---|
342 | |
---|
343 | // XXX Need to check for nv2 support and make a program manager for it |
---|
344 | // XXX Probably nv1 as well for older cards |
---|
345 | // GPU Program Manager setup |
---|
346 | mGpuProgramManager = new GLGpuProgramManager(); |
---|
347 | |
---|
348 | if(GLEW_ARB_vertex_program) |
---|
349 | { |
---|
350 | mCapabilities->setCapability(RSC_VERTEX_PROGRAM); |
---|
351 | |
---|
352 | // Vertex Program Properties |
---|
353 | mCapabilities->setMaxVertexProgramVersion("arbvp1"); |
---|
354 | mCapabilities->setVertexProgramConstantBoolCount(0); |
---|
355 | mCapabilities->setVertexProgramConstantIntCount(0); |
---|
356 | |
---|
357 | GLint floatConstantCount; |
---|
358 | glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &floatConstantCount); |
---|
359 | mCapabilities->setVertexProgramConstantFloatCount(floatConstantCount); |
---|
360 | |
---|
361 | mGpuProgramManager->_pushSyntaxCode("arbvp1"); |
---|
362 | mGpuProgramManager->registerProgramFactory("arbvp1", createGLArbGpuProgram); |
---|
363 | if (GLEW_NV_vertex_program2_option) |
---|
364 | { |
---|
365 | mCapabilities->setMaxVertexProgramVersion("vp30"); |
---|
366 | mGpuProgramManager->_pushSyntaxCode("vp30"); |
---|
367 | mGpuProgramManager->registerProgramFactory("vp30", createGLArbGpuProgram); |
---|
368 | } |
---|
369 | |
---|
370 | if (GLEW_NV_vertex_program3) |
---|
371 | { |
---|
372 | mCapabilities->setMaxVertexProgramVersion("vp40"); |
---|
373 | mGpuProgramManager->_pushSyntaxCode("vp40"); |
---|
374 | mGpuProgramManager->registerProgramFactory("vp40", createGLArbGpuProgram); |
---|
375 | } |
---|
376 | } |
---|
377 | |
---|
378 | if (GLEW_NV_register_combiners2 && |
---|
379 | GLEW_NV_texture_shader) |
---|
380 | { |
---|
381 | mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM); |
---|
382 | mCapabilities->setMaxFragmentProgramVersion("fp20"); |
---|
383 | |
---|
384 | mGpuProgramManager->_pushSyntaxCode("fp20"); |
---|
385 | mGpuProgramManager->registerProgramFactory("fp20", createGLGpuNvparseProgram); |
---|
386 | } |
---|
387 | |
---|
388 | // NFZ - check for ATI fragment shader support |
---|
389 | if (GLEW_ATI_fragment_shader) |
---|
390 | { |
---|
391 | mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM); |
---|
392 | mCapabilities->setMaxFragmentProgramVersion("ps_1_4"); |
---|
393 | // no boolean params allowed |
---|
394 | mCapabilities->setFragmentProgramConstantBoolCount(0); |
---|
395 | // no integer params allowed |
---|
396 | mCapabilities->setFragmentProgramConstantIntCount(0); |
---|
397 | |
---|
398 | // only 8 Vector4 constant floats supported |
---|
399 | mCapabilities->setFragmentProgramConstantFloatCount(8); |
---|
400 | |
---|
401 | mGpuProgramManager->_pushSyntaxCode("ps_1_4"); |
---|
402 | mGpuProgramManager->_pushSyntaxCode("ps_1_3"); |
---|
403 | mGpuProgramManager->_pushSyntaxCode("ps_1_2"); |
---|
404 | mGpuProgramManager->_pushSyntaxCode("ps_1_1"); |
---|
405 | |
---|
406 | mGpuProgramManager->registerProgramFactory("ps_1_4", createGL_ATI_FS_GpuProgram); |
---|
407 | mGpuProgramManager->registerProgramFactory("ps_1_3", createGL_ATI_FS_GpuProgram); |
---|
408 | mGpuProgramManager->registerProgramFactory("ps_1_2", createGL_ATI_FS_GpuProgram); |
---|
409 | mGpuProgramManager->registerProgramFactory("ps_1_1", createGL_ATI_FS_GpuProgram); |
---|
410 | } |
---|
411 | |
---|
412 | if (GLEW_ARB_fragment_program) |
---|
413 | { |
---|
414 | mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM); |
---|
415 | |
---|
416 | // Fragment Program Properties |
---|
417 | mCapabilities->setMaxFragmentProgramVersion("arbfp1"); |
---|
418 | mCapabilities->setFragmentProgramConstantBoolCount(0); |
---|
419 | mCapabilities->setFragmentProgramConstantIntCount(0); |
---|
420 | |
---|
421 | GLint floatConstantCount; |
---|
422 | glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &floatConstantCount); |
---|
423 | mCapabilities->setFragmentProgramConstantFloatCount(floatConstantCount); |
---|
424 | |
---|
425 | mGpuProgramManager->_pushSyntaxCode("arbfp1"); |
---|
426 | mGpuProgramManager->registerProgramFactory("arbfp1", createGLArbGpuProgram); |
---|
427 | if (GLEW_NV_fragment_program_option) |
---|
428 | { |
---|
429 | mCapabilities->setMaxFragmentProgramVersion("fp30"); |
---|
430 | mGpuProgramManager->_pushSyntaxCode("fp30"); |
---|
431 | mGpuProgramManager->registerProgramFactory("fp30", createGLArbGpuProgram); |
---|
432 | } |
---|
433 | |
---|
434 | if (GLEW_NV_fragment_program2) |
---|
435 | { |
---|
436 | mCapabilities->setMaxFragmentProgramVersion("fp40"); |
---|
437 | mGpuProgramManager->_pushSyntaxCode("fp40"); |
---|
438 | mGpuProgramManager->registerProgramFactory("fp40", createGLArbGpuProgram); |
---|
439 | } |
---|
440 | } |
---|
441 | |
---|
442 | // NFZ - Check if GLSL is supported |
---|
443 | if ( GLEW_VERSION_2_0 || |
---|
444 | (GLEW_ARB_shading_language_100 && |
---|
445 | GLEW_ARB_shader_objects && |
---|
446 | GLEW_ARB_fragment_shader && |
---|
447 | GLEW_ARB_vertex_shader) ) |
---|
448 | { |
---|
449 | // NFZ - check for GLSL vertex and fragment shader support successful |
---|
450 | mGLSLProgramFactory = new GLSLProgramFactory(); |
---|
451 | HighLevelGpuProgramManager::getSingleton().addFactory(mGLSLProgramFactory); |
---|
452 | mGpuProgramManager->_pushSyntaxCode("glsl"); |
---|
453 | LogManager::getSingleton().logMessage("GLSL support detected"); |
---|
454 | } |
---|
455 | |
---|
456 | // Check for texture compression |
---|
457 | if(GLEW_VERSION_1_3 || GLEW_ARB_texture_compression) |
---|
458 | { |
---|
459 | mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION); |
---|
460 | |
---|
461 | // Check for dxt compression |
---|
462 | if(GLEW_EXT_texture_compression_s3tc) |
---|
463 | { |
---|
464 | mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT); |
---|
465 | } |
---|
466 | // Check for vtc compression |
---|
467 | if(GLEW_NV_texture_compression_vtc) |
---|
468 | { |
---|
469 | mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_VTC); |
---|
470 | } |
---|
471 | } |
---|
472 | |
---|
473 | // Scissor test is standard in GL 1.2 (is it emulated on some cards though?) |
---|
474 | mCapabilities->setCapability(RSC_SCISSOR_TEST); |
---|
475 | // As are user clipping planes |
---|
476 | mCapabilities->setCapability(RSC_USER_CLIP_PLANES); |
---|
477 | |
---|
478 | // 2-sided stencil? |
---|
479 | if (GLEW_VERSION_2_0 || GLEW_EXT_stencil_two_side) |
---|
480 | { |
---|
481 | mCapabilities->setCapability(RSC_TWO_SIDED_STENCIL); |
---|
482 | } |
---|
483 | // stencil wrapping? |
---|
484 | if (GLEW_VERSION_1_4 || GLEW_EXT_stencil_wrap) |
---|
485 | { |
---|
486 | mCapabilities->setCapability(RSC_STENCIL_WRAP); |
---|
487 | } |
---|
488 | |
---|
489 | // Check for hardware occlusion support |
---|
490 | if(GLEW_VERSION_1_5 || GLEW_ARB_occlusion_query) |
---|
491 | { |
---|
492 | // Some buggy driver claim that it is GL 1.5 compliant and |
---|
493 | // not support ARB_occlusion_query |
---|
494 | if (!GLEW_ARB_occlusion_query) |
---|
495 | { |
---|
496 | // Assign ARB functions same to GL 1.5 version since |
---|
497 | // interface identical |
---|
498 | glBeginQueryARB = glBeginQuery; |
---|
499 | glDeleteQueriesARB = glDeleteQueries; |
---|
500 | glEndQueryARB = glEndQuery; |
---|
501 | glGenQueriesARB = glGenQueries; |
---|
502 | glGetQueryObjectivARB = glGetQueryObjectiv; |
---|
503 | glGetQueryObjectuivARB = glGetQueryObjectuiv; |
---|
504 | glGetQueryivARB = glGetQueryiv; |
---|
505 | glIsQueryARB = glIsQuery; |
---|
506 | } |
---|
507 | |
---|
508 | mCapabilities->setCapability(RSC_HWOCCLUSION); |
---|
509 | } |
---|
510 | else if (GLEW_NV_occlusion_query) |
---|
511 | { |
---|
512 | // Support NV extension too for old hardware |
---|
513 | mCapabilities->setCapability(RSC_HWOCCLUSION); |
---|
514 | } |
---|
515 | |
---|
516 | // UBYTE4 always supported |
---|
517 | mCapabilities->setCapability(RSC_VERTEX_FORMAT_UBYTE4); |
---|
518 | |
---|
519 | // Inifinite far plane always supported |
---|
520 | mCapabilities->setCapability(RSC_INFINITE_FAR_PLANE); |
---|
521 | |
---|
522 | // Check for non-power-of-2 texture support |
---|
523 | if(GLEW_ARB_texture_non_power_of_two) |
---|
524 | { |
---|
525 | mCapabilities->setCapability(RSC_NON_POWER_OF_2_TEXTURES); |
---|
526 | } |
---|
527 | |
---|
528 | // Check for Float textures |
---|
529 | if(GLEW_ATI_texture_float || GLEW_ARB_texture_float) |
---|
530 | { |
---|
531 | mCapabilities->setCapability(RSC_TEXTURE_FLOAT); |
---|
532 | } |
---|
533 | |
---|
534 | // 3D textures should be supported by GL 1.2, which is our minimum version |
---|
535 | mCapabilities->setCapability(RSC_TEXTURE_3D); |
---|
536 | |
---|
537 | /// Do this after extension function pointers are initialised as the extension |
---|
538 | /// is used to probe further capabilities. |
---|
539 | ConfigOptionMap::iterator cfi = getConfigOptions().find("RTT Preferred Mode"); |
---|
540 | // RTT Mode: 0 use whatever available, 1 use PBuffers, 2 force use copying |
---|
541 | int rttMode = 0; |
---|
542 | if (cfi != getConfigOptions().end()) |
---|
543 | { |
---|
544 | if (cfi->second.currentValue == "PBuffer") |
---|
545 | { |
---|
546 | rttMode = 1; |
---|
547 | } |
---|
548 | else if (cfi->second.currentValue == "Copy") |
---|
549 | { |
---|
550 | rttMode = 2; |
---|
551 | } |
---|
552 | } |
---|
553 | // Check for framebuffer object extension |
---|
554 | if(GLEW_EXT_framebuffer_object && rttMode < 1) |
---|
555 | { |
---|
556 | // Probe number of draw buffers |
---|
557 | // Only makes sense with FBO support, so probe here |
---|
558 | if(GLEW_VERSION_2_0 || |
---|
559 | GLEW_ARB_draw_buffers || |
---|
560 | GLEW_ATI_draw_buffers) |
---|
561 | { |
---|
562 | GLint buffers; |
---|
563 | glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &buffers); |
---|
564 | mCapabilities->setNumMultiRenderTargets(std::min(buffers, OGRE_MAX_MULTIPLE_RENDER_TARGETS)); |
---|
565 | if(!GLEW_VERSION_2_0) |
---|
566 | { |
---|
567 | // Before GL version 2.0, we need to get one of the extensions |
---|
568 | if(GLEW_ARB_draw_buffers) |
---|
569 | __glewDrawBuffers = glDrawBuffersARB; |
---|
570 | else if(GLEW_ATI_draw_buffers) |
---|
571 | __glewDrawBuffers = glDrawBuffersATI; |
---|
572 | } |
---|
573 | } |
---|
574 | // Create FBO manager |
---|
575 | LogManager::getSingleton().logMessage("GL: Using GL_EXT_framebuffer_object for rendering to textures (best)"); |
---|
576 | //mRTTManager = new GLFBOManager(mGLSupport->getGLVendor() == "ATI"); |
---|
577 | mRTTManager = new GLFBOManager(false); |
---|
578 | mCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE); |
---|
579 | } |
---|
580 | else |
---|
581 | { |
---|
582 | // Check GLSupport for PBuffer support |
---|
583 | if(mGLSupport->supportsPBuffers() && rttMode < 2) |
---|
584 | { |
---|
585 | // Use PBuffers |
---|
586 | mRTTManager = new GLPBRTTManager(mGLSupport, primary); |
---|
587 | LogManager::getSingleton().logMessage("GL: Using PBuffers for rendering to textures"); |
---|
588 | mCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE); |
---|
589 | } |
---|
590 | else |
---|
591 | { |
---|
592 | // No pbuffer support either -- fallback to simplest copying from framebuffer |
---|
593 | mRTTManager = new GLCopyingRTTManager(); |
---|
594 | LogManager::getSingleton().logMessage("GL: Using framebuffer copy for rendering to textures (worst)"); |
---|
595 | LogManager::getSingleton().logMessage("GL: Warning: RenderTexture size is restricted to size of framebuffer. If you are on Linux, consider using GLX instead of SDL."); |
---|
596 | } |
---|
597 | } |
---|
598 | |
---|
599 | // Point size |
---|
600 | float ps; |
---|
601 | glGetFloatv(GL_POINT_SIZE_MAX, &ps); |
---|
602 | mCapabilities->setMaxPointSize(ps); |
---|
603 | |
---|
604 | // Vertex texture fetching |
---|
605 | GLint vUnits; |
---|
606 | glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &vUnits); |
---|
607 | mCapabilities->setNumVertexTextureUnits(static_cast<ushort>(vUnits)); |
---|
608 | if (vUnits > 0) |
---|
609 | { |
---|
610 | mCapabilities->setCapability(RSC_VERTEX_TEXTURE_FETCH); |
---|
611 | } |
---|
612 | // GL always shares vertex and fragment texture units (for now?) |
---|
613 | mCapabilities->setVertexTextureUnitsShared(true); |
---|
614 | |
---|
615 | // Mipmap LOD biasing? |
---|
616 | if (GLEW_VERSION_1_4 || GLEW_EXT_texture_lod_bias) |
---|
617 | { |
---|
618 | mCapabilities->setCapability(RSC_MIPMAP_LOD_BIAS); |
---|
619 | } |
---|
620 | |
---|
621 | |
---|
622 | Log* defaultLog = LogManager::getSingleton().getDefaultLog(); |
---|
623 | if (defaultLog) |
---|
624 | { |
---|
625 | mCapabilities->log(defaultLog); |
---|
626 | } |
---|
627 | |
---|
628 | /// Create the texture manager |
---|
629 | mTextureManager = new GLTextureManager(*mGLSupport); |
---|
630 | |
---|
631 | mGLInitialized = true; |
---|
632 | } |
---|
633 | |
---|
634 | void GLRenderSystem::reinitialise(void) |
---|
635 | { |
---|
636 | this->shutdown(); |
---|
637 | this->initialise(true); |
---|
638 | } |
---|
639 | |
---|
640 | void GLRenderSystem::shutdown(void) |
---|
641 | { |
---|
642 | RenderSystem::shutdown(); |
---|
643 | |
---|
644 | // Deleting the GLSL program factory |
---|
645 | if (mGLSLProgramFactory) |
---|
646 | { |
---|
647 | // Remove from manager safely |
---|
648 | if (HighLevelGpuProgramManager::getSingletonPtr()) |
---|
649 | HighLevelGpuProgramManager::getSingleton().removeFactory(mGLSLProgramFactory); |
---|
650 | delete mGLSLProgramFactory; |
---|
651 | mGLSLProgramFactory = 0; |
---|
652 | } |
---|
653 | |
---|
654 | // Deleting the GPU program manager and hardware buffer manager. Has to be done before the mGLSupport->stop(). |
---|
655 | delete mGpuProgramManager; |
---|
656 | mGpuProgramManager = 0; |
---|
657 | |
---|
658 | delete mHardwareBufferManager; |
---|
659 | mHardwareBufferManager = 0; |
---|
660 | |
---|
661 | delete mRTTManager; |
---|
662 | mRTTManager = 0; |
---|
663 | |
---|
664 | // Delete extra threads contexts |
---|
665 | for (GLContextList::iterator i = mBackgroundContextList.begin(); |
---|
666 | i != mBackgroundContextList.end(); ++i) |
---|
667 | { |
---|
668 | delete *i; |
---|
669 | } |
---|
670 | mBackgroundContextList.clear(); |
---|
671 | |
---|
672 | mGLSupport->stop(); |
---|
673 | mStopRendering = true; |
---|
674 | |
---|
675 | delete mTextureManager; |
---|
676 | mTextureManager = 0; |
---|
677 | |
---|
678 | // There will be a new initial window and so forth, thus any call to test |
---|
679 | // some params will access an invalid pointer, so it is best to reset |
---|
680 | // the whole state. |
---|
681 | mGLInitialized = 0; |
---|
682 | } |
---|
683 | |
---|
684 | void GLRenderSystem::setAmbientLight(float r, float g, float b) |
---|
685 | { |
---|
686 | GLfloat lmodel_ambient[] = {r, g, b, 1.0}; |
---|
687 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); |
---|
688 | } |
---|
689 | |
---|
690 | void GLRenderSystem::setShadingType(ShadeOptions so) |
---|
691 | { |
---|
692 | switch(so) |
---|
693 | { |
---|
694 | case SO_FLAT: |
---|
695 | glShadeModel(GL_FLAT); |
---|
696 | break; |
---|
697 | default: |
---|
698 | glShadeModel(GL_SMOOTH); |
---|
699 | break; |
---|
700 | } |
---|
701 | } |
---|
702 | |
---|
703 | RenderWindow* GLRenderSystem::createRenderWindow(const String &name, |
---|
704 | unsigned int width, unsigned int height, bool fullScreen, |
---|
705 | const NameValuePairList *miscParams) |
---|
706 | { |
---|
707 | if (mRenderTargets.find(name) != mRenderTargets.end()) |
---|
708 | { |
---|
709 | OGRE_EXCEPT( |
---|
710 | Exception::ERR_INVALIDPARAMS, |
---|
711 | "Window with name '" + name + "' already exists", |
---|
712 | "GLRenderSystem::createRenderWindow" ); |
---|
713 | } |
---|
714 | // Log a message |
---|
715 | std::stringstream ss; |
---|
716 | ss << "GLRenderSystem::createRenderWindow \"" << name << "\", " << |
---|
717 | width << "x" << height << " "; |
---|
718 | if(fullScreen) |
---|
719 | ss << "fullscreen "; |
---|
720 | else |
---|
721 | ss << "windowed "; |
---|
722 | if(miscParams) |
---|
723 | { |
---|
724 | ss << " miscParams: "; |
---|
725 | NameValuePairList::const_iterator it; |
---|
726 | for(it=miscParams->begin(); it!=miscParams->end(); ++it) |
---|
727 | { |
---|
728 | ss << it->first << "=" << it->second << " "; |
---|
729 | } |
---|
730 | LogManager::getSingleton().logMessage(ss.str()); |
---|
731 | } |
---|
732 | |
---|
733 | // Create the window |
---|
734 | RenderWindow* win = mGLSupport->newWindow(name, width, height, |
---|
735 | fullScreen, miscParams); |
---|
736 | |
---|
737 | attachRenderTarget( *win ); |
---|
738 | |
---|
739 | if (!mGLInitialized) |
---|
740 | { |
---|
741 | // Initialise GL after the first window has been created |
---|
742 | initGL(win); |
---|
743 | |
---|
744 | // Initialise the main context |
---|
745 | _oneTimeContextInitialization(); |
---|
746 | if(mCurrentContext) |
---|
747 | mCurrentContext->setInitialized(); |
---|
748 | } |
---|
749 | |
---|
750 | return win; |
---|
751 | } |
---|
752 | |
---|
753 | //----------------------------------------------------------------------- |
---|
754 | MultiRenderTarget * GLRenderSystem::createMultiRenderTarget(const String & name) |
---|
755 | { |
---|
756 | MultiRenderTarget *retval = mRTTManager->createMultiRenderTarget(name); |
---|
757 | attachRenderTarget( *retval ); |
---|
758 | return retval; |
---|
759 | } |
---|
760 | |
---|
761 | //----------------------------------------------------------------------- |
---|
762 | void GLRenderSystem::destroyRenderWindow(RenderWindow* pWin) |
---|
763 | { |
---|
764 | // Find it to remove from list |
---|
765 | RenderTargetMap::iterator i = mRenderTargets.begin(); |
---|
766 | |
---|
767 | while (i != mRenderTargets.end()) |
---|
768 | { |
---|
769 | if (i->second == pWin) |
---|
770 | { |
---|
771 | mRenderTargets.erase(i); |
---|
772 | delete pWin; |
---|
773 | break; |
---|
774 | } |
---|
775 | } |
---|
776 | } |
---|
777 | |
---|
778 | //--------------------------------------------------------------------- |
---|
779 | void GLRenderSystem::_useLights(const LightList& lights, unsigned short limit) |
---|
780 | { |
---|
781 | // Save previous modelview |
---|
782 | glMatrixMode(GL_MODELVIEW); |
---|
783 | glPushMatrix(); |
---|
784 | // just load view matrix (identity world) |
---|
785 | GLfloat mat[16]; |
---|
786 | makeGLMatrix(mat, mViewMatrix); |
---|
787 | glLoadMatrixf(mat); |
---|
788 | |
---|
789 | LightList::const_iterator i, iend; |
---|
790 | iend = lights.end(); |
---|
791 | unsigned short num = 0; |
---|
792 | for (i = lights.begin(); i != iend && num < limit; ++i, ++num) |
---|
793 | { |
---|
794 | setGLLight(num, *i); |
---|
795 | mLights[num] = *i; |
---|
796 | } |
---|
797 | // Disable extra lights |
---|
798 | for (; num < mCurrentLights; ++num) |
---|
799 | { |
---|
800 | setGLLight(num, NULL); |
---|
801 | mLights[num] = NULL; |
---|
802 | } |
---|
803 | mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size())); |
---|
804 | |
---|
805 | setLights(); |
---|
806 | |
---|
807 | // restore previous |
---|
808 | glPopMatrix(); |
---|
809 | |
---|
810 | } |
---|
811 | |
---|
812 | void GLRenderSystem::setGLLight(size_t index, Light* lt) |
---|
813 | { |
---|
814 | GLenum gl_index = GL_LIGHT0 + index; |
---|
815 | |
---|
816 | if (!lt) |
---|
817 | { |
---|
818 | // Disable in the scene |
---|
819 | glDisable(gl_index); |
---|
820 | } |
---|
821 | else |
---|
822 | { |
---|
823 | switch (lt->getType()) |
---|
824 | { |
---|
825 | case Light::LT_SPOTLIGHT: |
---|
826 | glLightf( gl_index, GL_SPOT_CUTOFF, 0.5f * lt->getSpotlightOuterAngle().valueDegrees() ); |
---|
827 | glLightf(gl_index, GL_SPOT_EXPONENT, lt->getSpotlightFalloff()); |
---|
828 | break; |
---|
829 | default: |
---|
830 | glLightf( gl_index, GL_SPOT_CUTOFF, 180.0 ); |
---|
831 | break; |
---|
832 | } |
---|
833 | |
---|
834 | // Color |
---|
835 | ColourValue col; |
---|
836 | col = lt->getDiffuseColour(); |
---|
837 | |
---|
838 | |
---|
839 | GLfloat f4vals[4] = {col.r, col.g, col.b, col.a}; |
---|
840 | glLightfv(gl_index, GL_DIFFUSE, f4vals); |
---|
841 | |
---|
842 | col = lt->getSpecularColour(); |
---|
843 | f4vals[0] = col.r; |
---|
844 | f4vals[1] = col.g; |
---|
845 | f4vals[2] = col.b; |
---|
846 | f4vals[3] = col.a; |
---|
847 | glLightfv(gl_index, GL_SPECULAR, f4vals); |
---|
848 | |
---|
849 | |
---|
850 | // Disable ambient light for movables; |
---|
851 | f4vals[0] = 0; |
---|
852 | f4vals[1] = 0; |
---|
853 | f4vals[2] = 0; |
---|
854 | f4vals[3] = 1; |
---|
855 | glLightfv(gl_index, GL_AMBIENT, f4vals); |
---|
856 | |
---|
857 | setGLLightPositionDirection(lt, gl_index); |
---|
858 | |
---|
859 | |
---|
860 | // Attenuation |
---|
861 | glLightf(gl_index, GL_CONSTANT_ATTENUATION, lt->getAttenuationConstant()); |
---|
862 | glLightf(gl_index, GL_LINEAR_ATTENUATION, lt->getAttenuationLinear()); |
---|
863 | glLightf(gl_index, GL_QUADRATIC_ATTENUATION, lt->getAttenuationQuadric()); |
---|
864 | // Enable in the scene |
---|
865 | glEnable(gl_index); |
---|
866 | |
---|
867 | } |
---|
868 | |
---|
869 | } |
---|
870 | |
---|
871 | //----------------------------------------------------------------------------- |
---|
872 | void GLRenderSystem::makeGLMatrix(GLfloat gl_matrix[16], const Matrix4& m) |
---|
873 | { |
---|
874 | size_t x = 0; |
---|
875 | for (size_t i = 0; i < 4; i++) |
---|
876 | { |
---|
877 | for (size_t j = 0; j < 4; j++) |
---|
878 | { |
---|
879 | gl_matrix[x] = m[j][i]; |
---|
880 | x++; |
---|
881 | } |
---|
882 | } |
---|
883 | } |
---|
884 | //----------------------------------------------------------------------------- |
---|
885 | void GLRenderSystem::_setWorldMatrix( const Matrix4 &m ) |
---|
886 | { |
---|
887 | GLfloat mat[16]; |
---|
888 | mWorldMatrix = m; |
---|
889 | makeGLMatrix( mat, mViewMatrix * mWorldMatrix ); |
---|
890 | glMatrixMode(GL_MODELVIEW); |
---|
891 | glLoadMatrixf(mat); |
---|
892 | } |
---|
893 | |
---|
894 | //----------------------------------------------------------------------------- |
---|
895 | void GLRenderSystem::_setViewMatrix( const Matrix4 &m ) |
---|
896 | { |
---|
897 | mViewMatrix = m; |
---|
898 | |
---|
899 | GLfloat mat[16]; |
---|
900 | makeGLMatrix( mat, mViewMatrix * mWorldMatrix ); |
---|
901 | glMatrixMode(GL_MODELVIEW); |
---|
902 | glLoadMatrixf(mat); |
---|
903 | |
---|
904 | setGLClipPlanes(); |
---|
905 | } |
---|
906 | //----------------------------------------------------------------------------- |
---|
907 | void GLRenderSystem::_setProjectionMatrix(const Matrix4 &m) |
---|
908 | { |
---|
909 | GLfloat mat[16]; |
---|
910 | makeGLMatrix(mat, m); |
---|
911 | if (mActiveRenderTarget->requiresTextureFlipping()) |
---|
912 | { |
---|
913 | // Invert transformed y |
---|
914 | mat[1] = -mat[1]; |
---|
915 | mat[5] = -mat[5]; |
---|
916 | mat[9] = -mat[9]; |
---|
917 | mat[13] = -mat[13]; |
---|
918 | } |
---|
919 | glMatrixMode(GL_PROJECTION); |
---|
920 | glLoadMatrixf(mat); |
---|
921 | glMatrixMode(GL_MODELVIEW); |
---|
922 | } |
---|
923 | //----------------------------------------------------------------------------- |
---|
924 | void GLRenderSystem::_setSurfaceParams(const ColourValue &ambient, |
---|
925 | const ColourValue &diffuse, const ColourValue &specular, |
---|
926 | const ColourValue &emissive, Real shininess, |
---|
927 | TrackVertexColourType tracking) |
---|
928 | { |
---|
929 | |
---|
930 | // Track vertex colour |
---|
931 | if(tracking != TVC_NONE) |
---|
932 | { |
---|
933 | GLenum gt = GL_DIFFUSE; |
---|
934 | // There are actually 15 different combinations for tracking, of which |
---|
935 | // GL only supports the most used 5. This means that we have to do some |
---|
936 | // magic to find the best match. NOTE: |
---|
937 | // GL_AMBIENT_AND_DIFFUSE != GL_AMBIENT | GL__DIFFUSE |
---|
938 | if(tracking & TVC_AMBIENT) |
---|
939 | { |
---|
940 | if(tracking & TVC_DIFFUSE) |
---|
941 | { |
---|
942 | gt = GL_AMBIENT_AND_DIFFUSE; |
---|
943 | } |
---|
944 | else |
---|
945 | { |
---|
946 | gt = GL_AMBIENT; |
---|
947 | } |
---|
948 | } |
---|
949 | else if(tracking & TVC_DIFFUSE) |
---|
950 | { |
---|
951 | gt = GL_DIFFUSE; |
---|
952 | } |
---|
953 | else if(tracking & TVC_SPECULAR) |
---|
954 | { |
---|
955 | gt = GL_SPECULAR; |
---|
956 | } |
---|
957 | else if(tracking & TVC_EMISSIVE) |
---|
958 | { |
---|
959 | gt = GL_EMISSION; |
---|
960 | } |
---|
961 | glColorMaterial(GL_FRONT_AND_BACK, gt); |
---|
962 | |
---|
963 | glEnable(GL_COLOR_MATERIAL); |
---|
964 | } |
---|
965 | else |
---|
966 | { |
---|
967 | glDisable(GL_COLOR_MATERIAL); |
---|
968 | } |
---|
969 | |
---|
970 | // XXX Cache previous values? |
---|
971 | // XXX Front or Front and Back? |
---|
972 | |
---|
973 | GLfloat f4val[4] = {diffuse.r, diffuse.g, diffuse.b, diffuse.a}; |
---|
974 | glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, f4val); |
---|
975 | f4val[0] = ambient.r; |
---|
976 | f4val[1] = ambient.g; |
---|
977 | f4val[2] = ambient.b; |
---|
978 | f4val[3] = ambient.a; |
---|
979 | glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, f4val); |
---|
980 | f4val[0] = specular.r; |
---|
981 | f4val[1] = specular.g; |
---|
982 | f4val[2] = specular.b; |
---|
983 | f4val[3] = specular.a; |
---|
984 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, f4val); |
---|
985 | f4val[0] = emissive.r; |
---|
986 | f4val[1] = emissive.g; |
---|
987 | f4val[2] = emissive.b; |
---|
988 | f4val[3] = emissive.a; |
---|
989 | glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, f4val); |
---|
990 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); |
---|
991 | } |
---|
992 | //----------------------------------------------------------------------------- |
---|
993 | void GLRenderSystem::_setPointParameters(Real size, |
---|
994 | bool attenuationEnabled, Real constant, Real linear, Real quadratic, |
---|
995 | Real minSize, Real maxSize) |
---|
996 | { |
---|
997 | |
---|
998 | if(attenuationEnabled && |
---|
999 | mCapabilities->hasCapability(RSC_POINT_EXTENDED_PARAMETERS)) |
---|
1000 | { |
---|
1001 | // Point size is still calculated in pixels even when attenuation is |
---|
1002 | // enabled, which is pretty awkward, since you typically want a viewport |
---|
1003 | // independent size if you're looking for attenuation. |
---|
1004 | // So, scale the point size up by viewport size (this is equivalent to |
---|
1005 | // what D3D does as standard) |
---|
1006 | Real adjSize = size * mActiveViewport->getActualHeight(); |
---|
1007 | Real adjMinSize = minSize * mActiveViewport->getActualHeight(); |
---|
1008 | Real adjMaxSize; |
---|
1009 | if (maxSize == 0.0f) |
---|
1010 | adjMaxSize = mCapabilities->getMaxPointSize(); // pixels |
---|
1011 | else |
---|
1012 | adjMaxSize = maxSize * mActiveViewport->getActualHeight(); |
---|
1013 | glPointSize(adjSize); |
---|
1014 | |
---|
1015 | // XXX: why do I need this for results to be consistent with D3D? |
---|
1016 | // Equations are supposedly the same once you factor in vp height |
---|
1017 | Real correction = 0.005; |
---|
1018 | // scaling required |
---|
1019 | float val[4] = {constant, linear*correction, quadratic*correction, 1}; |
---|
1020 | glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val); |
---|
1021 | glPointParameterf(GL_POINT_SIZE_MIN, adjMinSize); |
---|
1022 | glPointParameterf(GL_POINT_SIZE_MAX, adjMaxSize); |
---|
1023 | } |
---|
1024 | else |
---|
1025 | { |
---|
1026 | // no scaling required |
---|
1027 | // GL has no disabled flag for this so just set to constant |
---|
1028 | glPointSize(size); |
---|
1029 | |
---|
1030 | if (mCapabilities->hasCapability(RSC_POINT_EXTENDED_PARAMETERS)) |
---|
1031 | { |
---|
1032 | float val[4] = {1, 0, 0, 1}; |
---|
1033 | glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val); |
---|
1034 | glPointParameterf(GL_POINT_SIZE_MIN, minSize); |
---|
1035 | if (maxSize == 0.0f) |
---|
1036 | maxSize = mCapabilities->getMaxPointSize(); |
---|
1037 | glPointParameterf(GL_POINT_SIZE_MAX, maxSize); |
---|
1038 | } |
---|
1039 | } |
---|
1040 | |
---|
1041 | |
---|
1042 | |
---|
1043 | } |
---|
1044 | //--------------------------------------------------------------------- |
---|
1045 | void GLRenderSystem::_setPointSpritesEnabled(bool enabled) |
---|
1046 | { |
---|
1047 | if (enabled) |
---|
1048 | { |
---|
1049 | glEnable(GL_POINT_SPRITE); |
---|
1050 | } |
---|
1051 | else |
---|
1052 | { |
---|
1053 | glDisable(GL_POINT_SPRITE); |
---|
1054 | } |
---|
1055 | |
---|
1056 | // Set sprite texture coord generation |
---|
1057 | // Don't offer this as an option since D3D links it to sprite enabled |
---|
1058 | for (ushort i = 0; i < mFixedFunctionTextureUnits; ++i) |
---|
1059 | { |
---|
1060 | glActiveTextureARB(GL_TEXTURE0 + i); |
---|
1061 | glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, |
---|
1062 | enabled ? GL_TRUE : GL_FALSE); |
---|
1063 | } |
---|
1064 | glActiveTextureARB(GL_TEXTURE0); |
---|
1065 | |
---|
1066 | } |
---|
1067 | //----------------------------------------------------------------------------- |
---|
1068 | void GLRenderSystem::_setTexture(size_t stage, bool enabled, const TexturePtr &texPtr) |
---|
1069 | { |
---|
1070 | GLTexturePtr tex = texPtr; |
---|
1071 | |
---|
1072 | GLenum lastTextureType = mTextureTypes[stage]; |
---|
1073 | |
---|
1074 | glActiveTextureARB( GL_TEXTURE0 + stage ); |
---|
1075 | if (enabled) |
---|
1076 | { |
---|
1077 | if (!tex.isNull()) |
---|
1078 | { |
---|
1079 | // note used |
---|
1080 | tex->touch(); |
---|
1081 | mTextureTypes[stage] = tex->getGLTextureTarget(); |
---|
1082 | } |
---|
1083 | else |
---|
1084 | // assume 2D |
---|
1085 | mTextureTypes[stage] = GL_TEXTURE_2D; |
---|
1086 | |
---|
1087 | if(lastTextureType != mTextureTypes[stage] && lastTextureType != 0) |
---|
1088 | { |
---|
1089 | if (stage < mFixedFunctionTextureUnits) |
---|
1090 | { |
---|
1091 | glDisable( lastTextureType ); |
---|
1092 | } |
---|
1093 | } |
---|
1094 | |
---|
1095 | if (stage < mFixedFunctionTextureUnits) |
---|
1096 | { |
---|
1097 | glEnable( mTextureTypes[stage] ); |
---|
1098 | } |
---|
1099 | |
---|
1100 | if(!tex.isNull()) |
---|
1101 | glBindTexture( mTextureTypes[stage], tex->getGLID() ); |
---|
1102 | else |
---|
1103 | glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(mTextureManager)->getWarningTextureID() ); |
---|
1104 | } |
---|
1105 | else |
---|
1106 | { |
---|
1107 | if (stage < mFixedFunctionTextureUnits) |
---|
1108 | { |
---|
1109 | if (lastTextureType != 0) |
---|
1110 | { |
---|
1111 | glDisable( mTextureTypes[stage] ); |
---|
1112 | } |
---|
1113 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
---|
1114 | } |
---|
1115 | // bind zero texture |
---|
1116 | glBindTexture (GL_TEXTURE_2D, 0); |
---|
1117 | } |
---|
1118 | |
---|
1119 | glActiveTextureARB( GL_TEXTURE0 ); |
---|
1120 | } |
---|
1121 | |
---|
1122 | //----------------------------------------------------------------------------- |
---|
1123 | void GLRenderSystem::_setTextureCoordSet(size_t stage, size_t index) |
---|
1124 | { |
---|
1125 | mTextureCoordIndex[stage] = index; |
---|
1126 | } |
---|
1127 | //----------------------------------------------------------------------------- |
---|
1128 | void GLRenderSystem::_setTextureCoordCalculation(size_t stage, TexCoordCalcMethod m, |
---|
1129 | const Frustum* frustum) |
---|
1130 | { |
---|
1131 | if (stage >= mFixedFunctionTextureUnits) |
---|
1132 | { |
---|
1133 | // Can't do this |
---|
1134 | return; |
---|
1135 | } |
---|
1136 | |
---|
1137 | |
---|
1138 | GLfloat M[16]; |
---|
1139 | Matrix4 projectionBias; |
---|
1140 | |
---|
1141 | // Default to no extra auto texture matrix |
---|
1142 | mUseAutoTextureMatrix = false; |
---|
1143 | |
---|
1144 | GLfloat eyePlaneS[] = {1.0, 0.0, 0.0, 0.0}; |
---|
1145 | GLfloat eyePlaneT[] = {0.0, 1.0, 0.0, 0.0}; |
---|
1146 | GLfloat eyePlaneR[] = {0.0, 0.0, 1.0, 0.0}; |
---|
1147 | GLfloat eyePlaneQ[] = {0.0, 0.0, 0.0, 1.0}; |
---|
1148 | |
---|
1149 | glActiveTextureARB( GL_TEXTURE0 + stage ); |
---|
1150 | |
---|
1151 | switch( m ) |
---|
1152 | { |
---|
1153 | case TEXCALC_NONE: |
---|
1154 | glDisable( GL_TEXTURE_GEN_S ); |
---|
1155 | glDisable( GL_TEXTURE_GEN_T ); |
---|
1156 | glDisable( GL_TEXTURE_GEN_R ); |
---|
1157 | glDisable( GL_TEXTURE_GEN_Q ); |
---|
1158 | break; |
---|
1159 | |
---|
1160 | case TEXCALC_ENVIRONMENT_MAP: |
---|
1161 | glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ); |
---|
1162 | glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ); |
---|
1163 | |
---|
1164 | glEnable( GL_TEXTURE_GEN_S ); |
---|
1165 | glEnable( GL_TEXTURE_GEN_T ); |
---|
1166 | glDisable( GL_TEXTURE_GEN_R ); |
---|
1167 | glDisable( GL_TEXTURE_GEN_Q ); |
---|
1168 | |
---|
1169 | // Need to use a texture matrix to flip the spheremap |
---|
1170 | mUseAutoTextureMatrix = true; |
---|
1171 | memset(mAutoTextureMatrix, 0, sizeof(GLfloat)*16); |
---|
1172 | mAutoTextureMatrix[0] = mAutoTextureMatrix[10] = mAutoTextureMatrix[15] = 1.0f; |
---|
1173 | mAutoTextureMatrix[5] = -1.0f; |
---|
1174 | |
---|
1175 | break; |
---|
1176 | |
---|
1177 | case TEXCALC_ENVIRONMENT_MAP_PLANAR: |
---|
1178 | // XXX This doesn't seem right?! |
---|
1179 | #ifdef GL_VERSION_1_3 |
---|
1180 | glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); |
---|
1181 | glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); |
---|
1182 | glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); |
---|
1183 | |
---|
1184 | glEnable( GL_TEXTURE_GEN_S ); |
---|
1185 | glEnable( GL_TEXTURE_GEN_T ); |
---|
1186 | glEnable( GL_TEXTURE_GEN_R ); |
---|
1187 | glDisable( GL_TEXTURE_GEN_Q ); |
---|
1188 | #else |
---|
1189 | glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ); |
---|
1190 | glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ); |
---|
1191 | |
---|
1192 | glEnable( GL_TEXTURE_GEN_S ); |
---|
1193 | glEnable( GL_TEXTURE_GEN_T ); |
---|
1194 | glDisable( GL_TEXTURE_GEN_R ); |
---|
1195 | glDisable( GL_TEXTURE_GEN_Q ); |
---|
1196 | #endif |
---|
1197 | break; |
---|
1198 | case TEXCALC_ENVIRONMENT_MAP_REFLECTION: |
---|
1199 | |
---|
1200 | glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); |
---|
1201 | glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); |
---|
1202 | glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); |
---|
1203 | |
---|
1204 | glEnable( GL_TEXTURE_GEN_S ); |
---|
1205 | glEnable( GL_TEXTURE_GEN_T ); |
---|
1206 | glEnable( GL_TEXTURE_GEN_R ); |
---|
1207 | glDisable( GL_TEXTURE_GEN_Q ); |
---|
1208 | |
---|
1209 | // We need an extra texture matrix here |
---|
1210 | // This sets the texture matrix to be the inverse of the view matrix |
---|
1211 | mUseAutoTextureMatrix = true; |
---|
1212 | makeGLMatrix( M, mViewMatrix); |
---|
1213 | |
---|
1214 | // Transpose 3x3 in order to invert matrix (rotation) |
---|
1215 | // Note that we need to invert the Z _before_ the rotation |
---|
1216 | // No idea why we have to invert the Z at all, but reflection is wrong without it |
---|
1217 | mAutoTextureMatrix[0] = M[0]; mAutoTextureMatrix[1] = M[4]; mAutoTextureMatrix[2] = -M[8]; |
---|
1218 | mAutoTextureMatrix[4] = M[1]; mAutoTextureMatrix[5] = M[5]; mAutoTextureMatrix[6] = -M[9]; |
---|
1219 | mAutoTextureMatrix[8] = M[2]; mAutoTextureMatrix[9] = M[6]; mAutoTextureMatrix[10] = -M[10]; |
---|
1220 | mAutoTextureMatrix[3] = mAutoTextureMatrix[7] = mAutoTextureMatrix[11] = 0.0f; |
---|
1221 | mAutoTextureMatrix[12] = mAutoTextureMatrix[13] = mAutoTextureMatrix[14] = 0.0f; |
---|
1222 | mAutoTextureMatrix[15] = 1.0f; |
---|
1223 | |
---|
1224 | break; |
---|
1225 | case TEXCALC_ENVIRONMENT_MAP_NORMAL: |
---|
1226 | glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP ); |
---|
1227 | glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP ); |
---|
1228 | glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP ); |
---|
1229 | |
---|
1230 | glEnable( GL_TEXTURE_GEN_S ); |
---|
1231 | glEnable( GL_TEXTURE_GEN_T ); |
---|
1232 | glEnable( GL_TEXTURE_GEN_R ); |
---|
1233 | glDisable( GL_TEXTURE_GEN_Q ); |
---|
1234 | break; |
---|
1235 | case TEXCALC_PROJECTIVE_TEXTURE: |
---|
1236 | glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
---|
1237 | glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
---|
1238 | glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
---|
1239 | glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
---|
1240 | glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS); |
---|
1241 | glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT); |
---|
1242 | glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR); |
---|
1243 | glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ); |
---|
1244 | glEnable(GL_TEXTURE_GEN_S); |
---|
1245 | glEnable(GL_TEXTURE_GEN_T); |
---|
1246 | glEnable(GL_TEXTURE_GEN_R); |
---|
1247 | glEnable(GL_TEXTURE_GEN_Q); |
---|
1248 | |
---|
1249 | mUseAutoTextureMatrix = true; |
---|
1250 | |
---|
1251 | // Set scale and translation matrix for projective textures |
---|
1252 | projectionBias = Matrix4::CLIPSPACE2DTOIMAGESPACE; |
---|
1253 | |
---|
1254 | projectionBias = projectionBias * frustum->getProjectionMatrix(); |
---|
1255 | projectionBias = projectionBias * frustum->getViewMatrix(); |
---|
1256 | projectionBias = projectionBias * mWorldMatrix; |
---|
1257 | |
---|
1258 | makeGLMatrix(mAutoTextureMatrix, projectionBias); |
---|
1259 | break; |
---|
1260 | default: |
---|
1261 | break; |
---|
1262 | } |
---|
1263 | glActiveTextureARB( GL_TEXTURE0 ); |
---|
1264 | } |
---|
1265 | //----------------------------------------------------------------------------- |
---|
1266 | GLint GLRenderSystem::getTextureAddressingMode( |
---|
1267 | TextureUnitState::TextureAddressingMode tam) const |
---|
1268 | { |
---|
1269 | switch(tam) |
---|
1270 | { |
---|
1271 | default: |
---|
1272 | case TextureUnitState::TAM_WRAP: |
---|
1273 | return GL_REPEAT; |
---|
1274 | case TextureUnitState::TAM_MIRROR: |
---|
1275 | return GL_MIRRORED_REPEAT; |
---|
1276 | case TextureUnitState::TAM_CLAMP: |
---|
1277 | return GL_CLAMP_TO_EDGE; |
---|
1278 | case TextureUnitState::TAM_BORDER: |
---|
1279 | return GL_CLAMP_TO_BORDER; |
---|
1280 | } |
---|
1281 | |
---|
1282 | } |
---|
1283 | //----------------------------------------------------------------------------- |
---|
1284 | void GLRenderSystem::_setTextureAddressingMode(size_t stage, const TextureUnitState::UVWAddressingMode& uvw) |
---|
1285 | { |
---|
1286 | glActiveTextureARB( GL_TEXTURE0 + stage ); |
---|
1287 | glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_S, |
---|
1288 | getTextureAddressingMode(uvw.u)); |
---|
1289 | glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_T, |
---|
1290 | getTextureAddressingMode(uvw.v)); |
---|
1291 | glTexParameteri( mTextureTypes[stage], GL_TEXTURE_WRAP_R, |
---|
1292 | getTextureAddressingMode(uvw.w)); |
---|
1293 | glActiveTextureARB( GL_TEXTURE0 ); |
---|
1294 | } |
---|
1295 | //----------------------------------------------------------------------------- |
---|
1296 | void GLRenderSystem::_setTextureBorderColour(size_t stage, const ColourValue& colour) |
---|
1297 | { |
---|
1298 | GLfloat border[4] = { colour.r, colour.g, colour.b, colour.a }; |
---|
1299 | glActiveTextureARB( GL_TEXTURE0 + stage ); |
---|
1300 | glTexParameterfv( mTextureTypes[stage], GL_TEXTURE_BORDER_COLOR, border); |
---|
1301 | glActiveTextureARB( GL_TEXTURE0 ); |
---|
1302 | } |
---|
1303 | //----------------------------------------------------------------------------- |
---|
1304 | void GLRenderSystem::_setTextureMipmapBias(size_t stage, float bias) |
---|
1305 | { |
---|
1306 | if (mCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS)) |
---|
1307 | { |
---|
1308 | glActiveTextureARB( GL_TEXTURE0 + stage ); |
---|
1309 | glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias); |
---|
1310 | glActiveTextureARB( GL_TEXTURE0 ); |
---|
1311 | } |
---|
1312 | |
---|
1313 | } |
---|
1314 | //----------------------------------------------------------------------------- |
---|
1315 | void GLRenderSystem::_setTextureMatrix(size_t stage, const Matrix4& xform) |
---|
1316 | { |
---|
1317 | if (stage >= mFixedFunctionTextureUnits) |
---|
1318 | { |
---|
1319 | // Can't do this |
---|
1320 | return; |
---|
1321 | } |
---|
1322 | |
---|
1323 | GLfloat mat[16]; |
---|
1324 | makeGLMatrix(mat, xform); |
---|
1325 | |
---|
1326 | glActiveTextureARB(GL_TEXTURE0 + stage); |
---|
1327 | glMatrixMode(GL_TEXTURE); |
---|
1328 | |
---|
1329 | // Load this matrix in |
---|
1330 | glLoadMatrixf(mat); |
---|
1331 | |
---|
1332 | if (mUseAutoTextureMatrix) |
---|
1333 | { |
---|
1334 | // Concat auto matrix |
---|
1335 | glMultMatrixf(mAutoTextureMatrix); |
---|
1336 | } |
---|
1337 | |
---|
1338 | glMatrixMode(GL_MODELVIEW); |
---|
1339 | glActiveTextureARB(GL_TEXTURE0); |
---|
1340 | } |
---|
1341 | //----------------------------------------------------------------------------- |
---|
1342 | GLint GLRenderSystem::getBlendMode(SceneBlendFactor ogreBlend) const |
---|
1343 | { |
---|
1344 | switch(ogreBlend) |
---|
1345 | { |
---|
1346 | case SBF_ONE: |
---|
1347 | return GL_ONE; |
---|
1348 | case SBF_ZERO: |
---|
1349 | return GL_ZERO; |
---|
1350 | case SBF_DEST_COLOUR: |
---|
1351 | return GL_DST_COLOR; |
---|
1352 | case SBF_SOURCE_COLOUR: |
---|
1353 | return GL_SRC_COLOR; |
---|
1354 | case SBF_ONE_MINUS_DEST_COLOUR: |
---|
1355 | return GL_ONE_MINUS_DST_COLOR; |
---|
1356 | case SBF_ONE_MINUS_SOURCE_COLOUR: |
---|
1357 | return GL_ONE_MINUS_SRC_COLOR; |
---|
1358 | case SBF_DEST_ALPHA: |
---|
1359 | return GL_DST_ALPHA; |
---|
1360 | case SBF_SOURCE_ALPHA: |
---|
1361 | return GL_SRC_ALPHA; |
---|
1362 | case SBF_ONE_MINUS_DEST_ALPHA: |
---|
1363 | return GL_ONE_MINUS_DST_ALPHA; |
---|
1364 | case SBF_ONE_MINUS_SOURCE_ALPHA: |
---|
1365 | return GL_ONE_MINUS_SRC_ALPHA; |
---|
1366 | }; |
---|
1367 | // to keep compiler happy |
---|
1368 | return GL_ONE; |
---|
1369 | } |
---|
1370 | |
---|
1371 | void GLRenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor) |
---|
1372 | { |
---|
1373 | GLint sourceBlend = getBlendMode(sourceFactor); |
---|
1374 | GLint destBlend = getBlendMode(destFactor); |
---|
1375 | if(sourceFactor == SBF_ONE && destFactor == SBF_ZERO) |
---|
1376 | { |
---|
1377 | glDisable(GL_BLEND); |
---|
1378 | } |
---|
1379 | else |
---|
1380 | { |
---|
1381 | glEnable(GL_BLEND); |
---|
1382 | glBlendFunc(sourceBlend, destBlend); |
---|
1383 | } |
---|
1384 | } |
---|
1385 | //----------------------------------------------------------------------------- |
---|
1386 | void GLRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value) |
---|
1387 | { |
---|
1388 | if(func == CMPF_ALWAYS_PASS) |
---|
1389 | { |
---|
1390 | glDisable(GL_ALPHA_TEST); |
---|
1391 | } |
---|
1392 | else |
---|
1393 | { |
---|
1394 | glEnable(GL_ALPHA_TEST); |
---|
1395 | glAlphaFunc(convertCompareFunction(func), value / 255.0f); |
---|
1396 | } |
---|
1397 | } |
---|
1398 | //----------------------------------------------------------------------------- |
---|
1399 | void GLRenderSystem::_setViewport(Viewport *vp) |
---|
1400 | { |
---|
1401 | // Check if viewport is different |
---|
1402 | if (vp != mActiveViewport || vp->_isUpdated()) |
---|
1403 | { |
---|
1404 | RenderTarget* target; |
---|
1405 | target = vp->getTarget(); |
---|
1406 | _setRenderTarget(target); |
---|
1407 | mActiveViewport = vp; |
---|
1408 | |
---|
1409 | GLsizei x, y, w, h; |
---|
1410 | |
---|
1411 | // Calculate the "lower-left" corner of the viewport |
---|
1412 | w = vp->getActualWidth(); |
---|
1413 | h = vp->getActualHeight(); |
---|
1414 | x = vp->getActualLeft(); |
---|
1415 | y = vp->getActualTop(); |
---|
1416 | if (!target->requiresTextureFlipping()) |
---|
1417 | { |
---|
1418 | // Convert "upper-left" corner to "lower-left" |
---|
1419 | y = target->getHeight() - h - y; |
---|
1420 | } |
---|
1421 | glViewport(x, y, w, h); |
---|
1422 | |
---|
1423 | // Configure the viewport clipping |
---|
1424 | glScissor(x, y, w, h); |
---|
1425 | |
---|
1426 | vp->_clearUpdatedFlag(); |
---|
1427 | } |
---|
1428 | } |
---|
1429 | |
---|
1430 | void GLRenderSystem::setLights() |
---|
1431 | { |
---|
1432 | for (size_t i = 0; i < MAX_LIGHTS; ++i) |
---|
1433 | { |
---|
1434 | if (mLights[i] != NULL) |
---|
1435 | { |
---|
1436 | Light* lt = mLights[i]; |
---|
1437 | setGLLightPositionDirection(lt, GL_LIGHT0 + i); |
---|
1438 | } |
---|
1439 | } |
---|
1440 | } |
---|
1441 | |
---|
1442 | //----------------------------------------------------------------------------- |
---|
1443 | void GLRenderSystem::_beginFrame(void) |
---|
1444 | { |
---|
1445 | if (!mActiveViewport) |
---|
1446 | OGRE_EXCEPT(Exception::ERR_INVALID_STATE, |
---|
1447 | "Cannot begin frame - no viewport selected.", |
---|
1448 | "GLRenderSystem::_beginFrame"); |
---|
1449 | |
---|
1450 | // Activate the viewport clipping |
---|
1451 | glEnable(GL_SCISSOR_TEST); |
---|
1452 | } |
---|
1453 | |
---|
1454 | //----------------------------------------------------------------------------- |
---|
1455 | void GLRenderSystem::_endFrame(void) |
---|
1456 | { |
---|
1457 | // Deactivate the viewport clipping. |
---|
1458 | glDisable(GL_SCISSOR_TEST); |
---|
1459 | } |
---|
1460 | |
---|
1461 | //----------------------------------------------------------------------------- |
---|
1462 | void GLRenderSystem::_setCullingMode(CullingMode mode) |
---|
1463 | { |
---|
1464 | // NB: Because two-sided stencil API dependence of the front face, we must |
---|
1465 | // use the same 'winding' for the front face everywhere. As the OGRE default |
---|
1466 | // culling mode is clockwise, we also treat anticlockwise winding as front |
---|
1467 | // face for consistently. On the assumption that, we can't change the front |
---|
1468 | // face by glFrontFace anywhere. |
---|
1469 | |
---|
1470 | GLenum cullMode; |
---|
1471 | |
---|
1472 | switch( mode ) |
---|
1473 | { |
---|
1474 | case CULL_NONE: |
---|
1475 | glDisable( GL_CULL_FACE ); |
---|
1476 | return; |
---|
1477 | default: |
---|
1478 | case CULL_CLOCKWISE: |
---|
1479 | if (mActiveRenderTarget && |
---|
1480 | ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) || |
---|
1481 | (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding))) |
---|
1482 | { |
---|
1483 | cullMode = GL_FRONT; |
---|
1484 | } |
---|
1485 | else |
---|
1486 | { |
---|
1487 | cullMode = GL_BACK; |
---|
1488 | } |
---|
1489 | break; |
---|
1490 | case CULL_ANTICLOCKWISE: |
---|
1491 | if (mActiveRenderTarget && |
---|
1492 | ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) || |
---|
1493 | (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding))) |
---|
1494 | { |
---|
1495 | cullMode = GL_BACK; |
---|
1496 | } |
---|
1497 | else |
---|
1498 | { |
---|
1499 | cullMode = GL_FRONT; |
---|
1500 | } |
---|
1501 | break; |
---|
1502 | } |
---|
1503 | |
---|
1504 | glEnable( GL_CULL_FACE ); |
---|
1505 | glCullFace( cullMode ); |
---|
1506 | } |
---|
1507 | //----------------------------------------------------------------------------- |
---|
1508 | void GLRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction) |
---|
1509 | { |
---|
1510 | _setDepthBufferCheckEnabled(depthTest); |
---|
1511 | _setDepthBufferWriteEnabled(depthWrite); |
---|
1512 | _setDepthBufferFunction(depthFunction); |
---|
1513 | } |
---|
1514 | //----------------------------------------------------------------------------- |
---|
1515 | void GLRenderSystem::_setDepthBufferCheckEnabled(bool enabled) |
---|
1516 | { |
---|
1517 | if (enabled) |
---|
1518 | { |
---|
1519 | glClearDepth(1.0f); |
---|
1520 | glEnable(GL_DEPTH_TEST); |
---|
1521 | } |
---|
1522 | else |
---|
1523 | { |
---|
1524 | glDisable(GL_DEPTH_TEST); |
---|
1525 | } |
---|
1526 | } |
---|
1527 | //----------------------------------------------------------------------------- |
---|
1528 | void GLRenderSystem::_setDepthBufferWriteEnabled(bool enabled) |
---|
1529 | { |
---|
1530 | GLboolean flag = enabled ? GL_TRUE : GL_FALSE; |
---|
1531 | glDepthMask( flag ); |
---|
1532 | // Store for reference in _beginFrame |
---|
1533 | mDepthWrite = enabled; |
---|
1534 | } |
---|
1535 | //----------------------------------------------------------------------------- |
---|
1536 | void GLRenderSystem::_setDepthBufferFunction(CompareFunction func) |
---|
1537 | { |
---|
1538 | glDepthFunc(convertCompareFunction(func)); |
---|
1539 | } |
---|
1540 | //----------------------------------------------------------------------------- |
---|
1541 | void GLRenderSystem::_setDepthBias(float constantBias, float slopeScaleBias) |
---|
1542 | { |
---|
1543 | if (constantBias != 0 || slopeScaleBias != 0) |
---|
1544 | { |
---|
1545 | glEnable(GL_POLYGON_OFFSET_FILL); |
---|
1546 | glEnable(GL_POLYGON_OFFSET_POINT); |
---|
1547 | glEnable(GL_POLYGON_OFFSET_LINE); |
---|
1548 | glPolygonOffset(-slopeScaleBias, -constantBias); |
---|
1549 | } |
---|
1550 | else |
---|
1551 | { |
---|
1552 | glDisable(GL_POLYGON_OFFSET_FILL); |
---|
1553 | glDisable(GL_POLYGON_OFFSET_POINT); |
---|
1554 | glDisable(GL_POLYGON_OFFSET_LINE); |
---|
1555 | } |
---|
1556 | } |
---|
1557 | //----------------------------------------------------------------------------- |
---|
1558 | void GLRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha) |
---|
1559 | { |
---|
1560 | glColorMask(red, green, blue, alpha); |
---|
1561 | // record this |
---|
1562 | mColourWrite[0] = red; |
---|
1563 | mColourWrite[1] = blue; |
---|
1564 | mColourWrite[2] = green; |
---|
1565 | mColourWrite[3] = alpha; |
---|
1566 | } |
---|
1567 | //----------------------------------------------------------------------------- |
---|
1568 | String GLRenderSystem::getErrorDescription(long errCode) const |
---|
1569 | { |
---|
1570 | const GLubyte *errString = gluErrorString (errCode); |
---|
1571 | return String((const char*) errString); |
---|
1572 | } |
---|
1573 | //----------------------------------------------------------------------------- |
---|
1574 | void GLRenderSystem::setLightingEnabled(bool enabled) |
---|
1575 | { |
---|
1576 | if (enabled) |
---|
1577 | { |
---|
1578 | glEnable(GL_LIGHTING); |
---|
1579 | } |
---|
1580 | else |
---|
1581 | { |
---|
1582 | glDisable(GL_LIGHTING); |
---|
1583 | } |
---|
1584 | } |
---|
1585 | //----------------------------------------------------------------------------- |
---|
1586 | void GLRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end) |
---|
1587 | { |
---|
1588 | |
---|
1589 | GLint fogMode; |
---|
1590 | switch (mode) |
---|
1591 | { |
---|
1592 | case FOG_EXP: |
---|
1593 | fogMode = GL_EXP; |
---|
1594 | break; |
---|
1595 | case FOG_EXP2: |
---|
1596 | fogMode = GL_EXP2; |
---|
1597 | break; |
---|
1598 | case FOG_LINEAR: |
---|
1599 | fogMode = GL_LINEAR; |
---|
1600 | break; |
---|
1601 | default: |
---|
1602 | // Give up on it |
---|
1603 | glDisable(GL_FOG); |
---|
1604 | return; |
---|
1605 | } |
---|
1606 | |
---|
1607 | glEnable(GL_FOG); |
---|
1608 | glFogi(GL_FOG_MODE, fogMode); |
---|
1609 | GLfloat fogColor[4] = {colour.r, colour.g, colour.b, colour.a}; |
---|
1610 | glFogfv(GL_FOG_COLOR, fogColor); |
---|
1611 | glFogf(GL_FOG_DENSITY, density); |
---|
1612 | glFogf(GL_FOG_START, start); |
---|
1613 | glFogf(GL_FOG_END, end); |
---|
1614 | // XXX Hint here? |
---|
1615 | } |
---|
1616 | |
---|
1617 | VertexElementType GLRenderSystem::getColourVertexElementType(void) const |
---|
1618 | { |
---|
1619 | return VET_COLOUR_ABGR; |
---|
1620 | } |
---|
1621 | |
---|
1622 | void GLRenderSystem::_convertProjectionMatrix(const Matrix4& matrix, |
---|
1623 | Matrix4& dest, bool forGpuProgram) |
---|
1624 | { |
---|
1625 | // no any convertion request for OpenGL |
---|
1626 | dest = matrix; |
---|
1627 | } |
---|
1628 | |
---|
1629 | void GLRenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane, |
---|
1630 | Real farPlane, Matrix4& dest, bool forGpuProgram) |
---|
1631 | { |
---|
1632 | Radian thetaY ( fovy / 2.0f ); |
---|
1633 | Real tanThetaY = Math::Tan(thetaY); |
---|
1634 | //Real thetaX = thetaY * aspect; |
---|
1635 | //Real tanThetaX = Math::Tan(thetaX); |
---|
1636 | |
---|
1637 | // Calc matrix elements |
---|
1638 | Real w = (1.0f / tanThetaY) / aspect; |
---|
1639 | Real h = 1.0f / tanThetaY; |
---|
1640 | Real q, qn; |
---|
1641 | if (farPlane == 0) |
---|
1642 | { |
---|
1643 | // Infinite far plane |
---|
1644 | q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1; |
---|
1645 | qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2); |
---|
1646 | } |
---|
1647 | else |
---|
1648 | { |
---|
1649 | q = -(farPlane + nearPlane) / (farPlane - nearPlane); |
---|
1650 | qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane); |
---|
1651 | } |
---|
1652 | |
---|
1653 | // NB This creates Z in range [-1,1] |
---|
1654 | // |
---|
1655 | // [ w 0 0 0 ] |
---|
1656 | // [ 0 h 0 0 ] |
---|
1657 | // [ 0 0 q qn ] |
---|
1658 | // [ 0 0 -1 0 ] |
---|
1659 | |
---|
1660 | dest = Matrix4::ZERO; |
---|
1661 | dest[0][0] = w; |
---|
1662 | dest[1][1] = h; |
---|
1663 | dest[2][2] = q; |
---|
1664 | dest[2][3] = qn; |
---|
1665 | dest[3][2] = -1; |
---|
1666 | |
---|
1667 | } |
---|
1668 | |
---|
1669 | void GLRenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, |
---|
1670 | Real farPlane, Matrix4& dest, bool forGpuProgram) |
---|
1671 | { |
---|
1672 | Radian thetaY (fovy / 2.0f); |
---|
1673 | Real tanThetaY = Math::Tan(thetaY); |
---|
1674 | |
---|
1675 | //Real thetaX = thetaY * aspect; |
---|
1676 | Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX); |
---|
1677 | Real half_w = tanThetaX * nearPlane; |
---|
1678 | Real half_h = tanThetaY * nearPlane; |
---|
1679 | Real iw = 1.0 / half_w; |
---|
1680 | Real ih = 1.0 / half_h; |
---|
1681 | Real q; |
---|
1682 | if (farPlane == 0) |
---|
1683 | { |
---|
1684 | q = 0; |
---|
1685 | } |
---|
1686 | else |
---|
1687 | { |
---|
1688 | q = 2.0 / (farPlane - nearPlane); |
---|
1689 | } |
---|
1690 | dest = Matrix4::ZERO; |
---|
1691 | dest[0][0] = iw; |
---|
1692 | dest[1][1] = ih; |
---|
1693 | dest[2][2] = -q; |
---|
1694 | dest[2][3] = - (farPlane + nearPlane)/(farPlane - nearPlane); |
---|
1695 | dest[3][3] = 1; |
---|
1696 | } |
---|
1697 | |
---|
1698 | void GLRenderSystem::_setPolygonMode(PolygonMode level) |
---|
1699 | { |
---|
1700 | GLenum glmode; |
---|
1701 | switch(level) |
---|
1702 | { |
---|
1703 | case PM_POINTS: |
---|
1704 | glmode = GL_POINT; |
---|
1705 | break; |
---|
1706 | case PM_WIREFRAME: |
---|
1707 | glmode = GL_LINE; |
---|
1708 | break; |
---|
1709 | default: |
---|
1710 | case PM_SOLID: |
---|
1711 | glmode = GL_FILL; |
---|
1712 | break; |
---|
1713 | } |
---|
1714 | glPolygonMode(GL_FRONT_AND_BACK, glmode); |
---|
1715 | } |
---|
1716 | //--------------------------------------------------------------------- |
---|
1717 | void GLRenderSystem::setStencilCheckEnabled(bool enabled) |
---|
1718 | { |
---|
1719 | if (enabled) |
---|
1720 | { |
---|
1721 | glEnable(GL_STENCIL_TEST); |
---|
1722 | } |
---|
1723 | else |
---|
1724 | { |
---|
1725 | glDisable(GL_STENCIL_TEST); |
---|
1726 | } |
---|
1727 | } |
---|
1728 | //--------------------------------------------------------------------- |
---|
1729 | void GLRenderSystem::setStencilBufferParams(CompareFunction func, |
---|
1730 | uint32 refValue, uint32 mask, StencilOperation stencilFailOp, |
---|
1731 | StencilOperation depthFailOp, StencilOperation passOp, |
---|
1732 | bool twoSidedOperation) |
---|
1733 | { |
---|
1734 | bool flip; |
---|
1735 | mStencilMask = mask; |
---|
1736 | |
---|
1737 | if (twoSidedOperation) |
---|
1738 | { |
---|
1739 | if (!mCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL)) |
---|
1740 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported", |
---|
1741 | "GLRenderSystem::setStencilBufferParams"); |
---|
1742 | |
---|
1743 | // NB: We should always treat CCW as front face for consistent with default |
---|
1744 | // culling mode. Therefore, we must take care with two-sided stencil settings. |
---|
1745 | flip = (mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping()) || |
---|
1746 | (!mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping()); |
---|
1747 | if(GLEW_VERSION_2_0) // New GL2 commands |
---|
1748 | { |
---|
1749 | // Back |
---|
1750 | glStencilMaskSeparate(GL_BACK, mask); |
---|
1751 | glStencilFuncSeparate(GL_BACK, convertCompareFunction(func), refValue, mask); |
---|
1752 | glStencilOpSeparate(GL_BACK, |
---|
1753 | convertStencilOp(stencilFailOp, !flip), |
---|
1754 | convertStencilOp(depthFailOp, !flip), |
---|
1755 | convertStencilOp(passOp, !flip)); |
---|
1756 | // Front |
---|
1757 | glStencilMaskSeparate(GL_FRONT, mask); |
---|
1758 | glStencilFuncSeparate(GL_FRONT, convertCompareFunction(func), refValue, mask); |
---|
1759 | glStencilOpSeparate(GL_FRONT, |
---|
1760 | convertStencilOp(stencilFailOp, flip), |
---|
1761 | convertStencilOp(depthFailOp, flip), |
---|
1762 | convertStencilOp(passOp, flip)); |
---|
1763 | } |
---|
1764 | else // EXT_stencil_two_side |
---|
1765 | { |
---|
1766 | glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); |
---|
1767 | // Back |
---|
1768 | glActiveStencilFaceEXT(GL_BACK); |
---|
1769 | glStencilMask(mask); |
---|
1770 | glStencilFunc(convertCompareFunction(func), refValue, mask); |
---|
1771 | glStencilOp( |
---|
1772 | convertStencilOp(stencilFailOp, !flip), |
---|
1773 | convertStencilOp(depthFailOp, !flip), |
---|
1774 | convertStencilOp(passOp, !flip)); |
---|
1775 | // Front |
---|
1776 | glActiveStencilFaceEXT(GL_FRONT); |
---|
1777 | glStencilMask(mask); |
---|
1778 | glStencilFunc(convertCompareFunction(func), refValue, mask); |
---|
1779 | glStencilOp( |
---|
1780 | convertStencilOp(stencilFailOp, flip), |
---|
1781 | convertStencilOp(depthFailOp, flip), |
---|
1782 | convertStencilOp(passOp, flip)); |
---|
1783 | } |
---|
1784 | } |
---|
1785 | else |
---|
1786 | { |
---|
1787 | glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); |
---|
1788 | flip = false; |
---|
1789 | glStencilMask(mask); |
---|
1790 | glStencilFunc(convertCompareFunction(func), refValue, mask); |
---|
1791 | glStencilOp( |
---|
1792 | convertStencilOp(stencilFailOp, flip), |
---|
1793 | convertStencilOp(depthFailOp, flip), |
---|
1794 | convertStencilOp(passOp, flip)); |
---|
1795 | } |
---|
1796 | } |
---|
1797 | //--------------------------------------------------------------------- |
---|
1798 | GLint GLRenderSystem::convertCompareFunction(CompareFunction func) const |
---|
1799 | { |
---|
1800 | switch(func) |
---|
1801 | { |
---|
1802 | case CMPF_ALWAYS_FAIL: |
---|
1803 | return GL_NEVER; |
---|
1804 | case CMPF_ALWAYS_PASS: |
---|
1805 | return GL_ALWAYS; |
---|
1806 | case CMPF_LESS: |
---|
1807 | return GL_LESS; |
---|
1808 | case CMPF_LESS_EQUAL: |
---|
1809 | return GL_LEQUAL; |
---|
1810 | case CMPF_EQUAL: |
---|
1811 | return GL_EQUAL; |
---|
1812 | case CMPF_NOT_EQUAL: |
---|
1813 | return GL_NOTEQUAL; |
---|
1814 | case CMPF_GREATER_EQUAL: |
---|
1815 | return GL_GEQUAL; |
---|
1816 | case CMPF_GREATER: |
---|
1817 | return GL_GREATER; |
---|
1818 | }; |
---|
1819 | // to keep compiler happy |
---|
1820 | return GL_ALWAYS; |
---|
1821 | } |
---|
1822 | //--------------------------------------------------------------------- |
---|
1823 | GLint GLRenderSystem::convertStencilOp(StencilOperation op, bool invert) const |
---|
1824 | { |
---|
1825 | switch(op) |
---|
1826 | { |
---|
1827 | case SOP_KEEP: |
---|
1828 | return GL_KEEP; |
---|
1829 | case SOP_ZERO: |
---|
1830 | return GL_ZERO; |
---|
1831 | case SOP_REPLACE: |
---|
1832 | return GL_REPLACE; |
---|
1833 | case SOP_INCREMENT: |
---|
1834 | return invert ? GL_DECR : GL_INCR; |
---|
1835 | case SOP_DECREMENT: |
---|
1836 | return invert ? GL_INCR : GL_DECR; |
---|
1837 | case SOP_INCREMENT_WRAP: |
---|
1838 | return invert ? GL_DECR_WRAP_EXT : GL_INCR_WRAP_EXT; |
---|
1839 | case SOP_DECREMENT_WRAP: |
---|
1840 | return invert ? GL_INCR_WRAP_EXT : GL_DECR_WRAP_EXT; |
---|
1841 | case SOP_INVERT: |
---|
1842 | return GL_INVERT; |
---|
1843 | }; |
---|
1844 | // to keep compiler happy |
---|
1845 | return SOP_KEEP; |
---|
1846 | } |
---|
1847 | //--------------------------------------------------------------------- |
---|
1848 | GLuint GLRenderSystem::getCombinedMinMipFilter(void) const |
---|
1849 | { |
---|
1850 | switch(mMinFilter) |
---|
1851 | { |
---|
1852 | case FO_ANISOTROPIC: |
---|
1853 | case FO_LINEAR: |
---|
1854 | switch(mMipFilter) |
---|
1855 | { |
---|
1856 | case FO_ANISOTROPIC: |
---|
1857 | case FO_LINEAR: |
---|
1858 | // linear min, linear mip |
---|
1859 | return GL_LINEAR_MIPMAP_LINEAR; |
---|
1860 | case FO_POINT: |
---|
1861 | // linear min, point mip |
---|
1862 | return GL_LINEAR_MIPMAP_NEAREST; |
---|
1863 | case FO_NONE: |
---|
1864 | // linear min, no mip |
---|
1865 | return GL_LINEAR; |
---|
1866 | } |
---|
1867 | break; |
---|
1868 | case FO_POINT: |
---|
1869 | case FO_NONE: |
---|
1870 | switch(mMipFilter) |
---|
1871 | { |
---|
1872 | case FO_ANISOTROPIC: |
---|
1873 | case FO_LINEAR: |
---|
1874 | // nearest min, linear mip |
---|
1875 | return GL_NEAREST_MIPMAP_LINEAR; |
---|
1876 | case FO_POINT: |
---|
1877 | // nearest min, point mip |
---|
1878 | return GL_NEAREST_MIPMAP_NEAREST; |
---|
1879 | case FO_NONE: |
---|
1880 | // nearest min, no mip |
---|
1881 | return GL_NEAREST; |
---|
1882 | } |
---|
1883 | break; |
---|
1884 | } |
---|
1885 | |
---|
1886 | // should never get here |
---|
1887 | return 0; |
---|
1888 | |
---|
1889 | } |
---|
1890 | //--------------------------------------------------------------------- |
---|
1891 | void GLRenderSystem::_setTextureUnitFiltering(size_t unit, |
---|
1892 | FilterType ftype, FilterOptions fo) |
---|
1893 | { |
---|
1894 | glActiveTextureARB( GL_TEXTURE0 + unit ); |
---|
1895 | switch(ftype) |
---|
1896 | { |
---|
1897 | case FT_MIN: |
---|
1898 | mMinFilter = fo; |
---|
1899 | // Combine with existing mip filter |
---|
1900 | glTexParameteri( |
---|
1901 | mTextureTypes[unit], |
---|
1902 | GL_TEXTURE_MIN_FILTER, |
---|
1903 | getCombinedMinMipFilter()); |
---|
1904 | break; |
---|
1905 | case FT_MAG: |
---|
1906 | switch (fo) |
---|
1907 | { |
---|
1908 | case FO_ANISOTROPIC: // GL treats linear and aniso the same |
---|
1909 | case FO_LINEAR: |
---|
1910 | glTexParameteri( |
---|
1911 | mTextureTypes[unit], |
---|
1912 | GL_TEXTURE_MAG_FILTER, |
---|
1913 | GL_LINEAR); |
---|
1914 | break; |
---|
1915 | case FO_POINT: |
---|
1916 | case FO_NONE: |
---|
1917 | glTexParameteri( |
---|
1918 | mTextureTypes[unit], |
---|
1919 | GL_TEXTURE_MAG_FILTER, |
---|
1920 | GL_NEAREST); |
---|
1921 | break; |
---|
1922 | } |
---|
1923 | break; |
---|
1924 | case FT_MIP: |
---|
1925 | mMipFilter = fo; |
---|
1926 | // Combine with existing min filter |
---|
1927 | glTexParameteri( |
---|
1928 | mTextureTypes[unit], |
---|
1929 | GL_TEXTURE_MIN_FILTER, |
---|
1930 | getCombinedMinMipFilter()); |
---|
1931 | break; |
---|
1932 | } |
---|
1933 | |
---|
1934 | glActiveTextureARB( GL_TEXTURE0 ); |
---|
1935 | } |
---|
1936 | //--------------------------------------------------------------------- |
---|
1937 | GLfloat GLRenderSystem::_getCurrentAnisotropy(size_t unit) |
---|
1938 | { |
---|
1939 | GLfloat curAniso = 0; |
---|
1940 | glGetTexParameterfv(mTextureTypes[unit], |
---|
1941 | GL_TEXTURE_MAX_ANISOTROPY_EXT, &curAniso); |
---|
1942 | return curAniso ? curAniso : 1; |
---|
1943 | } |
---|
1944 | //--------------------------------------------------------------------- |
---|
1945 | void GLRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy) |
---|
1946 | { |
---|
1947 | if (!mCapabilities->hasCapability(RSC_ANISOTROPY)) |
---|
1948 | return; |
---|
1949 | |
---|
1950 | GLfloat largest_supported_anisotropy = 0; |
---|
1951 | glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy); |
---|
1952 | if (maxAnisotropy > largest_supported_anisotropy) |
---|
1953 | maxAnisotropy = largest_supported_anisotropy ? |
---|
1954 | static_cast<uint>(largest_supported_anisotropy) : 1; |
---|
1955 | if (_getCurrentAnisotropy(unit) != maxAnisotropy) |
---|
1956 | glTexParameterf(mTextureTypes[unit], GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy); |
---|
1957 | } |
---|
1958 | //----------------------------------------------------------------------------- |
---|
1959 | void GLRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm) |
---|
1960 | { |
---|
1961 | if (stage >= mFixedFunctionTextureUnits) |
---|
1962 | { |
---|
1963 | // Can't do this |
---|
1964 | return; |
---|
1965 | } |
---|
1966 | |
---|
1967 | // Check to see if blending is supported |
---|
1968 | if(!mCapabilities->hasCapability(RSC_BLENDING)) |
---|
1969 | return; |
---|
1970 | |
---|
1971 | GLenum src1op, src2op, cmd; |
---|
1972 | GLfloat cv1[4], cv2[4]; |
---|
1973 | |
---|
1974 | if (bm.blendType == LBT_COLOUR) |
---|
1975 | { |
---|
1976 | cv1[0] = bm.colourArg1.r; |
---|
1977 | cv1[1] = bm.colourArg1.g; |
---|
1978 | cv1[2] = bm.colourArg1.b; |
---|
1979 | cv1[3] = bm.colourArg1.a; |
---|
1980 | mManualBlendColours[stage][0] = bm.colourArg1; |
---|
1981 | |
---|
1982 | |
---|
1983 | cv2[0] = bm.colourArg2.r; |
---|
1984 | cv2[1] = bm.colourArg2.g; |
---|
1985 | cv2[2] = bm.colourArg2.b; |
---|
1986 | cv2[3] = bm.colourArg2.a; |
---|
1987 | mManualBlendColours[stage][1] = bm.colourArg2; |
---|
1988 | } |
---|
1989 | |
---|
1990 | if (bm.blendType == LBT_ALPHA) |
---|
1991 | { |
---|
1992 | cv1[0] = mManualBlendColours[stage][0].r; |
---|
1993 | cv1[1] = mManualBlendColours[stage][0].g; |
---|
1994 | cv1[2] = mManualBlendColours[stage][0].b; |
---|
1995 | cv1[3] = bm.alphaArg1; |
---|
1996 | |
---|
1997 | cv2[0] = mManualBlendColours[stage][1].r; |
---|
1998 | cv2[1] = mManualBlendColours[stage][1].g; |
---|
1999 | cv2[2] = mManualBlendColours[stage][1].b; |
---|
2000 | cv2[3] = bm.alphaArg2; |
---|
2001 | } |
---|
2002 | |
---|
2003 | switch (bm.source1) |
---|
2004 | { |
---|
2005 | case LBS_CURRENT: |
---|
2006 | src1op = GL_PREVIOUS; |
---|
2007 | break; |
---|
2008 | case LBS_TEXTURE: |
---|
2009 | src1op = GL_TEXTURE; |
---|
2010 | break; |
---|
2011 | case LBS_MANUAL: |
---|
2012 | src1op = GL_CONSTANT; |
---|
2013 | break; |
---|
2014 | case LBS_DIFFUSE: |
---|
2015 | src1op = GL_PRIMARY_COLOR; |
---|
2016 | break; |
---|
2017 | // XXX |
---|
2018 | case LBS_SPECULAR: |
---|
2019 | src1op = GL_PRIMARY_COLOR; |
---|
2020 | break; |
---|
2021 | default: |
---|
2022 | src1op = 0; |
---|
2023 | } |
---|
2024 | |
---|
2025 | switch (bm.source2) |
---|
2026 | { |
---|
2027 | case LBS_CURRENT: |
---|
2028 | src2op = GL_PREVIOUS; |
---|
2029 | break; |
---|
2030 | case LBS_TEXTURE: |
---|
2031 | src2op = GL_TEXTURE; |
---|
2032 | break; |
---|
2033 | case LBS_MANUAL: |
---|
2034 | src2op = GL_CONSTANT; |
---|
2035 | break; |
---|
2036 | case LBS_DIFFUSE: |
---|
2037 | src2op = GL_PRIMARY_COLOR; |
---|
2038 | break; |
---|
2039 | // XXX |
---|
2040 | case LBS_SPECULAR: |
---|
2041 | src2op = GL_PRIMARY_COLOR; |
---|
2042 | break; |
---|
2043 | default: |
---|
2044 | src2op = 0; |
---|
2045 | } |
---|
2046 | |
---|
2047 | switch (bm.operation) |
---|
2048 | { |
---|
2049 | case LBX_SOURCE1: |
---|
2050 | cmd = GL_REPLACE; |
---|
2051 | break; |
---|
2052 | case LBX_SOURCE2: |
---|
2053 | cmd = GL_REPLACE; |
---|
2054 | break; |
---|
2055 | case LBX_MODULATE: |
---|
2056 | cmd = GL_MODULATE; |
---|
2057 | break; |
---|
2058 | case LBX_MODULATE_X2: |
---|
2059 | cmd = GL_MODULATE; |
---|
2060 | break; |
---|
2061 | case LBX_MODULATE_X4: |
---|
2062 | cmd = GL_MODULATE; |
---|
2063 | break; |
---|
2064 | case LBX_ADD: |
---|
2065 | cmd = GL_ADD; |
---|
2066 | break; |
---|
2067 | case LBX_ADD_SIGNED: |
---|
2068 | cmd = GL_ADD_SIGNED; |
---|
2069 | break; |
---|
2070 | case LBX_ADD_SMOOTH: |
---|
2071 | cmd = GL_INTERPOLATE; |
---|
2072 | break; |
---|
2073 | case LBX_SUBTRACT: |
---|
2074 | cmd = GL_SUBTRACT; |
---|
2075 | break; |
---|
2076 | case LBX_BLEND_DIFFUSE_COLOUR: |
---|
2077 | cmd = GL_INTERPOLATE; |
---|
2078 | break; |
---|
2079 | case LBX_BLEND_DIFFUSE_ALPHA: |
---|
2080 | cmd = GL_INTERPOLATE; |
---|
2081 | break; |
---|
2082 | case LBX_BLEND_TEXTURE_ALPHA: |
---|
2083 | cmd = GL_INTERPOLATE; |
---|
2084 | break; |
---|
2085 | case LBX_BLEND_CURRENT_ALPHA: |
---|
2086 | cmd = GL_INTERPOLATE; |
---|
2087 | break; |
---|
2088 | case LBX_BLEND_MANUAL: |
---|
2089 | cmd = GL_INTERPOLATE; |
---|
2090 | break; |
---|
2091 | case LBX_DOTPRODUCT: |
---|
2092 | cmd = mCapabilities->hasCapability(RSC_DOT3) |
---|
2093 | ? GL_DOT3_RGB : GL_MODULATE; |
---|
2094 | break; |
---|
2095 | default: |
---|
2096 | cmd = 0; |
---|
2097 | } |
---|
2098 | |
---|
2099 | glActiveTextureARB(GL_TEXTURE0 + stage); |
---|
2100 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); |
---|
2101 | |
---|
2102 | if (bm.blendType == LBT_COLOUR) |
---|
2103 | { |
---|
2104 | glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, cmd); |
---|
2105 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, src1op); |
---|
2106 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, src2op); |
---|
2107 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT); |
---|
2108 | } |
---|
2109 | else |
---|
2110 | { |
---|
2111 | glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, cmd); |
---|
2112 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, src1op); |
---|
2113 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, src2op); |
---|
2114 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT); |
---|
2115 | } |
---|
2116 | |
---|
2117 | float blendValue[4] = {0, 0, 0, bm.factor}; |
---|
2118 | switch (bm.operation) |
---|
2119 | { |
---|
2120 | case LBX_BLEND_DIFFUSE_COLOUR: |
---|
2121 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR); |
---|
2122 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR); |
---|
2123 | break; |
---|
2124 | case LBX_BLEND_DIFFUSE_ALPHA: |
---|
2125 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR); |
---|
2126 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR); |
---|
2127 | break; |
---|
2128 | case LBX_BLEND_TEXTURE_ALPHA: |
---|
2129 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE); |
---|
2130 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_TEXTURE); |
---|
2131 | break; |
---|
2132 | case LBX_BLEND_CURRENT_ALPHA: |
---|
2133 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS); |
---|
2134 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PREVIOUS); |
---|
2135 | break; |
---|
2136 | case LBX_BLEND_MANUAL: |
---|
2137 | glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blendValue); |
---|
2138 | break; |
---|
2139 | default: |
---|
2140 | break; |
---|
2141 | }; |
---|
2142 | |
---|
2143 | switch (bm.operation) |
---|
2144 | { |
---|
2145 | case LBX_MODULATE_X2: |
---|
2146 | glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? |
---|
2147 | GL_RGB_SCALE : GL_ALPHA_SCALE, 2); |
---|
2148 | break; |
---|
2149 | case LBX_MODULATE_X4: |
---|
2150 | glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? |
---|
2151 | GL_RGB_SCALE : GL_ALPHA_SCALE, 4); |
---|
2152 | break; |
---|
2153 | default: |
---|
2154 | glTexEnvi(GL_TEXTURE_ENV, bm.blendType == LBT_COLOUR ? |
---|
2155 | GL_RGB_SCALE : GL_ALPHA_SCALE, 1); |
---|
2156 | break; |
---|
2157 | } |
---|
2158 | |
---|
2159 | if (bm.blendType == LBT_COLOUR){ |
---|
2160 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); |
---|
2161 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); |
---|
2162 | if (bm.operation == LBX_BLEND_DIFFUSE_COLOUR){ |
---|
2163 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); |
---|
2164 | } else { |
---|
2165 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); |
---|
2166 | } |
---|
2167 | } |
---|
2168 | |
---|
2169 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); |
---|
2170 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); |
---|
2171 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); |
---|
2172 | if(bm.source1 == LBS_MANUAL) |
---|
2173 | glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv1); |
---|
2174 | if (bm.source2 == LBS_MANUAL) |
---|
2175 | glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv2); |
---|
2176 | |
---|
2177 | glActiveTextureARB(GL_TEXTURE0); |
---|
2178 | } |
---|
2179 | //--------------------------------------------------------------------- |
---|
2180 | void GLRenderSystem::setGLLightPositionDirection(Light* lt, GLenum lightindex) |
---|
2181 | { |
---|
2182 | // Set position / direction |
---|
2183 | Vector4 vec; |
---|
2184 | // Use general 4D vector which is the same as GL's approach |
---|
2185 | vec = lt->getAs4DVector(); |
---|
2186 | |
---|
2187 | #if OGRE_DOUBLE_PRECISION |
---|
2188 | // Must convert to float* |
---|
2189 | float tmp[4] = {vec.x, vec.y, vec.z, vec.w}; |
---|
2190 | glLightfv(lightindex, GL_POSITION, tmp); |
---|
2191 | #else |
---|
2192 | glLightfv(lightindex, GL_POSITION, vec.ptr()); |
---|
2193 | #endif |
---|
2194 | // Set spotlight direction |
---|
2195 | if (lt->getType() == Light::LT_SPOTLIGHT) |
---|
2196 | { |
---|
2197 | vec = lt->getDerivedDirection(); |
---|
2198 | vec.w = 0.0; |
---|
2199 | #if OGRE_DOUBLE_PRECISION |
---|
2200 | // Must convert to float* |
---|
2201 | float tmp2[4] = {vec.x, vec.y, vec.z, vec.w}; |
---|
2202 | glLightfv(lightindex, GL_SPOT_DIRECTION, tmp2); |
---|
2203 | #else |
---|
2204 | glLightfv(lightindex, GL_SPOT_DIRECTION, vec.ptr()); |
---|
2205 | #endif |
---|
2206 | } |
---|
2207 | } |
---|
2208 | //--------------------------------------------------------------------- |
---|
2209 | void GLRenderSystem::setVertexDeclaration(VertexDeclaration* decl) |
---|
2210 | { |
---|
2211 | } |
---|
2212 | //--------------------------------------------------------------------- |
---|
2213 | void GLRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding) |
---|
2214 | { |
---|
2215 | } |
---|
2216 | //--------------------------------------------------------------------- |
---|
2217 | void GLRenderSystem::_render(const RenderOperation& op) |
---|
2218 | { |
---|
2219 | // Call super class |
---|
2220 | RenderSystem::_render(op); |
---|
2221 | |
---|
2222 | void* pBufferData = 0; |
---|
2223 | |
---|
2224 | const VertexDeclaration::VertexElementList& decl = |
---|
2225 | op.vertexData->vertexDeclaration->getElements(); |
---|
2226 | VertexDeclaration::VertexElementList::const_iterator elem, elemEnd; |
---|
2227 | elemEnd = decl.end(); |
---|
2228 | |
---|
2229 | for (elem = decl.begin(); elem != elemEnd; ++elem) |
---|
2230 | { |
---|
2231 | if (!op.vertexData->vertexBufferBinding->isBufferBound(elem->getSource())) |
---|
2232 | continue; // skip unbound elements |
---|
2233 | |
---|
2234 | HardwareVertexBufferSharedPtr vertexBuffer = |
---|
2235 | op.vertexData->vertexBufferBinding->getBuffer(elem->getSource()); |
---|
2236 | if(mCapabilities->hasCapability(RSC_VBO)) |
---|
2237 | { |
---|
2238 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, |
---|
2239 | static_cast<const GLHardwareVertexBuffer*>(vertexBuffer.get())->getGLBufferId()); |
---|
2240 | pBufferData = VBO_BUFFER_OFFSET(elem->getOffset()); |
---|
2241 | } |
---|
2242 | else |
---|
2243 | { |
---|
2244 | pBufferData = static_cast<const GLDefaultHardwareVertexBuffer*>(vertexBuffer.get())->getDataPtr(elem->getOffset()); |
---|
2245 | } |
---|
2246 | if (op.vertexData->vertexStart) |
---|
2247 | { |
---|
2248 | pBufferData = static_cast<char*>(pBufferData) + op.vertexData->vertexStart * vertexBuffer->getVertexSize(); |
---|
2249 | } |
---|
2250 | |
---|
2251 | unsigned int i = 0; |
---|
2252 | VertexElementSemantic sem = elem->getSemantic(); |
---|
2253 | switch(sem) |
---|
2254 | { |
---|
2255 | case VES_POSITION: |
---|
2256 | glVertexPointer(VertexElement::getTypeCount( |
---|
2257 | elem->getType()), |
---|
2258 | GLHardwareBufferManager::getGLType(elem->getType()), |
---|
2259 | static_cast<GLsizei>(vertexBuffer->getVertexSize()), |
---|
2260 | pBufferData); |
---|
2261 | glEnableClientState( GL_VERTEX_ARRAY ); |
---|
2262 | break; |
---|
2263 | case VES_NORMAL: |
---|
2264 | glNormalPointer( |
---|
2265 | GLHardwareBufferManager::getGLType(elem->getType()), |
---|
2266 | static_cast<GLsizei>(vertexBuffer->getVertexSize()), |
---|
2267 | pBufferData); |
---|
2268 | glEnableClientState( GL_NORMAL_ARRAY ); |
---|
2269 | break; |
---|
2270 | case VES_DIFFUSE: |
---|
2271 | glColorPointer(4, |
---|
2272 | GLHardwareBufferManager::getGLType(elem->getType()), |
---|
2273 | static_cast<GLsizei>(vertexBuffer->getVertexSize()), |
---|
2274 | pBufferData); |
---|
2275 | glEnableClientState( GL_COLOR_ARRAY ); |
---|
2276 | break; |
---|
2277 | case VES_SPECULAR: |
---|
2278 | if (GLEW_EXT_secondary_color) |
---|
2279 | { |
---|
2280 | glSecondaryColorPointerEXT(4, |
---|
2281 | GLHardwareBufferManager::getGLType(elem->getType()), |
---|
2282 | static_cast<GLsizei>(vertexBuffer->getVertexSize()), |
---|
2283 | pBufferData); |
---|
2284 | glEnableClientState( GL_SECONDARY_COLOR_ARRAY ); |
---|
2285 | } |
---|
2286 | break; |
---|
2287 | case VES_TEXTURE_COORDINATES: |
---|
2288 | |
---|
2289 | if (mCurrentVertexProgram) |
---|
2290 | { |
---|
2291 | // Programmable pipeline - direct UV assignment |
---|
2292 | glClientActiveTextureARB(GL_TEXTURE0 + elem->getIndex()); |
---|
2293 | glTexCoordPointer( |
---|
2294 | VertexElement::getTypeCount(elem->getType()), |
---|
2295 | GLHardwareBufferManager::getGLType(elem->getType()), |
---|
2296 | static_cast<GLsizei>(vertexBuffer->getVertexSize()), |
---|
2297 | pBufferData); |
---|
2298 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); |
---|
2299 | } |
---|
2300 | else |
---|
2301 | { |
---|
2302 | // fixed function matching to units based on tex_coord_set |
---|
2303 | for (i = 0; i < mDisabledTexUnitsFrom; i++) |
---|
2304 | { |
---|
2305 | // Only set this texture unit's texcoord pointer if it |
---|
2306 | // is supposed to be using this element's index |
---|
2307 | if (mTextureCoordIndex[i] == elem->getIndex()) |
---|
2308 | { |
---|
2309 | glClientActiveTextureARB(GL_TEXTURE0 + i); |
---|
2310 | glTexCoordPointer( |
---|
2311 | VertexElement::getTypeCount(elem->getType()), |
---|
2312 | GLHardwareBufferManager::getGLType(elem->getType()), |
---|
2313 | static_cast<GLsizei>(vertexBuffer->getVertexSize()), |
---|
2314 | pBufferData); |
---|
2315 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); |
---|
2316 | } |
---|
2317 | } |
---|
2318 | } |
---|
2319 | break; |
---|
2320 | case VES_BLEND_INDICES: |
---|
2321 | case VES_BLEND_WEIGHTS: |
---|
2322 | case VES_TANGENT: |
---|
2323 | case VES_BINORMAL: |
---|
2324 | if (mCurrentVertexProgram) |
---|
2325 | { |
---|
2326 | GLuint attrib = mCurrentVertexProgram->getAttributeIndex(sem); |
---|
2327 | glVertexAttribPointerARB( |
---|
2328 | attrib, |
---|
2329 | VertexElement::getTypeCount(elem->getType()), |
---|
2330 | GLHardwareBufferManager::getGLType(elem->getType()), |
---|
2331 | GL_FALSE, // normalisation disabled |
---|
2332 | static_cast<GLsizei>(vertexBuffer->getVertexSize()), |
---|
2333 | pBufferData); |
---|
2334 | glEnableVertexAttribArrayARB(attrib); |
---|
2335 | |
---|
2336 | } |
---|
2337 | break; |
---|
2338 | default: |
---|
2339 | break; |
---|
2340 | }; |
---|
2341 | |
---|
2342 | } |
---|
2343 | |
---|
2344 | glClientActiveTextureARB(GL_TEXTURE0); |
---|
2345 | |
---|
2346 | // Find the correct type to render |
---|
2347 | GLint primType; |
---|
2348 | switch (op.operationType) |
---|
2349 | { |
---|
2350 | case RenderOperation::OT_POINT_LIST: |
---|
2351 | primType = GL_POINTS; |
---|
2352 | break; |
---|
2353 | case RenderOperation::OT_LINE_LIST: |
---|
2354 | primType = GL_LINES; |
---|
2355 | break; |
---|
2356 | case RenderOperation::OT_LINE_STRIP: |
---|
2357 | primType = GL_LINE_STRIP; |
---|
2358 | break; |
---|
2359 | default: |
---|
2360 | case RenderOperation::OT_TRIANGLE_LIST: |
---|
2361 | primType = GL_TRIANGLES; |
---|
2362 | break; |
---|
2363 | case RenderOperation::OT_TRIANGLE_STRIP: |
---|
2364 | primType = GL_TRIANGLE_STRIP; |
---|
2365 | break; |
---|
2366 | case RenderOperation::OT_TRIANGLE_FAN: |
---|
2367 | primType = GL_TRIANGLE_FAN; |
---|
2368 | break; |
---|
2369 | } |
---|
2370 | |
---|
2371 | if (op.useIndexes) |
---|
2372 | { |
---|
2373 | if(mCapabilities->hasCapability(RSC_VBO)) |
---|
2374 | { |
---|
2375 | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, |
---|
2376 | static_cast<GLHardwareIndexBuffer*>( |
---|
2377 | op.indexData->indexBuffer.get())->getGLBufferId()); |
---|
2378 | |
---|
2379 | pBufferData = VBO_BUFFER_OFFSET( |
---|
2380 | op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize()); |
---|
2381 | } |
---|
2382 | else |
---|
2383 | { |
---|
2384 | pBufferData = static_cast<GLDefaultHardwareIndexBuffer*>( |
---|
2385 | op.indexData->indexBuffer.get())->getDataPtr( |
---|
2386 | op.indexData->indexStart * op.indexData->indexBuffer->getIndexSize()); |
---|
2387 | } |
---|
2388 | |
---|
2389 | GLenum indexType = (op.indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; |
---|
2390 | |
---|
2391 | do |
---|
2392 | { |
---|
2393 | glDrawElements(primType, op.indexData->indexCount, indexType, pBufferData); |
---|
2394 | } while (updatePassIterationRenderState()); |
---|
2395 | |
---|
2396 | } |
---|
2397 | else |
---|
2398 | { |
---|
2399 | do |
---|
2400 | { |
---|
2401 | glDrawArrays(primType, 0, op.vertexData->vertexCount); |
---|
2402 | } while (updatePassIterationRenderState()); |
---|
2403 | } |
---|
2404 | |
---|
2405 | glDisableClientState( GL_VERTEX_ARRAY ); |
---|
2406 | for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; i++) |
---|
2407 | { |
---|
2408 | glClientActiveTextureARB(GL_TEXTURE0 + i); |
---|
2409 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); |
---|
2410 | } |
---|
2411 | glClientActiveTextureARB(GL_TEXTURE0); |
---|
2412 | glDisableClientState( GL_NORMAL_ARRAY ); |
---|
2413 | glDisableClientState( GL_COLOR_ARRAY ); |
---|
2414 | if (GLEW_EXT_secondary_color) |
---|
2415 | { |
---|
2416 | glDisableClientState( GL_SECONDARY_COLOR_ARRAY ); |
---|
2417 | } |
---|
2418 | if (mCurrentVertexProgram) |
---|
2419 | { |
---|
2420 | // unbind any custom attributes |
---|
2421 | if (mCurrentVertexProgram->isAttributeValid(VES_BLEND_INDICES)) |
---|
2422 | { |
---|
2423 | glDisableVertexAttribArrayARB( |
---|
2424 | mCurrentVertexProgram->getAttributeIndex( |
---|
2425 | VES_BLEND_INDICES)); |
---|
2426 | } |
---|
2427 | if (mCurrentVertexProgram->isAttributeValid(VES_BLEND_WEIGHTS)) |
---|
2428 | { |
---|
2429 | glDisableVertexAttribArrayARB( |
---|
2430 | mCurrentVertexProgram->getAttributeIndex( |
---|
2431 | VES_BLEND_WEIGHTS)); |
---|
2432 | } |
---|
2433 | if (mCurrentVertexProgram->isAttributeValid(VES_TANGENT)) |
---|
2434 | { |
---|
2435 | glDisableVertexAttribArrayARB( |
---|
2436 | mCurrentVertexProgram->getAttributeIndex( |
---|
2437 | VES_TANGENT)); |
---|
2438 | } |
---|
2439 | if (mCurrentVertexProgram->isAttributeValid(VES_BINORMAL)) |
---|
2440 | { |
---|
2441 | glDisableVertexAttribArrayARB( |
---|
2442 | mCurrentVertexProgram->getAttributeIndex( |
---|
2443 | VES_BINORMAL)); |
---|
2444 | } |
---|
2445 | } |
---|
2446 | glColor4f(1,1,1,1); |
---|
2447 | if (GLEW_EXT_secondary_color) |
---|
2448 | { |
---|
2449 | glSecondaryColor3fEXT(0.0f, 0.0f, 0.0f); |
---|
2450 | } |
---|
2451 | |
---|
2452 | } |
---|
2453 | //--------------------------------------------------------------------- |
---|
2454 | void GLRenderSystem::setNormaliseNormals(bool normalise) |
---|
2455 | { |
---|
2456 | if (normalise) |
---|
2457 | glEnable(GL_NORMALIZE); |
---|
2458 | else |
---|
2459 | glDisable(GL_NORMALIZE); |
---|
2460 | |
---|
2461 | } |
---|
2462 | //--------------------------------------------------------------------- |
---|
2463 | void GLRenderSystem::bindGpuProgram(GpuProgram* prg) |
---|
2464 | { |
---|
2465 | GLGpuProgram* glprg = static_cast<GLGpuProgram*>(prg); |
---|
2466 | |
---|
2467 | // Unbind previous gpu program first. |
---|
2468 | // |
---|
2469 | // Note: |
---|
2470 | // 1. Even if both previous and current are the same object, we can't |
---|
2471 | // bypass re-bind completely since the object itself maybe modified. |
---|
2472 | // But we can bypass unbind based on the assumption that object |
---|
2473 | // internally GL program type shouldn't be changed after it has |
---|
2474 | // been created. The behavior of bind to a GL program type twice |
---|
2475 | // should be same as unbind and rebind that GL program type, even |
---|
2476 | // for difference objects. |
---|
2477 | // 2. We also assumed that the program's type (vertex or fragment) should |
---|
2478 | // not be changed during it's in using. If not, the following switch |
---|
2479 | // statement will confuse GL state completely, and we can't fix it |
---|
2480 | // here. To fix this case, we must coding the program implementation |
---|
2481 | // itself, if type is changing (during load/unload, etc), and it's inuse, |
---|
2482 | // unbind and notify render system to correct for its state. |
---|
2483 | // |
---|
2484 | switch (glprg->getType()) |
---|
2485 | { |
---|
2486 | case GPT_VERTEX_PROGRAM: |
---|
2487 | if (mCurrentVertexProgram != glprg) |
---|
2488 | { |
---|
2489 | if (mCurrentVertexProgram) |
---|
2490 | mCurrentVertexProgram->unbindProgram(); |
---|
2491 | mCurrentVertexProgram = glprg; |
---|
2492 | } |
---|
2493 | break; |
---|
2494 | |
---|
2495 | case GPT_FRAGMENT_PROGRAM: |
---|
2496 | if (mCurrentFragmentProgram != glprg) |
---|
2497 | { |
---|
2498 | if (mCurrentFragmentProgram) |
---|
2499 | mCurrentFragmentProgram->unbindProgram(); |
---|
2500 | mCurrentFragmentProgram = glprg; |
---|
2501 | } |
---|
2502 | break; |
---|
2503 | } |
---|
2504 | |
---|
2505 | // Bind the program |
---|
2506 | glprg->bindProgram(); |
---|
2507 | |
---|
2508 | RenderSystem::bindGpuProgram(prg); |
---|
2509 | } |
---|
2510 | //--------------------------------------------------------------------- |
---|
2511 | void GLRenderSystem::unbindGpuProgram(GpuProgramType gptype) |
---|
2512 | { |
---|
2513 | |
---|
2514 | if (gptype == GPT_VERTEX_PROGRAM && mCurrentVertexProgram) |
---|
2515 | { |
---|
2516 | mActiveVertexGpuProgramParameters.setNull(); |
---|
2517 | mCurrentVertexProgram->unbindProgram(); |
---|
2518 | mCurrentVertexProgram = 0; |
---|
2519 | } |
---|
2520 | else if (gptype == GPT_FRAGMENT_PROGRAM && mCurrentFragmentProgram) |
---|
2521 | { |
---|
2522 | mActiveFragmentGpuProgramParameters.setNull(); |
---|
2523 | mCurrentFragmentProgram->unbindProgram(); |
---|
2524 | mCurrentFragmentProgram = 0; |
---|
2525 | } |
---|
2526 | RenderSystem::unbindGpuProgram(gptype); |
---|
2527 | |
---|
2528 | } |
---|
2529 | //--------------------------------------------------------------------- |
---|
2530 | void GLRenderSystem::bindGpuProgramParameters(GpuProgramType gptype, GpuProgramParametersSharedPtr params) |
---|
2531 | { |
---|
2532 | if (gptype == GPT_VERTEX_PROGRAM) |
---|
2533 | { |
---|
2534 | mActiveVertexGpuProgramParameters = params; |
---|
2535 | mCurrentVertexProgram->bindProgramParameters(params); |
---|
2536 | } |
---|
2537 | else |
---|
2538 | { |
---|
2539 | mActiveFragmentGpuProgramParameters = params; |
---|
2540 | mCurrentFragmentProgram->bindProgramParameters(params); |
---|
2541 | } |
---|
2542 | } |
---|
2543 | //--------------------------------------------------------------------- |
---|
2544 | void GLRenderSystem::bindGpuProgramPassIterationParameters(GpuProgramType gptype) |
---|
2545 | { |
---|
2546 | if (gptype == GPT_VERTEX_PROGRAM) |
---|
2547 | { |
---|
2548 | mCurrentVertexProgram->bindProgramPassIterationParameters(mActiveVertexGpuProgramParameters); |
---|
2549 | } |
---|
2550 | else |
---|
2551 | { |
---|
2552 | mCurrentFragmentProgram->bindProgramPassIterationParameters(mActiveFragmentGpuProgramParameters); |
---|
2553 | } |
---|
2554 | } |
---|
2555 | //--------------------------------------------------------------------- |
---|
2556 | void GLRenderSystem::setClipPlanes(const PlaneList& clipPlanes) |
---|
2557 | { |
---|
2558 | size_t i; |
---|
2559 | size_t numClipPlanes; |
---|
2560 | GLdouble clipPlane[4]; |
---|
2561 | |
---|
2562 | numClipPlanes = clipPlanes.size(); |
---|
2563 | for (i = 0; i < numClipPlanes; ++i) |
---|
2564 | { |
---|
2565 | GLenum clipPlaneId = static_cast<GLenum>(GL_CLIP_PLANE0 + i); |
---|
2566 | const Plane& plane = clipPlanes[i]; |
---|
2567 | |
---|
2568 | if (i >= 6/*GL_MAX_CLIP_PLANES*/) |
---|
2569 | { |
---|
2570 | OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set clip plane", |
---|
2571 | "GLRenderSystem::setClipPlanes"); |
---|
2572 | } |
---|
2573 | |
---|
2574 | clipPlane[0] = plane.normal.x; |
---|
2575 | clipPlane[1] = plane.normal.y; |
---|
2576 | clipPlane[2] = plane.normal.z; |
---|
2577 | clipPlane[3] = plane.d; |
---|
2578 | |
---|
2579 | glClipPlane(clipPlaneId, clipPlane); |
---|
2580 | glEnable(clipPlaneId); |
---|
2581 | } |
---|
2582 | |
---|
2583 | // disable remaining clip planes |
---|
2584 | for ( ; i < 6/*GL_MAX_CLIP_PLANES*/; ++i) |
---|
2585 | { |
---|
2586 | glDisable(static_cast<GLenum>(GL_CLIP_PLANE0 + i)); |
---|
2587 | } |
---|
2588 | } |
---|
2589 | //--------------------------------------------------------------------- |
---|
2590 | void GLRenderSystem::setScissorTest(bool enabled, size_t left, |
---|
2591 | size_t top, size_t right, size_t bottom) |
---|
2592 | { |
---|
2593 | // If request texture flipping, use "upper-left", otherwise use "lower-left" |
---|
2594 | bool flipping = mActiveRenderTarget->requiresTextureFlipping(); |
---|
2595 | // GL measures from the bottom, not the top |
---|
2596 | size_t targetHeight = mActiveRenderTarget->getHeight(); |
---|
2597 | // Calculate the "lower-left" corner of the viewport |
---|
2598 | GLsizei w, h, x, y; |
---|
2599 | |
---|
2600 | if (enabled) |
---|
2601 | { |
---|
2602 | glEnable(GL_SCISSOR_TEST); |
---|
2603 | // NB GL uses width / height rather than right / bottom |
---|
2604 | x = left; |
---|
2605 | if (flipping) |
---|
2606 | y = top; |
---|
2607 | else |
---|
2608 | y = targetHeight - bottom; |
---|
2609 | w = right - left; |
---|
2610 | h = bottom - top; |
---|
2611 | glScissor(x, y, w, h); |
---|
2612 | } |
---|
2613 | else |
---|
2614 | { |
---|
2615 | glDisable(GL_SCISSOR_TEST); |
---|
2616 | // GL requires you to reset the scissor when disabling |
---|
2617 | w = mActiveViewport->getActualWidth(); |
---|
2618 | h = mActiveViewport->getActualHeight(); |
---|
2619 | x = mActiveViewport->getActualLeft(); |
---|
2620 | if (flipping) |
---|
2621 | y = mActiveViewport->getActualTop(); |
---|
2622 | else |
---|
2623 | y = targetHeight - mActiveViewport->getActualTop() - h; |
---|
2624 | glScissor(x, y, w, h); |
---|
2625 | } |
---|
2626 | } |
---|
2627 | //--------------------------------------------------------------------- |
---|
2628 | void GLRenderSystem::clearFrameBuffer(unsigned int buffers, |
---|
2629 | const ColourValue& colour, Real depth, unsigned short stencil) |
---|
2630 | { |
---|
2631 | |
---|
2632 | bool colourMask = !mColourWrite[0] || !mColourWrite[1] |
---|
2633 | || !mColourWrite[2] || !mColourWrite[3]; |
---|
2634 | |
---|
2635 | GLbitfield flags = 0; |
---|
2636 | if (buffers & FBT_COLOUR) |
---|
2637 | { |
---|
2638 | flags |= GL_COLOR_BUFFER_BIT; |
---|
2639 | // Enable buffer for writing if it isn't |
---|
2640 | if (colourMask) |
---|
2641 | { |
---|
2642 | glColorMask(true, true, true, true); |
---|
2643 | } |
---|
2644 | glClearColor(colour.r, colour.g, colour.b, colour.a); |
---|
2645 | } |
---|
2646 | if (buffers & FBT_DEPTH) |
---|
2647 | { |
---|
2648 | flags |= GL_DEPTH_BUFFER_BIT; |
---|
2649 | // Enable buffer for writing if it isn't |
---|
2650 | if (!mDepthWrite) |
---|
2651 | { |
---|
2652 | glDepthMask( GL_TRUE ); |
---|
2653 | } |
---|
2654 | glClearDepth(depth); |
---|
2655 | } |
---|
2656 | if (buffers & FBT_STENCIL) |
---|
2657 | { |
---|
2658 | flags |= GL_STENCIL_BUFFER_BIT; |
---|
2659 | // Enable buffer for writing if it isn't |
---|
2660 | glStencilMask(0xFFFFFFFF); |
---|
2661 | |
---|
2662 | glClearStencil(stencil); |
---|
2663 | } |
---|
2664 | |
---|
2665 | // Should be enable scissor test due the clear region is |
---|
2666 | // relied on scissor box bounds. |
---|
2667 | GLboolean scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST); |
---|
2668 | if (!scissorTestEnabled) |
---|
2669 | { |
---|
2670 | glEnable(GL_SCISSOR_TEST); |
---|
2671 | } |
---|
2672 | |
---|
2673 | // Sets the scissor box as same as viewport |
---|
2674 | GLint viewport[4], scissor[4]; |
---|
2675 | glGetIntegerv(GL_VIEWPORT, viewport); |
---|
2676 | glGetIntegerv(GL_SCISSOR_BOX, scissor); |
---|
2677 | bool scissorBoxDifference = |
---|
2678 | viewport[0] != scissor[0] || viewport[1] != scissor[1] || |
---|
2679 | viewport[2] != scissor[2] || viewport[3] != scissor[3]; |
---|
2680 | if (scissorBoxDifference) |
---|
2681 | { |
---|
2682 | glScissor(viewport[0], viewport[1], viewport[2], viewport[3]); |
---|
2683 | } |
---|
2684 | |
---|
2685 | // Clear buffers |
---|
2686 | glClear(flags); |
---|
2687 | |
---|
2688 | // Restore scissor box |
---|
2689 | if (scissorBoxDifference) |
---|
2690 | { |
---|
2691 | glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); |
---|
2692 | } |
---|
2693 | // Restore scissor test |
---|
2694 | if (!scissorTestEnabled) |
---|
2695 | { |
---|
2696 | glDisable(GL_SCISSOR_TEST); |
---|
2697 | } |
---|
2698 | |
---|
2699 | // Reset buffer write state |
---|
2700 | if (!mDepthWrite && (buffers & FBT_DEPTH)) |
---|
2701 | { |
---|
2702 | glDepthMask( GL_FALSE ); |
---|
2703 | } |
---|
2704 | if (colourMask && (buffers & FBT_COLOUR)) |
---|
2705 | { |
---|
2706 | glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]); |
---|
2707 | } |
---|
2708 | if (buffers & FBT_STENCIL) |
---|
2709 | { |
---|
2710 | glStencilMask(mStencilMask); |
---|
2711 | } |
---|
2712 | |
---|
2713 | } |
---|
2714 | // ------------------------------------------------------------------ |
---|
2715 | void GLRenderSystem::_makeProjectionMatrix(Real left, Real right, |
---|
2716 | Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest, |
---|
2717 | bool forGpuProgram) |
---|
2718 | { |
---|
2719 | Real width = right - left; |
---|
2720 | Real height = top - bottom; |
---|
2721 | Real q, qn; |
---|
2722 | if (farPlane == 0) |
---|
2723 | { |
---|
2724 | // Infinite far plane |
---|
2725 | q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1; |
---|
2726 | qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2); |
---|
2727 | } |
---|
2728 | else |
---|
2729 | { |
---|
2730 | q = -(farPlane + nearPlane) / (farPlane - nearPlane); |
---|
2731 | qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane); |
---|
2732 | } |
---|
2733 | dest = Matrix4::ZERO; |
---|
2734 | dest[0][0] = 2 * nearPlane / width; |
---|
2735 | dest[0][2] = (right+left) / width; |
---|
2736 | dest[1][1] = 2 * nearPlane / height; |
---|
2737 | dest[1][2] = (top+bottom) / height; |
---|
2738 | dest[2][2] = q; |
---|
2739 | dest[2][3] = qn; |
---|
2740 | dest[3][2] = -1; |
---|
2741 | } |
---|
2742 | |
---|
2743 | // ------------------------------------------------------------------ |
---|
2744 | void GLRenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D) |
---|
2745 | { |
---|
2746 | if (ushort(mClipPlanes.size()) < index+1) |
---|
2747 | mClipPlanes.resize(index+1); |
---|
2748 | mClipPlanes[index] = Vector4 (A, B, C, D); |
---|
2749 | GLdouble plane[4] = { A, B, C, D }; |
---|
2750 | glClipPlane (GL_CLIP_PLANE0 + index, plane); |
---|
2751 | } |
---|
2752 | |
---|
2753 | // ------------------------------------------------------------------ |
---|
2754 | void GLRenderSystem::setGLClipPlanes() const |
---|
2755 | { |
---|
2756 | size_t size = mClipPlanes.size(); |
---|
2757 | for (size_t i=0; i<size; i++) |
---|
2758 | { |
---|
2759 | const Vector4 &p = mClipPlanes[i]; |
---|
2760 | GLdouble plane[4] = { p.x, p.y, p.z, p.w }; |
---|
2761 | glClipPlane (GL_CLIP_PLANE0 + i, plane); |
---|
2762 | } |
---|
2763 | } |
---|
2764 | |
---|
2765 | // ------------------------------------------------------------------ |
---|
2766 | void GLRenderSystem::enableClipPlane (ushort index, bool enable) |
---|
2767 | { |
---|
2768 | glEnable (GL_CLIP_PLANE0 + index); |
---|
2769 | } |
---|
2770 | //--------------------------------------------------------------------- |
---|
2771 | HardwareOcclusionQuery* GLRenderSystem::createHardwareOcclusionQuery(void) |
---|
2772 | { |
---|
2773 | GLHardwareOcclusionQuery* ret = new GLHardwareOcclusionQuery(); |
---|
2774 | mHwOcclusionQueries.push_back(ret); |
---|
2775 | return ret; |
---|
2776 | } |
---|
2777 | //--------------------------------------------------------------------- |
---|
2778 | Real GLRenderSystem::getHorizontalTexelOffset(void) |
---|
2779 | { |
---|
2780 | // No offset in GL |
---|
2781 | return 0.0f; |
---|
2782 | } |
---|
2783 | //--------------------------------------------------------------------- |
---|
2784 | Real GLRenderSystem::getVerticalTexelOffset(void) |
---|
2785 | { |
---|
2786 | // No offset in GL |
---|
2787 | return 0.0f; |
---|
2788 | } |
---|
2789 | //--------------------------------------------------------------------- |
---|
2790 | void GLRenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane, |
---|
2791 | bool forGpuProgram) |
---|
2792 | { |
---|
2793 | // Thanks to Eric Lenyel for posting this calculation at www.terathon.com |
---|
2794 | |
---|
2795 | // Calculate the clip-space corner point opposite the clipping plane |
---|
2796 | // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and |
---|
2797 | // transform it into camera space by multiplying it |
---|
2798 | // by the inverse of the projection matrix |
---|
2799 | |
---|
2800 | Vector4 q; |
---|
2801 | q.x = (Math::Sign(plane.normal.x) + matrix[0][2]) / matrix[0][0]; |
---|
2802 | q.y = (Math::Sign(plane.normal.y) + matrix[1][2]) / matrix[1][1]; |
---|
2803 | q.z = -1.0F; |
---|
2804 | q.w = (1.0F + matrix[2][2]) / matrix[2][3]; |
---|
2805 | |
---|
2806 | // Calculate the scaled plane vector |
---|
2807 | Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d); |
---|
2808 | Vector4 c = clipPlane4d * (2.0F / (clipPlane4d.dotProduct(q))); |
---|
2809 | |
---|
2810 | // Replace the third row of the projection matrix |
---|
2811 | matrix[2][0] = c.x; |
---|
2812 | matrix[2][1] = c.y; |
---|
2813 | matrix[2][2] = c.z + 1.0F; |
---|
2814 | matrix[2][3] = c.w; |
---|
2815 | } |
---|
2816 | //--------------------------------------------------------------------- |
---|
2817 | void GLRenderSystem::_oneTimeContextInitialization() |
---|
2818 | { |
---|
2819 | // Set nicer lighting model -- d3d9 has this by default |
---|
2820 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); |
---|
2821 | glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); |
---|
2822 | glEnable(GL_COLOR_SUM); |
---|
2823 | glDisable(GL_DITHER); |
---|
2824 | |
---|
2825 | // Check for FSAA |
---|
2826 | // Enable the extension if it was enabled by the GLSupport |
---|
2827 | if (mGLSupport->checkExtension("GL_ARB_multisample")) |
---|
2828 | { |
---|
2829 | int fsaa_active = false; |
---|
2830 | glGetIntegerv(GL_SAMPLE_BUFFERS_ARB,(GLint*)&fsaa_active); |
---|
2831 | if(fsaa_active) |
---|
2832 | { |
---|
2833 | glEnable(GL_MULTISAMPLE_ARB); |
---|
2834 | LogManager::getSingleton().logMessage("Using FSAA from GL_ARB_multisample extension."); |
---|
2835 | } |
---|
2836 | } |
---|
2837 | } |
---|
2838 | //--------------------------------------------------------------------- |
---|
2839 | void GLRenderSystem::_switchContext(GLContext *context) |
---|
2840 | { |
---|
2841 | // Unbind GPU programs and rebind to new context later, because |
---|
2842 | // scene manager treat render system as ONE 'context' ONLY, and it |
---|
2843 | // cached the GPU programs using state. |
---|
2844 | if (mCurrentVertexProgram) |
---|
2845 | mCurrentVertexProgram->unbindProgram(); |
---|
2846 | if (mCurrentFragmentProgram) |
---|
2847 | mCurrentFragmentProgram->unbindProgram(); |
---|
2848 | |
---|
2849 | // It's ready to switching |
---|
2850 | mCurrentContext->endCurrent(); |
---|
2851 | mCurrentContext = context; |
---|
2852 | mCurrentContext->setCurrent(); |
---|
2853 | |
---|
2854 | // Check if the context has already done one-time initialisation |
---|
2855 | if(!mCurrentContext->getInitialized()) |
---|
2856 | { |
---|
2857 | _oneTimeContextInitialization(); |
---|
2858 | mCurrentContext->setInitialized(); |
---|
2859 | } |
---|
2860 | |
---|
2861 | // Rebind GPU programs to new context |
---|
2862 | if (mCurrentVertexProgram) |
---|
2863 | mCurrentVertexProgram->bindProgram(); |
---|
2864 | if (mCurrentFragmentProgram) |
---|
2865 | mCurrentFragmentProgram->bindProgram(); |
---|
2866 | |
---|
2867 | // Must reset depth/colour write mask to according with user desired, otherwise, |
---|
2868 | // clearFrameBuffer would be wrong because the value we are recorded may be |
---|
2869 | // difference with the really state stored in GL context. |
---|
2870 | glDepthMask(mDepthWrite); |
---|
2871 | glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]); |
---|
2872 | glStencilMask(mStencilMask); |
---|
2873 | |
---|
2874 | } |
---|
2875 | //--------------------------------------------------------------------- |
---|
2876 | void GLRenderSystem::_setRenderTarget(RenderTarget *target) |
---|
2877 | { |
---|
2878 | // Unbind frame buffer object |
---|
2879 | if(mActiveRenderTarget) |
---|
2880 | mRTTManager->unbind(mActiveRenderTarget); |
---|
2881 | |
---|
2882 | mActiveRenderTarget = target; |
---|
2883 | |
---|
2884 | // Switch context if different from current one |
---|
2885 | GLContext *newContext = 0; |
---|
2886 | target->getCustomAttribute("GLCONTEXT", &newContext); |
---|
2887 | if(newContext && mCurrentContext != newContext) |
---|
2888 | { |
---|
2889 | _switchContext(newContext); |
---|
2890 | } |
---|
2891 | |
---|
2892 | // Bind frame buffer object |
---|
2893 | mRTTManager->bind(target); |
---|
2894 | } |
---|
2895 | //--------------------------------------------------------------------- |
---|
2896 | void GLRenderSystem::_unregisterContext(GLContext *context) |
---|
2897 | { |
---|
2898 | if(mCurrentContext == context) { |
---|
2899 | // Change the context to something else so that a valid context |
---|
2900 | // remains active. When this is the main context being unregistered, |
---|
2901 | // we set the main context to 0. |
---|
2902 | if(mCurrentContext != mMainContext) { |
---|
2903 | _switchContext(mMainContext); |
---|
2904 | } else { |
---|
2905 | /// No contexts remain |
---|
2906 | mCurrentContext->endCurrent(); |
---|
2907 | mCurrentContext = 0; |
---|
2908 | mMainContext = 0; |
---|
2909 | } |
---|
2910 | } |
---|
2911 | } |
---|
2912 | //--------------------------------------------------------------------- |
---|
2913 | Real GLRenderSystem::getMinimumDepthInputValue(void) |
---|
2914 | { |
---|
2915 | // Range [-1.0f, 1.0f] |
---|
2916 | return -1.0f; |
---|
2917 | } |
---|
2918 | //--------------------------------------------------------------------- |
---|
2919 | Real GLRenderSystem::getMaximumDepthInputValue(void) |
---|
2920 | { |
---|
2921 | // Range [-1.0f, 1.0f] |
---|
2922 | return 1.0f; |
---|
2923 | } |
---|
2924 | //--------------------------------------------------------------------- |
---|
2925 | void GLRenderSystem::registerThread() |
---|
2926 | { |
---|
2927 | // This is only valid once we've created the main context |
---|
2928 | if (!mMainContext) |
---|
2929 | { |
---|
2930 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
2931 | "Cannot register a background thread before the main context " |
---|
2932 | "has been created.", |
---|
2933 | "GLRenderSystem::registerThread"); |
---|
2934 | } |
---|
2935 | |
---|
2936 | // Create a new context for this thread. Cloning from the main context |
---|
2937 | // will ensure that resources are shared with the main context |
---|
2938 | // We want a separate context so that we can safely create GL |
---|
2939 | // objects in parallel with the main thread |
---|
2940 | GLContext* newContext = mMainContext->clone(); |
---|
2941 | mBackgroundContextList.push_back(newContext); |
---|
2942 | |
---|
2943 | // Bind this new context to this thread. |
---|
2944 | newContext->setCurrent(); |
---|
2945 | |
---|
2946 | _oneTimeContextInitialization(); |
---|
2947 | newContext->setInitialized(); |
---|
2948 | |
---|
2949 | |
---|
2950 | } |
---|
2951 | //--------------------------------------------------------------------- |
---|
2952 | void GLRenderSystem::unregisterThread() |
---|
2953 | { |
---|
2954 | // nothing to do here? |
---|
2955 | // Don't need to worry about active context, just make sure we delete |
---|
2956 | // on shutdown. |
---|
2957 | |
---|
2958 | } |
---|
2959 | //--------------------------------------------------------------------- |
---|
2960 | void GLRenderSystem::preExtraThreadsStarted() |
---|
2961 | { |
---|
2962 | // free context, we'll need this to share lists |
---|
2963 | mCurrentContext->endCurrent(); |
---|
2964 | } |
---|
2965 | //--------------------------------------------------------------------- |
---|
2966 | void GLRenderSystem::postExtraThreadsStarted() |
---|
2967 | { |
---|
2968 | // reacquire context |
---|
2969 | mCurrentContext->setCurrent(); |
---|
2970 | } |
---|
2971 | |
---|
2972 | |
---|
2973 | } |
---|