36 #include "configEvent.h"
40 #include "vertexBufferState.h"
43 static GLfloat lightPosition[] = {0.0f, 0.0f, 1.0f, 0.0f};
44 static GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f};
45 static GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
46 static GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f};
49 static GLfloat materialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
50 static GLfloat materialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
51 static GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f};
52 static GLint materialShininess = 64;
55 # define M_SQRT3_2 0.86603f
62 : eq::Channel( parent )
81 for(
size_t i = 0; i < eq::NUM_EYES; ++i )
83 delete _accum[ i ].buffer;
84 _accum[ i ].buffer = 0;
98 const FrameData& frameData = _getFrameData();
99 const int32_t eyeIndex = lunchbox::getIndexOfLastBit(
getEye() );
100 if( _isDone() && !_accum[ eyeIndex ].transfer )
107 if( view && frameData.getCurrentViewID() == view->getID( ))
108 glClearColor( 1.f, 1.f, 1.f, 0.f );
110 else if( getenv(
"EQ_TAINT_CHANNELS" ))
113 glClearColor( color.r()/255.f, color.g()/255.f, color.b()/255.f, 0.f );
117 glClearColor( 0.f, 0.f, 0.f, 0.0f );
119 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
124 if( stopRendering( ))
133 const Model* oldModel = _model;
134 const Model* model = _getModel();
136 if( oldModel != model )
137 state.setFrustumCulling(
false );
140 _updateNearFar( model->getBoundingSphere( ));
144 glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
145 glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
146 glLightfv( GL_LIGHT0, GL_DIFFUSE, lightDiffuse );
147 glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
149 glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
150 glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse );
151 glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
152 glMateriali( GL_FRONT, GL_SHININESS, materialShininess );
154 const FrameData& frameData = _getFrameData();
155 glPolygonMode( GL_FRONT_AND_BACK,
156 frameData.useWireframe() ? GL_LINE : GL_FILL );
158 const eq::Vector3f& position = frameData.getCameraPosition();
160 glMultMatrixf( frameData.getCameraRotation().array );
161 glTranslatef( position.x(), position.y(), position.z() );
162 glMultMatrixf( frameData.getModelRotation().array );
164 if( frameData.getColorMode() == COLOR_DEMO )
167 glColor3ub( color.r(), color.g(), color.b() );
170 glColor3f( .75f, .75f, .75f );
176 glNormal3f( 0.f, -1.f, 0.f );
177 glBegin( GL_TRIANGLE_STRIP );
178 glVertex3f( .25f, 0.f, .25f );
179 glVertex3f( -.25f, 0.f, .25f );
180 glVertex3f( .25f, 0.f, -.25f );
181 glVertex3f( -.25f, 0.f, -.25f );
185 state.setFrustumCulling(
true );
186 Accum& accum = _accum[ lunchbox::getIndexOfLastBit(
getEye()) ];
187 accum.stepsDone = LB_MAX( accum.stepsDone,
189 accum.transfer =
true;
195 if( stopRendering( ))
201 Accum& accum = _accum[ lunchbox::getIndexOfLastBit(
getEye()) ];
205 accum.transfer =
true;
207 if( accum.buffer && !accum.buffer->usesFBO( ))
209 LBWARN <<
"Current viewport different from view viewport, "
210 <<
"idle anti-aliasing not implemented." << std::endl;
219 accum.transfer =
true;
220 for( eq::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i )
223 const eq::SubPixel& curSubPixel = frame->
getSubPixel();
225 if( curSubPixel != eq::SubPixel::ALL )
226 accum.transfer =
false;
228 accum.stepsDone = LB_MAX( accum.stepsDone, frame->
getSubPixel().size *
240 catch(
const co::Exception& e )
242 LBWARN << e.what() << std::endl;
251 if( stopRendering() || _isDone( ))
254 const FrameData& frameData = _getFrameData();
261 if( frameData.isIdle( ))
266 if( frameData.useCompression( ))
276 const uint32_t frameNumber )
278 if( stopRendering( ))
281 for(
size_t i = 0; i < eq::NUM_EYES; ++i )
282 _accum[ i ].stepsDone = 0;
289 if( stopRendering( ))
298 const uint32_t frameNumber )
300 if( stopRendering( ))
303 for(
size_t i = 0; i < eq::NUM_EYES; ++i )
305 Accum& accum = _accum[ i ];
308 if( int32_t( accum.stepsDone ) > accum.step )
311 accum.step -= accum.stepsDone;
320 if( stopRendering( ))
325 const FrameData& frameData = _getFrameData();
326 Accum& accum = _accum[ lunchbox::getIndexOfLastBit(
getEye()) ];
331 const bool isResized = accum.buffer->resize( pvp );
336 accum.buffer->clear();
337 accum.step = view->getIdleSteps();
340 else if( frameData.isIdle( ))
344 if( !_isDone() && accum.transfer )
345 accum.buffer->accum();
346 accum.buffer->display();
356 if( frameData.useStatistics())
360 if( frameData.isIdle( ))
362 for(
size_t i = 0; i < eq::NUM_EYES; ++i )
363 steps = LB_MAX( steps, _accum[i].step );
368 steps = view ? view->getIdleSteps() : 0;
374 config->
sendEvent( IDLE_AA_LEFT ) << steps;
381 const FrameData& frameData = _getFrameData();
382 return frameData.useOrtho();
385 const FrameData& Channel::_getFrameData()
const
388 return pipe->getFrameData();
391 bool Channel::_isDone()
const
393 const FrameData& frameData = _getFrameData();
394 if( !frameData.isIdle( ))
398 const Accum& accum = _accum[ lunchbox::getIndexOfLastBit(
getEye()) ];
399 return int32_t( subpixel.index ) >= accum.step;
402 void Channel::_initJitter()
407 const FrameData& frameData = _getFrameData();
408 if( frameData.isIdle( ))
411 const View* view =
static_cast< const View*
>(
getView( ));
415 const int32_t idleSteps = view->getIdleSteps();
420 Accum& accum = _accum[ lunchbox::getIndexOfLastBit(
getEye()) ];
422 accum.buffer->clear();
423 accum.step = idleSteps;
426 bool Channel::_initAccum()
432 const eq::Eye eye =
getEye();
433 Accum& accum = _accum[ lunchbox::getIndexOfLastBit( eye ) ];
438 if( accum.step == -1 )
444 for(
size_t i = 0; i < eq::NUM_EYES; ++i )
446 if( _accum[ i ].buffer )
448 LBWARN <<
"glAccum-based accumulation does not support "
449 <<
"stereo, disabling idle anti-aliasing."
451 for(
size_t j = 0; j < eq::NUM_EYES; ++j )
453 delete _accum[ j ].buffer;
454 _accum[ j ].buffer = 0;
455 _accum[ j ].step = -1;
458 view->setIdleSteps( 0 );
467 LBASSERT( pvp.isValid( ));
469 if( !accum.buffer->init( pvp,
getWindow()->getColorFormat( )) ||
470 accum.buffer->getMaxSteps() < 256 )
472 LBWARN <<
"Accumulation buffer initialization failed, "
473 <<
"idle AA not available." << std::endl;
481 LBVERB <<
"Initialized "
482 << (accum.buffer->usesFBO() ?
"FBO accum" :
"glAccum")
486 view->setIdleSteps( accum.buffer ? 256 : 0 );
490 bool Channel::stopRendering()
const
497 const FrameData& frameData = _getFrameData();
498 const Accum& accum = _accum[ lunchbox::getIndexOfLastBit(
getEye()) ];
500 if( !frameData.isIdle() || accum.step <= 0 )
504 if( !view || view->getIdleSteps() != 256 )
505 return eq::Vector2f::ZERO;
507 const eq::Vector2i jitterStep = _getJitterStep();
508 if( jitterStep == eq::Vector2i::ZERO )
509 return eq::Vector2f::ZERO;
512 const float pvp_w = float( pvp.w );
513 const float pvp_h = float( pvp.h );
514 const float frustum_w = float((
getFrustum().get_width( )));
515 const float frustum_h = float((
getFrustum().get_height( )));
517 const float pixel_w = frustum_w / pvp_w;
518 const float pixel_h = frustum_h / pvp_h;
520 const float sampleSize = 16.f;
521 const float subpixel_w = pixel_w / sampleSize;
522 const float subpixel_h = pixel_h / sampleSize;
526 const eq::Pixel& pixel =
getPixel();
528 const float i = ( rng.get<
float >() * subpixel_w +
529 float( jitterStep.x( )) * subpixel_w ) / float( pixel.w );
530 const float j = ( rng.get<
float >() * subpixel_h +
531 float( jitterStep.y( )) * subpixel_h ) / float( pixel.h );
533 return eq::Vector2f( i, j );
536 static const uint32_t _primes[100] = {
537 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
538 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
539 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
540 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109,
541 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
542 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
543 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
544 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451 };
546 eq::Vector2i Channel::_getJitterStep()
const
549 const uint32_t channelID = subPixel.index;
550 const View* view =
static_cast< const View*
>(
getView( ));
552 return eq::Vector2i::ZERO;
554 const uint32_t totalSteps = uint32_t( view->getIdleSteps( ));
555 if( totalSteps != 256 )
556 return eq::Vector2i::ZERO;
558 const Accum& accum = _accum[ lunchbox::getIndexOfLastBit(
getEye()) ];
560 const uint32_t index = ( accum.step * _primes[ channelID % 100 ] )%subset +
561 ( channelID * subset );
562 const uint32_t sampleSize = 16;
563 const int dx = index % sampleSize;
564 const int dy = index / sampleSize;
566 return eq::Vector2i( dx, dy );
569 const Model* Channel::_getModel()
571 Config* config =
static_cast< Config*
>(
getConfig( ));
572 const View* view =
static_cast< const View*
>(
getView( ));
573 const FrameData& frameData = _getFrameData();
574 LBASSERT( !view || dynamic_cast< const View* >(
getView( )));
576 eq::uint128_t
id = view ? view->getModelID() : frameData.getModelID();
578 id = frameData.getModelID();
581 _model = config->getModel(
id );
588 void Channel::_drawModel(
const Model* scene )
590 Window* window =
static_cast< Window*
>(
getWindow( ));
591 VertexBufferState& state = window->getState();
592 const FrameData& frameData = _getFrameData();
594 if( frameData.getColorMode() ==
COLOR_MODEL && scene->hasColors( ))
595 state.setColors(
true );
597 state.setColors(
false );
598 state.setChannel(
this );
601 const eq::Matrix4f& rotation = frameData.getCameraRotation();
602 const eq::Matrix4f& modelRotation = frameData.getModelRotation();
603 eq::Matrix4f position = eq::Matrix4f::IDENTITY;
604 position.set_translation( frameData.getCameraPosition());
607 const eq::Matrix4f projection =
useOrtho() ? frustum.compute_ortho_matrix():
608 frustum.compute_matrix();
610 const eq::Matrix4f model = rotation * position * modelRotation;
612 state.setProjectionModelViewMatrix( projection * view * model );
616 const GLuint program = state.getProgram( pipe );
617 if( program != VertexBufferState::INVALID )
618 glUseProgram( program );
620 scene->cullDraw( state );
622 state.setChannel( 0 );
623 if( program != VertexBufferState::INVALID )
626 const InitData& initData =
627 static_cast<Config*
>(
getConfig( ))->getInitData();
628 if( initData.useROI( ))
639 void Channel::_drawOverlay()
642 const Window* window =
static_cast<Window*
>(
getWindow( ));
647 glMatrixMode( GL_PROJECTION );
650 glMatrixMode( GL_MODELVIEW );
653 glDisable( GL_DEPTH_TEST );
654 glDisable( GL_LIGHTING );
655 glColor3f( 1.0f, 1.0f, 1.0f );
656 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
659 glEnable( GL_BLEND );
660 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
661 const GLenum target = texture->
getTarget();
664 glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
665 glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
667 const float tWidth = float( texture->
getWidth( ) );
668 const float tHeight = float( texture->
getHeight( ) );
670 const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth;
671 const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight;
673 glBegin( GL_QUADS ); {
674 glTexCoord2f( 0, 0 );
675 glVertex3f( 5.0f, 5.0f, 0.0f );
677 glTexCoord2f( width, 0 );
678 glVertex3f( tWidth + 5.0f, 5.0f, 0.0f );
680 glTexCoord2f( width, height );
681 glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f );
683 glTexCoord2f( 0, height );
684 glVertex3f( 5.0f, tHeight + 5.0f, 0.0f );
689 glDisable( GL_BLEND );
690 glEnable( GL_LIGHTING );
691 glEnable( GL_DEPTH_TEST );
694 void Channel::_drawHelp()
696 const FrameData& frameData = _getFrameData();
697 std::string message = frameData.getMessage();
699 if( !frameData.showHelp() && message.empty( ))
707 glEnable( GL_COLOR_LOGIC_OP );
708 glDisable( GL_LIGHTING );
709 glDisable( GL_DEPTH_TEST );
711 glColor3f( 1.f, 1.f, 1.f );
715 const float height = pvp.h / vp.h;
717 if( !message.empty( ))
721 const float width = pvp.w / vp.w;
722 const float xOffset = vp.x * width;
724 const float yOffset = vp.y * height;
725 const float yPos = 0.618f * height;
726 float y = yPos - yOffset;
728 for(
size_t pos = message.find(
'\n' ); pos != std::string::npos;
729 pos = message.find(
'\n' ))
731 glRasterPos3f( 10.f - xOffset, y, 0.99f );
732 font->
draw( message.substr( 0, pos ));
733 message = message.substr( pos + 1 );
737 glRasterPos3f( 10.f - xOffset, y, 0.99f );
738 font->
draw( message );
741 glMatrixMode( GL_PROJECTION );
744 glMatrixMode( GL_MODELVIEW );
746 if( frameData.showHelp( ))
749 std::string help = EqPly::getHelp();
750 float y = height - 16.f;
752 for(
size_t pos = help.find(
'\n' ); pos != std::string::npos;
753 pos = help.find(
'\n' ))
755 glRasterPos3f( 10.f, y, 0.99f );
757 font->
draw( help.substr( 0, pos ));
758 help = help.substr( pos + 1 );
762 glRasterPos3f( 10.f, y, 0.99f );
769 void Channel::_updateNearFar(
const triply::BoundingSphere& boundingSphere )
772 const FrameData& frameData = _getFrameData();
773 const eq::Matrix4f& rotation = frameData.getCameraRotation();
776 eq::Matrix4f viewInv;
777 compute_inverse( view, viewInv );
779 const eq::Vector3f& zero = viewInv * eq::Vector3f::ZERO;
780 eq::Vector3f front = viewInv * eq::Vector3f( 0.0f, 0.0f, -1.0f );
784 front *= boundingSphere.w();
786 const eq::Vector3f& center = frameData.getCameraPosition() -
787 boundingSphere.get_sub_vector< 3 >();
788 const eq::Vector3f nearPoint = view * ( center - front );
789 const eq::Vector3f farPoint = view * ( center + front );
793 LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) >
794 std::numeric_limits< float >::epsilon(),
795 nearPoint <<
" == " << farPoint );
802 const float width = fabs( frustum.right() - frustum.left() );
803 const float height = fabs( frustum.top() - frustum.bottom() );
804 const float size = LB_MIN( width, height );
805 const float minNear = frustum.near_plane() / size * .001f;
807 const float zNear = LB_MAX( minNear, -nearPoint.z() );
808 const float zFar = LB_MAX( zNear * 2.f, -farPoint.z() );
virtual EQ_API void frameFinish(const uint128_t &frameID, const uint32_t frameNumber)
Finish rendering a frame.
const PixelViewport & getPixelViewport() const
virtual EQ_API Vector2f getJitter() const
static uint32_t assembleFrames(const Frames &frames, Channel *channel, util::Accum *accum)
Assemble all frames in an arbitrary order using the fastest implemented algorithm on the given channe...
virtual EQ_API void frameReadback(const uint128_t &frameID, const Frames &frames)
Read back the rendered frame buffer into the output frames.
virtual EQ_API void outlineViewport()
Outline the current pixel viewport.
The representation of one GPU.
A C++ class to abstract an accumulation buffer.
A configuration is a visualization session driven by an application.
EQ_API uint32_t getCurrentFrame() const
Return the current frame number.
virtual void frameDraw(const eq::uint128_t &frameID)
Draw the scene.
EQ_API const SubPixel & getSubPixel() const
virtual EQ_API void frameStart(const uint128_t &frameID, const uint32_t frameNumber)
Start rendering a frame.
EQ_API void applyScreenFrustum() const
Apply an orthographic frustum for pixel-based 2D operations.
virtual EQ_API bool configInit(const uint128_t &initID)
Initialize this channel.
virtual EQ_API void frameDraw(const uint128_t &frameID)
Draw the scene.
EQ_API void bind() const
Bind the texture.
A Pipe represents a graphics card (GPU) on a Node.
A wrapper around AGL, WGL and GLX bitmap fonts.
virtual EQ_API void applyViewport() const
Apply the OpenGL viewport for the current rendering task.
A wrapper around OpenGL textures.
EQFABRIC_INL void setNearFar(const float nearPlane, const float farPlane)
Set the near and far planes for this channel.
virtual void frameStart(const eq::uint128_t &frameID, const uint32_t frameNumber)
Start rendering a frame.
EQ_API void sendEvent(ConfigEvent &event)
Send an (old) event to the application node.
virtual bool configExit()
Exit this channel.
EQ_API void draw(const std::string &text) const
Draw text on the current raster position.
const SubPixel & getSubPixel() const
EQ_API bool usesFBO() const
Test if the accumulation uses the FBO implementation.
EQ_API void setAlphaUsage(const bool useAlpha)
Set alpha usage for newly allocated images.
EQ_API void useCompressor(const Frame::Buffer buffer, const uint32_t name)
Sets a compressor for compression for following transmissions.
EQ_API void setQuality(const Frame::Buffer buffer, const float quality)
Set the minimum quality after compression.
EQFABRIC_API const std::string & getName() const
A Window represents an on-screen or off-screen drawable.
virtual bool useOrtho() const
Select perspective or orthographic rendering.
EQ_API Config * getConfig()
EQ_API const GLEWContext * glewGetContext() const
Get the GLEW context for this channel.
virtual EQ_API void frameViewStart(const uint128_t &frameID)
Start updating a destination channel.
uint32_t getPeriod() const
EQ_API const Vector3ub & getUniqueColor() const
EQ_API View * getNativeView()
Get the channel's native view.
virtual EQ_API void frameClear(const uint128_t &frameID)
Clear the frame buffer.
const Viewport & getViewport() const
virtual EQ_API void drawStatistics()
Draw a statistics overlay.
virtual EQ_API bool configExit()
Exit this channel.
std::vector< Frame * > Frames
A vector of pointers to eq::Frame.
A View is a 2D area of a Layout.
A window represent an OpenGL drawable and context.
virtual EQ_API void resetRegions()
Reset the declared regions of interest.
Frames::const_iterator FramesCIter
A const_iterator over a eq::Frame vector.
uint32_t size
Total number of contributors.
const Range & getRange() const
EQ_API View * getView()
Get the channel's current View.
const Matrix4f & getHeadTransform() const
Return the view matrix.
const Frustumf & getFrustum() const
virtual EQ_API void frameViewFinish(const uint128_t &frameID)
Finish updating a destination channel.
EQ_API int32_t getWidth() const
EQ_API int32_t getHeight() const
virtual EQ_API void setupAssemblyState()
Setup the OpenGL state for a readback or assemble operation.
EQ_API unsigned getTarget() const
A holder for a frame data and related parameters.
virtual EQ_API void applyBuffer()
Apply the current rendering buffer, including the color mask.
const Pixel & getPixel() const
virtual EQ_API void frameAssemble(const uint128_t &frameID, const Frames &frames)
Assemble all input frames.
virtual EQ_API void resetAssemblyState()
Reset the OpenGL state after an assembly operation.
Render using the colors defined in the ply file.
virtual EQ_API void declareRegion(const eq::PixelViewport ®ion)
Declare a region covered by the current draw or assemble operation.
EQ_API uint32_t getPeriod() const