|
Equalizer
1.3.1-git
|
00001 00002 /* Copyright (c) 2006-2012, Stefan Eilemann <eile@equalizergraphics.com> 00003 * 2010, Cedric Stalder <cedric.stalder@gmail.com> 00004 * 2007, Tobias Wolf <twolf@access.unizh.ch> 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * 00009 * - Redistributions of source code must retain the above copyright notice, this 00010 * list of conditions and the following disclaimer. 00011 * - Redistributions in binary form must reproduce the above copyright notice, 00012 * this list of conditions and the following disclaimer in the documentation 00013 * and/or other materials provided with the distribution. 00014 * - Neither the name of Eyescale Software GmbH nor the names of its 00015 * contributors may be used to endorse or promote products derived from this 00016 * software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00028 * POSSIBILITY OF SUCH DAMAGE. 00029 */ 00030 00031 #include "channel.h" 00032 00033 #include "initData.h" 00034 #include "config.h" 00035 #include "configEvent.h" 00036 #include "pipe.h" 00037 #include "view.h" 00038 #include "window.h" 00039 #include "vertexBufferState.h" 00040 00041 // light parameters 00042 static GLfloat lightPosition[] = {0.0f, 0.0f, 1.0f, 0.0f}; 00043 static GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f}; 00044 static GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f}; 00045 static GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f}; 00046 00047 // material properties 00048 static GLfloat materialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f}; 00049 static GLfloat materialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f}; 00050 static GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f}; 00051 static GLint materialShininess = 64; 00052 00053 #ifndef M_SQRT3_2 00054 # define M_SQRT3_2 0.86603f /* sqrt(3)/2 */ 00055 #endif 00056 00057 namespace eqPly 00058 { 00059 00060 Channel::Channel( eq::Window* parent ) 00061 : eq::Channel( parent ) 00062 , _model(0) 00063 , _modelID( lunchbox::UUID::ZERO ) 00064 , _frameRestart( 0 ) 00065 { 00066 } 00067 00068 bool Channel::configInit( const eq::uint128_t& initID ) 00069 { 00070 if( !eq::Channel::configInit( initID )) 00071 return false; 00072 00073 setNearFar( 0.1f, 10.0f ); 00074 _model = 0; 00075 _modelID = lunchbox::UUID::ZERO; 00076 return true; 00077 } 00078 00079 bool Channel::configExit() 00080 { 00081 for( size_t i = 0; i < eq::NUM_EYES; ++i ) 00082 { 00083 delete _accum[ i ].buffer; 00084 _accum[ i ].buffer = 0; 00085 } 00086 00087 return eq::Channel::configExit(); 00088 } 00089 00090 void Channel::frameClear( const eq::uint128_t& frameID ) 00091 { 00092 if( stopRendering( )) 00093 return; 00094 00095 _initJitter(); 00096 resetRegions(); 00097 00098 const FrameData& frameData = _getFrameData(); 00099 const int32_t eyeIndex = lunchbox::getIndexOfLastBit( getEye() ); 00100 if( _isDone() && !_accum[ eyeIndex ].transfer ) 00101 return; 00102 00103 applyBuffer(); 00104 applyViewport(); 00105 00106 const eq::View* view = getView(); 00107 if( view && frameData.getCurrentViewID() == view->getID( )) 00108 glClearColor( 1.f, 1.f, 1.f, 1.f ); 00109 #ifndef NDEBUG 00110 else if( getenv( "EQ_TAINT_CHANNELS" )) 00111 { 00112 const eq::Vector3ub color = getUniqueColor(); 00113 glClearColor( color.r()/255.0f, 00114 color.g()/255.0f, 00115 color.b()/255.0f, 1.0f ); 00116 } 00117 #endif // NDEBUG 00118 else 00119 glClearColor( 0.f, 0.f, 0.f, 1.0f ); 00120 00121 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 00122 } 00123 00124 void Channel::frameDraw( const eq::uint128_t& frameID ) 00125 { 00126 if( stopRendering( )) 00127 return; 00128 00129 _initJitter(); 00130 if( _isDone( )) 00131 return; 00132 00133 Window* window = static_cast< Window* >( getWindow( )); 00134 VertexBufferState& state = window->getState(); 00135 const Model* oldModel = _model; 00136 const Model* model = _getModel(); 00137 00138 if( oldModel != model ) 00139 state.setFrustumCulling( false ); // create all display lists/VBOs 00140 00141 if( model ) 00142 _updateNearFar( model->getBoundingSphere( )); 00143 00144 // Setup OpenGL state 00145 eq::Channel::frameDraw( frameID ); 00146 00147 glLightfv( GL_LIGHT0, GL_POSITION, lightPosition ); 00148 glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient ); 00149 glLightfv( GL_LIGHT0, GL_DIFFUSE, lightDiffuse ); 00150 glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular ); 00151 00152 glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient ); 00153 glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse ); 00154 glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular ); 00155 glMateriali( GL_FRONT, GL_SHININESS, materialShininess ); 00156 00157 const FrameData& frameData = _getFrameData(); 00158 glPolygonMode( GL_FRONT_AND_BACK, 00159 frameData.useWireframe() ? GL_LINE : GL_FILL ); 00160 00161 const eq::Vector3f& position = frameData.getCameraPosition(); 00162 00163 glMultMatrixf( frameData.getCameraRotation().array ); 00164 glTranslatef( position.x(), position.y(), position.z() ); 00165 glMultMatrixf( frameData.getModelRotation().array ); 00166 00167 if( frameData.getColorMode() == COLOR_DEMO ) 00168 { 00169 const eq::Vector3ub color = getUniqueColor(); 00170 glColor3ub( color.r(), color.g(), color.b() ); 00171 } 00172 else 00173 glColor3f( .75f, .75f, .75f ); 00174 00175 if( model ) 00176 _drawModel( model ); 00177 else 00178 { 00179 glNormal3f( 0.f, -1.f, 0.f ); 00180 glBegin( GL_TRIANGLE_STRIP ); 00181 glVertex3f( .25f, 0.f, .25f ); 00182 glVertex3f( -.25f, 0.f, .25f ); 00183 glVertex3f( .25f, 0.f, -.25f ); 00184 glVertex3f( -.25f, 0.f, -.25f ); 00185 glEnd(); 00186 } 00187 00188 state.setFrustumCulling( true ); 00189 Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ]; 00190 accum.stepsDone = LB_MAX( accum.stepsDone, 00191 getSubPixel().size * getPeriod( )); 00192 accum.transfer = true; 00193 } 00194 00195 void Channel::frameAssemble( const eq::uint128_t& frameID ) 00196 { 00197 if( stopRendering( )) 00198 return; 00199 00200 if( _isDone( )) 00201 return; 00202 00203 Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ]; 00204 00205 if( getPixelViewport() != _currentPVP ) 00206 { 00207 accum.transfer = true; 00208 00209 if( accum.buffer && !accum.buffer->usesFBO( )) 00210 { 00211 LBWARN << "Current viewport different from view viewport, " 00212 << "idle anti-aliasing not implemented." << std::endl; 00213 accum.step = 0; 00214 } 00215 00216 eq::Channel::frameAssemble( frameID ); 00217 return; 00218 } 00219 // else 00220 00221 accum.transfer = true; 00222 const eq::Frames& frames = getInputFrames(); 00223 00224 for( eq::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i ) 00225 { 00226 eq::Frame* frame = *i; 00227 const eq::SubPixel& curSubPixel = frame->getSubPixel(); 00228 00229 if( curSubPixel != eq::SubPixel::ALL ) 00230 accum.transfer = false; 00231 00232 accum.stepsDone = LB_MAX( accum.stepsDone, 00233 frame->getSubPixel().size*frame->getPeriod( )); 00234 } 00235 00236 applyBuffer(); 00237 applyViewport(); 00238 setupAssemblyState(); 00239 00240 try 00241 { 00242 eq::Compositor::assembleFrames( getInputFrames(), this, accum.buffer ); 00243 } 00244 catch( const co::Exception& e ) 00245 { 00246 LBWARN << e.what() << std::endl; 00247 } 00248 00249 resetAssemblyState(); 00250 } 00251 00252 void Channel::frameReadback( const eq::uint128_t& frameID ) 00253 { 00254 if( stopRendering() || _isDone( )) 00255 return; 00256 00257 const FrameData& frameData = _getFrameData(); 00258 const eq::Frames& frames = getOutputFrames(); 00259 for( eq::FramesCIter i = frames.begin(); i != frames.end(); ++i ) 00260 { 00261 eq::Frame* frame = *i; 00262 // OPT: Drop alpha channel from all frames during network transport 00263 frame->setAlphaUsage( false ); 00264 00265 if( frameData.isIdle( )) 00266 frame->setQuality( eq::Frame::BUFFER_COLOR, 1.f ); 00267 else 00268 frame->setQuality( eq::Frame::BUFFER_COLOR, frameData.getQuality()); 00269 00270 if( frameData.useCompression( )) 00271 frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_AUTO ); 00272 else 00273 frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_NONE ); 00274 } 00275 00276 eq::Channel::frameReadback( frameID ); 00277 } 00278 00279 void Channel::frameStart( const eq::uint128_t& frameID, 00280 const uint32_t frameNumber ) 00281 { 00282 if( stopRendering( )) 00283 return; 00284 00285 for( size_t i = 0; i < eq::NUM_EYES; ++i ) 00286 _accum[ i ].stepsDone = 0; 00287 00288 eq::Channel::frameStart( frameID, frameNumber ); 00289 } 00290 00291 void Channel::frameViewStart( const eq::uint128_t& frameID ) 00292 { 00293 if( stopRendering( )) 00294 return; 00295 00296 _currentPVP = getPixelViewport(); 00297 _initJitter(); 00298 eq::Channel::frameViewStart( frameID ); 00299 } 00300 00301 void Channel::frameFinish( const eq::uint128_t& frameID, 00302 const uint32_t frameNumber ) 00303 { 00304 if( stopRendering( )) 00305 return; 00306 00307 for( size_t i = 0; i < eq::NUM_EYES; ++i ) 00308 { 00309 Accum& accum = _accum[ i ]; 00310 if( accum.step > 0 ) 00311 { 00312 if( int32_t( accum.stepsDone ) > accum.step ) 00313 accum.step = 0; 00314 else 00315 accum.step -= accum.stepsDone; 00316 } 00317 } 00318 00319 eq::Channel::frameFinish( frameID, frameNumber ); 00320 } 00321 00322 void Channel::frameViewFinish( const eq::uint128_t& frameID ) 00323 { 00324 if( stopRendering( )) 00325 return; 00326 00327 applyBuffer(); 00328 00329 const FrameData& frameData = _getFrameData(); 00330 Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ]; 00331 00332 if( accum.buffer ) 00333 { 00334 const eq::PixelViewport& pvp = getPixelViewport(); 00335 const bool isResized = accum.buffer->resize( pvp.w, pvp.h ); 00336 00337 if( isResized ) 00338 { 00339 const View* view = static_cast< const View* >( getView( )); 00340 accum.buffer->clear(); 00341 accum.step = view->getIdleSteps(); 00342 accum.stepsDone = 0; 00343 } 00344 else if( frameData.isIdle( )) 00345 { 00346 setupAssemblyState(); 00347 00348 if( !_isDone() && accum.transfer ) 00349 accum.buffer->accum(); 00350 accum.buffer->display(); 00351 00352 resetAssemblyState(); 00353 } 00354 } 00355 00356 applyViewport(); 00357 _drawOverlay(); 00358 _drawHelp(); 00359 00360 if( frameData.useStatistics()) 00361 drawStatistics(); 00362 00363 ConfigEvent event; 00364 event.data.originator = getID(); 00365 event.data.type = ConfigEvent::IDLE_AA_LEFT; 00366 00367 if( frameData.isIdle( )) 00368 { 00369 event.steps = 0; 00370 for( size_t i = 0; i < eq::NUM_EYES; ++i ) 00371 event.steps = LB_MAX( event.steps, _accum[i].step ); 00372 } 00373 else 00374 { 00375 const View* view = static_cast< const View* >( getView( )); 00376 event.steps = view ? view->getIdleSteps() : 0; 00377 } 00378 00379 // if _jitterStep == 0 and no user redraw event happened, the app will exit 00380 // FSAA idle mode and block on the next redraw event. 00381 eq::Config* config = getConfig(); 00382 config->sendEvent( event ); 00383 } 00384 00385 bool Channel::useOrtho() const 00386 { 00387 const FrameData& frameData = _getFrameData(); 00388 return frameData.useOrtho(); 00389 } 00390 00391 const FrameData& Channel::_getFrameData() const 00392 { 00393 const Pipe* pipe = static_cast<const Pipe*>( getPipe( )); 00394 return pipe->getFrameData(); 00395 } 00396 00397 bool Channel::_isDone() const 00398 { 00399 const FrameData& frameData = _getFrameData(); 00400 if( !frameData.isIdle( )) 00401 return false; 00402 00403 const eq::SubPixel& subpixel = getSubPixel(); 00404 const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ]; 00405 return int32_t( subpixel.index ) >= accum.step; 00406 } 00407 00408 void Channel::_initJitter() 00409 { 00410 if( !_initAccum( )) 00411 return; 00412 00413 const FrameData& frameData = _getFrameData(); 00414 if( frameData.isIdle( )) 00415 return; 00416 00417 const View* view = static_cast< const View* >( getView( )); 00418 if( !view ) 00419 return; 00420 00421 const int32_t idleSteps = view->getIdleSteps(); 00422 if( idleSteps == 0 ) 00423 return; 00424 00425 // ready for the next FSAA 00426 Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ]; 00427 if( accum.buffer ) 00428 accum.buffer->clear(); 00429 accum.step = idleSteps; 00430 } 00431 00432 bool Channel::_initAccum() 00433 { 00434 View* view = static_cast< View* >( getNativeView( )); 00435 if( !view ) // Only alloc accum for dest 00436 return true; 00437 00438 const eq::Eye eye = getEye(); 00439 Accum& accum = _accum[ lunchbox::getIndexOfLastBit( eye ) ]; 00440 00441 if( accum.buffer ) // already done 00442 return true; 00443 00444 if( accum.step == -1 ) // accum init failed last time 00445 return false; 00446 00447 // Check unsupported cases 00448 if( !eq::util::Accum::usesFBO( glewGetContext( ))) 00449 { 00450 for( size_t i = 0; i < eq::NUM_EYES; ++i ) 00451 { 00452 if( _accum[ i ].buffer ) 00453 { 00454 LBWARN << "glAccum-based accumulation does not support " 00455 << "stereo, disabling idle anti-aliasing." 00456 << std::endl; 00457 for( size_t j = 0; j < eq::NUM_EYES; ++j ) 00458 { 00459 delete _accum[ j ].buffer; 00460 _accum[ j ].buffer = 0; 00461 _accum[ j ].step = -1; 00462 } 00463 00464 view->setIdleSteps( 0 ); 00465 return false; 00466 } 00467 } 00468 } 00469 00470 // set up accumulation buffer 00471 accum.buffer = new eq::util::Accum( glewGetContext( )); 00472 const eq::PixelViewport& pvp = getPixelViewport(); 00473 LBASSERT( pvp.isValid( )); 00474 00475 if( !accum.buffer->init( pvp, getWindow()->getColorFormat( )) || 00476 accum.buffer->getMaxSteps() < 256 ) 00477 { 00478 LBWARN <<"Accumulation buffer initialization failed, " 00479 << "idle AA not available." << std::endl; 00480 delete accum.buffer; 00481 accum.buffer = 0; 00482 accum.step = -1; 00483 return false; 00484 } 00485 00486 // else 00487 LBVERB << "Initialized " 00488 << (accum.buffer->usesFBO() ? "FBO accum" : "glAccum") 00489 << " buffer for " << getName() << " " << getEye() 00490 << std::endl; 00491 00492 view->setIdleSteps( accum.buffer ? 256 : 0 ); 00493 return true; 00494 } 00495 00496 bool Channel::stopRendering() const 00497 { 00498 return getPipe()->getCurrentFrame() < _frameRestart; 00499 } 00500 00501 eq::Vector2f Channel::getJitter() const 00502 { 00503 const FrameData& frameData = _getFrameData(); 00504 const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ]; 00505 00506 if( !frameData.isIdle() || accum.step <= 0 ) 00507 return eq::Channel::getJitter(); 00508 00509 const View* view = static_cast< const View* >( getView( )); 00510 if( !view || view->getIdleSteps() != 256 ) 00511 return eq::Vector2f::ZERO; 00512 00513 const eq::Vector2i jitterStep = _getJitterStep(); 00514 if( jitterStep == eq::Vector2i::ZERO ) 00515 return eq::Vector2f::ZERO; 00516 00517 const eq::PixelViewport& pvp = getPixelViewport(); 00518 const float pvp_w = float( pvp.w ); 00519 const float pvp_h = float( pvp.h ); 00520 const float frustum_w = float(( getFrustum().get_width( ))); 00521 const float frustum_h = float(( getFrustum().get_height( ))); 00522 00523 const float pixel_w = frustum_w / pvp_w; 00524 const float pixel_h = frustum_h / pvp_h; 00525 00526 const float sampleSize = 16.f; // sqrt( 256 ) 00527 const float subpixel_w = pixel_w / sampleSize; 00528 const float subpixel_h = pixel_h / sampleSize; 00529 00530 // Sample value randomly computed within the subpixel 00531 lunchbox::RNG rng; 00532 const eq::Pixel& pixel = getPixel(); 00533 00534 const float i = ( rng.get< float >() * subpixel_w + 00535 float( jitterStep.x( )) * subpixel_w ) / float( pixel.w ); 00536 const float j = ( rng.get< float >() * subpixel_h + 00537 float( jitterStep.y( )) * subpixel_h ) / float( pixel.h ); 00538 00539 return eq::Vector2f( i, j ); 00540 } 00541 00542 static const uint32_t _primes[100] = { 00543 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 00544 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 00545 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 00546 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 00547 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 00548 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 00549 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 00550 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451 }; 00551 00552 eq::Vector2i Channel::_getJitterStep() const 00553 { 00554 const eq::SubPixel& subPixel = getSubPixel(); 00555 const uint32_t channelID = subPixel.index; 00556 const View* view = static_cast< const View* >( getView( )); 00557 if( !view ) 00558 return eq::Vector2i::ZERO; 00559 00560 const uint32_t totalSteps = uint32_t( view->getIdleSteps( )); 00561 if( totalSteps != 256 ) 00562 return eq::Vector2i::ZERO; 00563 00564 const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ]; 00565 const uint32_t subset = totalSteps / getSubPixel().size; 00566 const uint32_t index = ( accum.step * _primes[ channelID % 100 ] )%subset + 00567 ( channelID * subset ); 00568 const uint32_t sampleSize = 16; 00569 const int dx = index % sampleSize; 00570 const int dy = index / sampleSize; 00571 00572 return eq::Vector2i( dx, dy ); 00573 } 00574 00575 const Model* Channel::_getModel() 00576 { 00577 Config* config = static_cast< Config* >( getConfig( )); 00578 const View* view = static_cast< const View* >( getView( )); 00579 const FrameData& frameData = _getFrameData(); 00580 LBASSERT( !view || dynamic_cast< const View* >( getView( ))); 00581 00582 eq::uint128_t id = view ? view->getModelID() : frameData.getModelID(); 00583 if( id == lunchbox::UUID::ZERO ) 00584 id = frameData.getModelID(); 00585 if( id != _modelID ) 00586 { 00587 _model = config->getModel( id ); 00588 _modelID = id; 00589 } 00590 00591 return _model; 00592 } 00593 00594 void Channel::_drawModel( const Model* scene ) 00595 { 00596 Window* window = static_cast< Window* >( getWindow( )); 00597 VertexBufferState& state = window->getState(); 00598 const FrameData& frameData = _getFrameData(); 00599 00600 if( frameData.getColorMode() == COLOR_MODEL && scene->hasColors( )) 00601 state.setColors( true ); 00602 else 00603 state.setColors( false ); 00604 state.setChannel( this ); 00605 00606 // Compute cull matrix 00607 const eq::Matrix4f& rotation = frameData.getCameraRotation(); 00608 const eq::Matrix4f& modelRotation = frameData.getModelRotation(); 00609 eq::Matrix4f position = eq::Matrix4f::IDENTITY; 00610 position.set_translation( frameData.getCameraPosition()); 00611 00612 const eq::Frustumf& frustum = getFrustum(); 00613 const eq::Matrix4f projection = useOrtho() ? frustum.compute_ortho_matrix(): 00614 frustum.compute_matrix(); 00615 const eq::Matrix4f& view = getHeadTransform(); 00616 const eq::Matrix4f model = rotation * position * modelRotation; 00617 00618 state.setProjectionModelViewMatrix( projection * view * model ); 00619 state.setRange( &getRange().start); 00620 00621 const eq::Pipe* pipe = getPipe(); 00622 const GLuint program = state.getProgram( pipe ); 00623 if( program != VertexBufferState::INVALID ) 00624 glUseProgram( program ); 00625 00626 scene->cullDraw( state ); 00627 00628 state.setChannel( 0 ); 00629 if( program != VertexBufferState::INVALID ) 00630 glUseProgram( 0 ); 00631 00632 const InitData& initData = 00633 static_cast<Config*>( getConfig( ))->getInitData(); 00634 if( !initData.useROI( )) 00635 { 00636 declareRegion( getPixelViewport( )); 00637 return; 00638 } 00639 00640 #ifndef NDEBUG // region border 00641 const eq::PixelViewport& pvp = getPixelViewport(); 00642 const eq::PixelViewport& region = getRegion(); 00643 00644 glMatrixMode( GL_PROJECTION ); 00645 glLoadIdentity(); 00646 glOrtho( 0.f, pvp.w, 0.f, pvp.h, -1.f, 1.f ); 00647 glMatrixMode( GL_MODELVIEW ); 00648 glLoadIdentity(); 00649 00650 const eq::View* currentView = getView(); 00651 if( currentView && frameData.getCurrentViewID() == currentView->getID( )) 00652 glColor3f( 0.f, 0.f, 0.f ); 00653 else 00654 glColor3f( 1.f, 1.f, 1.f ); 00655 glNormal3f( 0.f, 0.f, 1.f ); 00656 00657 const eq::Vector4f rect( float( region.x ) + .5f, float( region.y ) + .5f, 00658 float( region.getXEnd( )) - .5f, 00659 float( region.getYEnd( )) - .5f ); 00660 glBegin( GL_LINE_LOOP ); { 00661 glVertex3f( rect[0], rect[1], -.99f ); 00662 glVertex3f( rect[2], rect[1], -.99f ); 00663 glVertex3f( rect[2], rect[3], -.99f ); 00664 glVertex3f( rect[0], rect[3], -.99f ); 00665 } glEnd(); 00666 #endif 00667 } 00668 00669 void Channel::_drawOverlay() 00670 { 00671 // Draw the overlay logo 00672 const Window* window = static_cast<Window*>( getWindow( )); 00673 const eq::util::Texture* texture = window->getLogoTexture(); 00674 if( !texture ) 00675 return; 00676 00677 glMatrixMode( GL_PROJECTION ); 00678 glLoadIdentity(); 00679 applyScreenFrustum(); 00680 glMatrixMode( GL_MODELVIEW ); 00681 glLoadIdentity(); 00682 00683 glDisable( GL_DEPTH_TEST ); 00684 glDisable( GL_LIGHTING ); 00685 glColor3f( 1.0f, 1.0f, 1.0f ); 00686 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); 00687 00688 // logo 00689 glEnable( GL_BLEND ); 00690 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 00691 const GLenum target = texture->getTarget(); 00692 glEnable( target ); 00693 texture->bind(); 00694 glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 00695 glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 00696 00697 const float tWidth = float( texture->getWidth( ) ); 00698 const float tHeight = float( texture->getHeight( ) ); 00699 00700 const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth; 00701 const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight; 00702 00703 glBegin( GL_QUADS ); { 00704 glTexCoord2f( 0, 0 ); 00705 glVertex3f( 5.0f, 5.0f, 0.0f ); 00706 00707 glTexCoord2f( width, 0 ); 00708 glVertex3f( tWidth + 5.0f, 5.0f, 0.0f ); 00709 00710 glTexCoord2f( width, height ); 00711 glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f ); 00712 00713 glTexCoord2f( 0, height ); 00714 glVertex3f( 5.0f, tHeight + 5.0f, 0.0f ); 00715 00716 } glEnd(); 00717 00718 glDisable( target ); 00719 glDisable( GL_BLEND ); 00720 glEnable( GL_LIGHTING ); 00721 glEnable( GL_DEPTH_TEST ); 00722 } 00723 00724 void Channel::_drawHelp() 00725 { 00726 const FrameData& frameData = _getFrameData(); 00727 std::string message = frameData.getMessage(); 00728 00729 if( !frameData.showHelp() && message.empty( )) 00730 return; 00731 00732 applyBuffer(); 00733 applyViewport(); 00734 setupAssemblyState(); 00735 00736 glLogicOp( GL_XOR ); 00737 glEnable( GL_COLOR_LOGIC_OP ); 00738 glDisable( GL_LIGHTING ); 00739 glDisable( GL_DEPTH_TEST ); 00740 00741 glColor3f( 1.f, 1.f, 1.f ); 00742 00743 const eq::PixelViewport& pvp = getPixelViewport(); 00744 const eq::Viewport& vp = getViewport(); 00745 const float height = pvp.h / vp.h; 00746 00747 if( !message.empty( )) 00748 { 00749 const eq::Window::Font* font = getWindow()->getMediumFont(); 00750 00751 const float width = pvp.w / vp.w; 00752 const float xOffset = vp.x * width; 00753 00754 const float yOffset = vp.y * height; 00755 const float yPos = 0.618f * height; 00756 float y = yPos - yOffset; 00757 00758 for( size_t pos = message.find( '\n' ); pos != std::string::npos; 00759 pos = message.find( '\n' )) 00760 { 00761 glRasterPos3f( 10.f - xOffset, y, 0.99f ); 00762 font->draw( message.substr( 0, pos )); 00763 message = message.substr( pos + 1 ); 00764 y -= 22.f; 00765 } 00766 // last line 00767 glRasterPos3f( 10.f - xOffset, y, 0.99f ); 00768 font->draw( message ); 00769 } 00770 00771 glMatrixMode( GL_PROJECTION ); 00772 glLoadIdentity(); 00773 applyScreenFrustum(); 00774 glMatrixMode( GL_MODELVIEW ); 00775 00776 if( frameData.showHelp( )) 00777 { 00778 const eq::Window::Font* font = getWindow()->getSmallFont(); 00779 std::string help = EqPly::getHelp(); 00780 float y = height - 16.f; 00781 00782 for( size_t pos = help.find( '\n' ); pos != std::string::npos; 00783 pos = help.find( '\n' )) 00784 { 00785 glRasterPos3f( 10.f, y, 0.99f ); 00786 00787 font->draw( help.substr( 0, pos )); 00788 help = help.substr( pos + 1 ); 00789 y -= 16.f; 00790 } 00791 // last line 00792 glRasterPos3f( 10.f, y, 0.99f ); 00793 font->draw( help ); 00794 } 00795 00796 resetAssemblyState(); 00797 } 00798 00799 void Channel::_updateNearFar( const mesh::BoundingSphere& boundingSphere ) 00800 { 00801 // compute dynamic near/far plane of whole model 00802 const FrameData& frameData = _getFrameData(); 00803 00804 const eq::Matrix4f& rotation = frameData.getCameraRotation(); 00805 const eq::Matrix4f headTransform = getHeadTransform() * rotation; 00806 00807 eq::Matrix4f modelInv; 00808 compute_inverse( headTransform, modelInv ); 00809 00810 const eq::Vector3f zero = modelInv * eq::Vector3f::ZERO; 00811 eq::Vector3f front = modelInv * eq::Vector3f( 0.0f, 0.0f, -1.0f ); 00812 00813 front -= zero; 00814 front.normalize(); 00815 front *= boundingSphere.w(); 00816 00817 const eq::Vector3f center = 00818 frameData.getCameraPosition().get_sub_vector< 3 >() - 00819 boundingSphere.get_sub_vector< 3 >(); 00820 const eq::Vector3f nearPoint = headTransform * ( center - front ); 00821 const eq::Vector3f farPoint = headTransform * ( center + front ); 00822 00823 if( useOrtho( )) 00824 { 00825 LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) > 00826 std::numeric_limits< float >::epsilon(), 00827 nearPoint << " == " << farPoint ); 00828 setNearFar( -nearPoint.z(), -farPoint.z() ); 00829 } 00830 else 00831 { 00832 // estimate minimal value of near plane based on frustum size 00833 const eq::Frustumf& frustum = getFrustum(); 00834 const float width = fabs( frustum.right() - frustum.left() ); 00835 const float height = fabs( frustum.top() - frustum.bottom() ); 00836 const float size = LB_MIN( width, height ); 00837 const float minNear = frustum.near_plane() / size * .001f; 00838 00839 const float zNear = LB_MAX( minNear, -nearPoint.z() ); 00840 const float zFar = LB_MAX( zNear * 2.f, -farPoint.z() ); 00841 00842 setNearFar( zNear, zFar ); 00843 } 00844 } 00845 00846 }
1.3.1-git by
1.8.0