diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce8262e6c5a5549476cad778045aafdc1e984590..266b12686ba6692a87025029d893fb051a95acc1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@
cmake_minimum_required( VERSION 3.1 FATAL_ERROR )
# visimpl project and version
-project( visimpl VERSION 1.8.2 )
+project( visimpl VERSION 1.8.3 )
set( visimpl_VERSION_ABI 6 )
SET( VISIMPL_LICENSE "GPL")
diff --git a/visimpl/DomainManager.cpp b/visimpl/DomainManager.cpp
index 27ae227d9ca998413d6f30d03aa52b7ec368e185..f3be64bddd82bd25f2a6c28fdd732d8cd7b8bdab 100644
--- a/visimpl/DomainManager.cpp
+++ b/visimpl/DomainManager.cpp
@@ -24,6 +24,8 @@ namespace visimpl
, _currentRenderer( nullptr )
, _defaultRenderer( nullptr )
, _solidRenderer( nullptr )
+ , _solidMode( false )
+ , _accumulativeMode( false )
, _decay( 0.0f )
{
}
@@ -62,15 +64,48 @@ namespace visimpl
visimpl::PARTICLE_SOLID_FRAGMENT_SHADER );
_solidProgram.compileAndLink( );
- _defaultRenderer = std::make_shared< plab::CoverageRenderer >(
+ _defaultAccProgram.loadFromText(
+ visimpl::PARTICLE_VERTEX_SHADER ,
+ visimpl::PARTICLE_ACC_DEFAULT_FRAGMENT_SHADER );
+ _defaultAccProgram.compileAndLink( );
+
+ _solidAccProgram.loadFromText(
+ visimpl::PARTICLE_VERTEX_SHADER ,
+ visimpl::PARTICLE_ACC_SOLID_FRAGMENT_SHADER );
+ _solidAccProgram.compileAndLink( );
+
+ _defaultRenderer = std::make_shared< plab::SimpleRenderer >(
_defaultProgram.program( ));
- _solidRenderer = std::make_shared< plab::CoverageRenderer >(
+ _solidRenderer = std::make_shared< plab::SimpleRenderer >(
_solidProgram.program( ));
- _currentRenderer = _defaultRenderer;
+ _defaultAccRenderer = std::make_shared< plab::SimpleRenderer >(
+ _defaultAccProgram.program( ));
+ _solidAccRenderer = std::make_shared< plab::SimpleRenderer >(
+ _solidAccProgram.program( ));
_selectionCluster->setModel( _selectionModel );
- _selectionCluster->setRenderer( _currentRenderer );
+
+ refreshRenderer( );
+ }
+
+ void DomainManager::refreshRenderer( )
+ {
+ if ( _accumulativeMode )
+ {
+ _currentRenderer = _solidMode ? _solidAccRenderer : _defaultAccRenderer;
+ }
+ else
+ {
+ _currentRenderer = _solidMode ? _solidRenderer : _defaultRenderer;
+ }
+
+ if ( _selectionCluster != nullptr )
+ _selectionCluster->setRenderer( _currentRenderer );
+ for ( const auto& item: _groupClusters )
+ item.second->setRenderer( _currentRenderer );
+ for ( const auto& item: _attributeClusters )
+ item.second->setRenderer( _currentRenderer );
}
#ifdef SIMIL_USE_BRION
@@ -291,8 +326,7 @@ namespace visimpl
_currentRenderer ,
_selectionModel->isClippingEnabled( ));
- group->getModel( )->setAccumulativeMode(
- _selectionModel->isAccumulativeMode( ));
+ group->getModel( )->setAccumulativeMode( _accumulativeMode );
std::vector< uint32_t > ids;
std::vector< NeuronParticle > particles;
@@ -326,8 +360,7 @@ namespace visimpl
_currentRenderer ,
_selectionModel->isClippingEnabled( ));
- group->getModel( )->setAccumulativeMode(
- _selectionModel->isAccumulativeMode( ));
+ group->getModel( )->setAccumulativeMode( _accumulativeMode );
std::vector< NeuronParticle > particles;
for ( const auto& gid: _selectionGids )
@@ -345,7 +378,7 @@ namespace visimpl
void DomainManager::removeGroup( const std::string& name )
{
- if(1 != _groupClusters.erase( name ))
+ if ( 1 != _groupClusters.erase( name ))
{
std::cerr << "DomainManager: Error removing group '" << name
<< "' - " << __FILE__ << ":" << __LINE__ << std::endl;
@@ -373,8 +406,7 @@ namespace visimpl
_selectionModel->getRightPlane( ) ,
_currentRenderer ,
_selectionModel->isClippingEnabled( ));
- group->getModel( )->setAccumulativeMode(
- _selectionModel->isAccumulativeMode( ));
+ group->getModel( )->setAccumulativeMode( _accumulativeMode );
const auto currentIndex = i % colors.size( );
const auto color = colors[ currentIndex ].toRgb( );
@@ -402,14 +434,21 @@ namespace visimpl
}
+ bool DomainManager::isAccumulativeModeEnabled( )
+ {
+ return _accumulativeMode;
+ }
+
void DomainManager::enableAccumulativeMode( bool enabled )
{
+ _accumulativeMode = enabled;
if ( _selectionModel != nullptr )
{
_selectionModel->setAccumulativeMode( enabled );
}
for ( const auto& item: _groupClusters )
item.second->getModel( )->setAccumulativeMode( enabled );
+ refreshRenderer( );
}
void DomainManager::enableClipping( bool enabled )
@@ -456,22 +495,14 @@ namespace visimpl
void DomainManager::applyDefaultShader( )
{
- _currentRenderer = _defaultRenderer;
- _selectionCluster->setRenderer( _currentRenderer );
- for ( const auto& item: _groupClusters )
- item.second->setRenderer( _currentRenderer );
- for ( const auto& item: _attributeClusters )
- item.second->setRenderer( _currentRenderer );
+ _solidMode = false;
+ refreshRenderer( );
}
void DomainManager::applySolidShader( )
{
- _currentRenderer = _solidRenderer;
- _selectionCluster->setRenderer( _currentRenderer );
- for ( const auto& item: _groupClusters )
- item.second->setRenderer( _currentRenderer );
- for ( const auto& item: _attributeClusters )
- item.second->setRenderer( _currentRenderer );
+ _solidMode = true;
+ refreshRenderer( );
}
void DomainManager::processInput(
@@ -551,7 +582,7 @@ namespace visimpl
{
particle->timestamp = -std::numeric_limits< float >::infinity( );
}
- auto gid = item.second->getGids().at( i );
+ auto gid = item.second->getGids( ).at( i );
auto value = input.find( gid );
if ( value != input.cend( ))
{
@@ -580,7 +611,7 @@ namespace visimpl
{
particle->timestamp = -std::numeric_limits< float >::infinity( );
}
- auto gid = item.second->getGids().at( i );
+ auto gid = item.second->getGids( ).at( i );
auto value = input.find( gid );
if ( value != input.cend( ))
{
diff --git a/visimpl/DomainManager.h b/visimpl/DomainManager.h
index 2a8dc65d60d3809949a5c49b0facb282eba2ee01..bd051039b08254dabddb55dfd4fc478a508c0ac4 100644
--- a/visimpl/DomainManager.h
+++ b/visimpl/DomainManager.h
@@ -47,10 +47,16 @@ namespace visimpl
// Renders
reto::ShaderProgram _defaultProgram;
reto::ShaderProgram _solidProgram;
+ reto::ShaderProgram _defaultAccProgram;
+ reto::ShaderProgram _solidAccProgram;
- std::shared_ptr< plab::CoverageRenderer > _currentRenderer;
- std::shared_ptr< plab::CoverageRenderer > _defaultRenderer;
- std::shared_ptr< plab::CoverageRenderer > _solidRenderer;
+ std::shared_ptr< plab::SimpleRenderer > _currentRenderer;
+ std::shared_ptr< plab::SimpleRenderer > _defaultRenderer;
+ std::shared_ptr< plab::SimpleRenderer > _solidRenderer;
+ std::shared_ptr< plab::SimpleRenderer > _defaultAccRenderer;
+ std::shared_ptr< plab::SimpleRenderer > _solidAccRenderer;
+
+ bool _solidMode , _accumulativeMode;
// Others
tBoundingBox _boundingBox;
@@ -65,6 +71,8 @@ namespace visimpl
const std::shared_ptr< reto::ClippingPlane >& rightPlane ,
const std::shared_ptr< plab::ICamera >& camera );
+ void refreshRenderer( );
+
#ifdef SIMIL_USE_BRION
void initAttributeData( const TGIDSet& gids ,
@@ -97,7 +105,7 @@ namespace visimpl
void setTime( float time );
- void addTime( float time, float endTime );
+ void addTime( float time , float endTime );
const tBoundingBox& getBoundingBox( ) const;
@@ -125,6 +133,8 @@ namespace visimpl
void applySolidShader( );
+ bool isAccumulativeModeEnabled( );
+
void enableAccumulativeMode( bool enabled );
void enableClipping( bool enabled );
diff --git a/visimpl/OpenGLWidget.cpp b/visimpl/OpenGLWidget.cpp
index 9367a6b173971b960135a82d7714fa60970a8eea..078d3f4dc3b0a045bd18878e847a6f6b9fc75776 100644
--- a/visimpl/OpenGLWidget.cpp
+++ b/visimpl/OpenGLWidget.cpp
@@ -61,8 +61,6 @@
constexpr float ZOOM_FACTOR = 1.3f;
constexpr float TRANSLATION_FACTOR = 0.001f;
constexpr float ROTATION_FACTOR = 0.01f;
-constexpr int FRAMEBUFFER_SCALE_FACTOR = 2;
-constexpr int SAMPLES = 4;
constexpr float DEFAULT_DELTA_TIME = 0.5f;
const QString INITIAL_CAMERA_POSITION = "0,0,0;1;1,0,0,0,1,0,0,0,1";
@@ -81,44 +79,18 @@ namespace visimpl
constexpr float invRGBInt = 1.0f / 255;
- const static std::string vertexShaderCode = R"(#version 330 core
-layout (location = 0) in vec2 aPos;
-layout (location = 1) in vec2 aTexCoords;
-
-out vec2 TexCoords;
-
-void main()
-{
- gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
- TexCoords = aTexCoords;
-}
-)";
-
- const static std::string screenFragment = R"(#version 330 core
-out vec4 FragColor;
-
-in vec2 TexCoords;
-
-uniform sampler2D screenTexture;
-
-void main()
-{
- FragColor = vec4(texture(screenTexture, TexCoords).rgb, 1);
-}
-)";
-
-
OpenGLWidget::OpenGLWidget( QWidget* parent_ ,
Qt::WindowFlags windowsFlags_ ,
const std::string&
#ifdef VISIMPL_USE_ZEROEQ
- zeqUri
+ zeqUri
#endif
)
: QOpenGLWidget( parent_ , windowsFlags_ )
#ifdef VISIMPL_USE_ZEROEQ
, _zeqUri( zeqUri )
#endif
+ , _gl( )
, _fpsLabel( nullptr )
, _labelCurrentTime( nullptr )
, _showFps( false )
@@ -189,12 +161,10 @@ void main()
, _deltaEvents( 0.125f )
, _domainManager( )
, _screenPlaneShader( nullptr )
- , _msaaFrameBuffer( 0 )
- , _msaaTextureColor( 0 )
- , _msaaRBODepth( 0 )
- , _midFrameBuffer( 0 )
- , _midTextureColor( 0 )
- , _midRBODepth( 0 )
+ , _quadVAO( 0 )
+ , _weightFrameBuffer( 0 )
+ , _accumulationTexture( 0 )
+ , _revealTexture( 0 )
{
_lastCameraPosition = glm::vec3( 0 , 0 , 0 );
@@ -277,7 +247,7 @@ void main()
}
}
#else
- _camera = std::make_shared< Camera >( );
+ _camera = std::make_shared< Camera >( );
#endif
Q_ASSERT( _camera );
@@ -292,7 +262,7 @@ void main()
void OpenGLWidget::initializeGL( void )
{
- initializeOpenGLFunctions( );
+ _gl.initializeOpenGLFunctions( );
auto* logger = new QOpenGLDebugLogger( this );
logger->initialize( );
@@ -316,8 +286,6 @@ void main()
glPolygonMode( GL_FRONT_AND_BACK , GL_FILL );
glEnable( GL_CULL_FACE );
- glLineWidth( 1.5 );
-
_then = std::chrono::system_clock::now( );
_lastFrame = std::chrono::system_clock::now( );
@@ -331,13 +299,14 @@ void main()
const GLubyte* shadingVer = glGetString( GL_SHADING_LANGUAGE_VERSION );
_screenPlaneShader = new reto::ShaderProgram( );
- _screenPlaneShader->loadVertexShaderFromText( vertexShaderCode );
- _screenPlaneShader->loadFragmentShaderFromText( screenFragment );
+ _screenPlaneShader->loadVertexShaderFromText( SHADER_SCREEN_VERTEX );
+ _screenPlaneShader->loadFragmentShaderFromText( SHADER_SCREEN_FRAGMENT );
_screenPlaneShader->create( );
_screenPlaneShader->link( );
_screenPlaneShader->autocatching( true );
_screenPlaneShader->use( );
- _screenPlaneShader->sendUniformi( "screenTexture" , 0 );
+ _screenPlaneShader->sendUniformi( "accumulation" , 0 );
+ _screenPlaneShader->sendUniformi( "reveal" , 1 );
std::cout << "OpenGL Hardware: " << vendor << " (" << renderer << ")"
@@ -348,84 +317,66 @@ void main()
void OpenGLWidget::_initRenderToTexture( void )
{
- _screenPlaneShader = new reto::ShaderProgram( );
- _screenPlaneShader->loadVertexShaderFromText( vertexShaderCode );
- _screenPlaneShader->loadFragmentShaderFromText( screenFragment );
- _screenPlaneShader->create( );
- _screenPlaneShader->link( );
- _screenPlaneShader->autocatching( true );
- _screenPlaneShader->use( );
- _screenPlaneShader->sendUniformi( "screenTexture" , 0 );
-
- // Generate the MSAA framebuffer
- glGenFramebuffers( 1 , &_msaaFrameBuffer );
- glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer );
+ // Generate the OIR framebuffer
- glGenTextures( 1 , &_msaaTextureColor );
- glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor );
-
- glTexImage2DMultisample(
- GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB ,
- width( ) * FRAMEBUFFER_SCALE_FACTOR ,
- height( ) * FRAMEBUFFER_SCALE_FACTOR ,
- GL_TRUE
- );
+ _gl.glGenFramebuffers( 1 , &_weightFrameBuffer );
+ _gl.glBindFramebuffer( GL_FRAMEBUFFER , _weightFrameBuffer );
- glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , 0 );
-
- glFramebufferTexture2D( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 ,
- GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor , 0 );
+ glGenTextures( 1 , &_accumulationTexture );
+ glBindTexture( GL_TEXTURE_2D , _accumulationTexture );
+ glTexImage2D( GL_TEXTURE_2D , 0 , GL_RGBA32F , width( ) , height( ) , 0 ,
+ GL_RGBA , GL_FLOAT , nullptr );
+ glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR );
+ glGenTextures( 1 , &_revealTexture );
+ glBindTexture( GL_TEXTURE_2D , _revealTexture );
+ glTexImage2D( GL_TEXTURE_2D , 0 , GL_R8 , width( ) , height( ) , 0 ,
+ GL_RED , GL_FLOAT , nullptr );
+ glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR );
- glGenRenderbuffers( 1 , &_msaaRBODepth );
- glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth );
- glRenderbufferStorageMultisample(
- GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 ,
- width( ) * FRAMEBUFFER_SCALE_FACTOR ,
- height( ) * FRAMEBUFFER_SCALE_FACTOR );
- glBindRenderbuffer( GL_RENDERBUFFER , 0 );
+ _gl.glFramebufferTexture2D( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 ,
+ GL_TEXTURE_2D , _accumulationTexture , 0 );
+ _gl.glFramebufferTexture2D( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT1 ,
+ GL_TEXTURE_2D , _revealTexture , 0 );
- glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT ,
- GL_RENDERBUFFER , _msaaRBODepth );
+ const GLenum transparentDrawBuffers[] = { GL_COLOR_ATTACHMENT0 ,
+ GL_COLOR_ATTACHMENT1 };
+ _gl.glDrawBuffers( 2 , transparentDrawBuffers );
- if ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE )
+ if ( _gl.glCheckFramebufferStatus( GL_FRAMEBUFFER ) !=
+ GL_FRAMEBUFFER_COMPLETE )
std::cerr << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!"
<< std::endl;
- // Generate the mid framebuffer.
+ _gl.glBindFramebuffer( GL_FRAMEBUFFER , defaultFramebufferObject( ));
- glGenFramebuffers( 1 , &_midFrameBuffer );
- glBindFramebuffer( GL_FRAMEBUFFER , _midFrameBuffer );
+ float quadVertices[] = {
+ // positions
+ -1.0f , -1.0f , 0.0f ,
+ 1.0f , -1.0f , 0.0f ,
+ 1.0f , 1.0f , 0.0f ,
- glGenTextures( 1 , &_midTextureColor );
- glBindTexture( GL_TEXTURE_2D , _midTextureColor );
- glTexImage2D( GL_TEXTURE_2D , 0 , GL_RGB ,
- width( ) * FRAMEBUFFER_SCALE_FACTOR ,
- height( ) * FRAMEBUFFER_SCALE_FACTOR ,
- 0 ,
- GL_RGB , GL_UNSIGNED_BYTE , nullptr );
- glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR );
- glBindTexture( GL_TEXTURE_2D , 0 );
- glFramebufferTexture2D( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 ,
- GL_TEXTURE_2D , _midTextureColor , 0 );
-
- glGenRenderbuffers( 1 , &_midRBODepth );
- glBindRenderbuffer( GL_RENDERBUFFER , _midRBODepth );
- glRenderbufferStorage( GL_RENDERBUFFER , GL_DEPTH_COMPONENT32 ,
- width( ) * FRAMEBUFFER_SCALE_FACTOR ,
- height( ) * FRAMEBUFFER_SCALE_FACTOR );
- glBindRenderbuffer( GL_RENDERBUFFER , 0 );
-
- glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT ,
- GL_RENDERBUFFER , _midRBODepth );
-
- if ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE )
- std::cerr << "ERROR::FRAMEBUFFER:: Mid Framebuffer is not complete!"
- << std::endl;
+ 1.0f , 1.0f , 0.0f ,
+ -1.0f , 1.0f , 0.0f ,
+ -1.0f , -1.0f , 0.0f
+ };
- glBindFramebuffer( GL_FRAMEBUFFER , defaultFramebufferObject( ));
+ // quad VAO
+ unsigned int quadVBO;
+ _gl.glGenVertexArrays( 1 , &_quadVAO );
+ _gl.glGenBuffers( 1 , &quadVBO );
+ _gl.glBindVertexArray( _quadVAO );
+ _gl.glBindBuffer( GL_ARRAY_BUFFER , quadVBO );
+ _gl.glBufferData( GL_ARRAY_BUFFER , sizeof( quadVertices ) , quadVertices ,
+ GL_STATIC_DRAW );
+ _gl.glEnableVertexAttribArray( 0 );
+ _gl.glVertexAttribPointer( 0 , 3 , GL_FLOAT , GL_FALSE ,
+ 3 * sizeof( float ) ,
+ ( void* ) 0 );
+ _gl.glBindVertexArray( 0 );
}
void OpenGLWidget::_configureSimulationFrame( void )
@@ -738,39 +689,60 @@ void main()
} // if player && player->isPlaying
-
- glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer );
- glViewport( 0 , 0 , width( ) * FRAMEBUFFER_SCALE_FACTOR ,
- height( ) * FRAMEBUFFER_SCALE_FACTOR );
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- glEnable( GL_DEPTH_TEST );
-
- _paintPlanes( );
- _paintParticles( );
-
glViewport( 0 , 0 , width( ) , height( ));
- // Perform MSAA
- glBindFramebuffer( GL_READ_FRAMEBUFFER , _msaaFrameBuffer );
- glBindFramebuffer( GL_DRAW_FRAMEBUFFER , _midFrameBuffer );
- int w = width( ) * FRAMEBUFFER_SCALE_FACTOR;
- int h = height( ) * FRAMEBUFFER_SCALE_FACTOR;
- glBlitFramebuffer(
- 0 , 0 ,
- w , h ,
- 0 , 0 ,
- w , h ,
- GL_COLOR_BUFFER_BIT , GL_NEAREST );
-
- // Perform super-sampling
- glBindFramebuffer( GL_READ_FRAMEBUFFER , _midFrameBuffer );
- glBindFramebuffer( GL_DRAW_FRAMEBUFFER , defaultFramebufferObject( ));
- glBlitFramebuffer(
- 0 , 0 ,
- w , h ,
- 0 , 0 ,
- width( ) , height( ) ,
- GL_COLOR_BUFFER_BIT , GL_LINEAR );
+ if ( _domainManager.isAccumulativeModeEnabled( ))
+ {
+ _gl.glBindFramebuffer( GL_FRAMEBUFFER , defaultFramebufferObject( ));
+ _gl.glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ _gl.glDisable( GL_DEPTH_TEST );
+ _gl.glDepthMask( GL_FALSE );
+ _gl.glEnable( GL_BLEND );
+ _gl.glBlendFunc( GL_SRC_ALPHA , GL_ONE_MINUS_CONSTANT_ALPHA );
+ _gl.glBlendEquation( GL_FUNC_ADD );
+ _paintPlanes( );
+ _paintParticles( );
+ }
+ else
+ {
+ _gl.glBindFramebuffer( GL_FRAMEBUFFER , _weightFrameBuffer );
+ _gl.glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ _gl.glEnable( GL_DEPTH_TEST );
+
+
+ _gl.glDepthMask( GL_FALSE );
+ _gl.glEnable( GL_BLEND );
+ _gl.glBlendFunci( 0 , GL_ONE , GL_ONE );
+ _gl.glBlendFunci( 1 , GL_ZERO , GL_ONE_MINUS_SRC_COLOR );
+ _gl.glBlendEquation( GL_FUNC_ADD );
+
+ glm::vec4 zeroFillerVec( 0.0f );
+ glm::vec4 oneFillerVec( 1.0f );
+ _gl.glClearBufferfv( GL_COLOR , 0 , &zeroFillerVec[ 0 ] );
+ _gl.glClearBufferfv( GL_COLOR , 1 , &oneFillerVec[ 0 ] );
+
+ _paintPlanes( );
+ _paintParticles( );
+
+ // Perform blend
+
+ _gl.glDepthFunc( GL_ALWAYS );
+ _gl.glEnable( GL_BLEND );
+ _gl.glBlendFunc( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA );
+
+ _gl.glBindFramebuffer( GL_FRAMEBUFFER , defaultFramebufferObject( ));
+ _gl.glClear(
+ GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+
+ _screenPlaneShader->use( );
+ _gl.glActiveTexture( GL_TEXTURE0 );
+ _gl.glBindTexture( GL_TEXTURE_2D , _accumulationTexture );
+ _gl.glActiveTexture( GL_TEXTURE1 );
+ _gl.glBindTexture( GL_TEXTURE_2D , _revealTexture );
+ _gl.glBindVertexArray( _quadVAO );
+ _gl.glDrawArrays( GL_TRIANGLES , 0 , 6 );
+ }
+
}
if ( _player && _elapsedTimeSliderAcc > _sliderUpdatePeriodMicroseconds )
@@ -1055,7 +1027,7 @@ void main()
{
if ( _player && ( _player->isPlaying( ) || _firstFrame ))
{
- _domainManager.addTime( renderDelta, _player->endTime() );
+ _domainManager.addTime( renderDelta , _player->endTime( ));
_firstFrame = false;
}
}
@@ -1111,35 +1083,21 @@ void main()
// _pickRenderer->setWindowSize( w , h );
//}
- if ( _msaaTextureColor != 0 )
+ if ( _accumulationTexture != 0 )
{
- int rw = width( ) * FRAMEBUFFER_SCALE_FACTOR;
- int rh = height( ) * FRAMEBUFFER_SCALE_FACTOR;
// Resize MSAA buffers
- glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor );
- glTexImage2DMultisample(
- GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB ,
- rw , rh , GL_TRUE );
-
- glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth );
- glRenderbufferStorageMultisample(
- GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 ,
- rw , rh );
-
- // And mid-buffers too!
-
- glBindTexture( GL_TEXTURE_2D , _midTextureColor );
- glTexImage2D( GL_TEXTURE_2D , 0 , GL_RGB ,
- rw , rh , 0 ,
- GL_RGB , GL_UNSIGNED_BYTE , nullptr );
-
- glBindRenderbuffer( GL_RENDERBUFFER , _midRBODepth );
- glRenderbufferStorage( GL_RENDERBUFFER , GL_DEPTH_COMPONENT32 ,
- rw , rh );
-
- glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , 0 );
- glBindTexture( GL_TEXTURE_2D , 0 );
- glBindRenderbuffer( GL_RENDERBUFFER , 0 );
+ _gl.glBindTexture( GL_TEXTURE_2D , _accumulationTexture );
+ _gl.glTexImage2D( GL_TEXTURE_2D , 0 , GL_RGBA32F , width( ) , height( ) ,
+ 0 ,
+ GL_RGBA , GL_FLOAT , nullptr );
+
+ _gl.glBindTexture( GL_TEXTURE_2D , _revealTexture );
+ _gl.glTexImage2D( GL_TEXTURE_2D , 0 , GL_R8 , width( ) , height( ) , 0 ,
+ GL_RED , GL_FLOAT , nullptr );
+
+ _gl.glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , 0 );
+ _gl.glBindTexture( GL_TEXTURE_2D , 0 );
+ //_gl.glBindRenderbuffer( GL_RENDERBUFFER , defaultFramebufferObject( ));
}
}
diff --git a/visimpl/OpenGLWidget.h b/visimpl/OpenGLWidget.h
index 421376b872441e0021f464e87bd988258abdb1d5..252d7136cdeeb8c542f2f39c966b0cc287257c17 100644
--- a/visimpl/OpenGLWidget.h
+++ b/visimpl/OpenGLWidget.h
@@ -50,6 +50,7 @@
#include <plab/plab.h>
#include <sstream>
+#include <QOpenGLFunctions_4_0_Core>
#include "types.h"
#include "render/Plane.h"
@@ -157,8 +158,7 @@ namespace visimpl
AB_REPEAT
} TPlaybackMode;
- class OpenGLWidget
- : public QOpenGLWidget , public QOpenGLFunctions_3_3_Core
+ class OpenGLWidget : public QOpenGLWidget
{
Q_OBJECT;
@@ -443,6 +443,8 @@ namespace visimpl
#endif
+ QOpenGLFunctions_4_0_Core _gl;
+
QLabel* _fpsLabel;
QLabel* _labelCurrentTime;
bool _showFps;
@@ -481,8 +483,8 @@ namespace visimpl
reto::ShaderProgram* _shaderClippingPlanes;
simil::SpikesPlayer* _player;
- std::shared_ptr<reto::ClippingPlane> _clippingPlaneLeft;
- std::shared_ptr<reto::ClippingPlane> _clippingPlaneRight;
+ std::shared_ptr< reto::ClippingPlane > _clippingPlaneLeft;
+ std::shared_ptr< reto::ClippingPlane > _clippingPlaneRight;
evec3 _planesCenter;
evec3 _planeNormalLeft;
evec3 _planeNormalRight;
@@ -570,13 +572,10 @@ namespace visimpl
// Render to texture
reto::ShaderProgram* _screenPlaneShader;
- unsigned int _msaaFrameBuffer;
- unsigned int _msaaTextureColor;
- unsigned int _msaaRBODepth;
-
- unsigned int _midFrameBuffer;
- unsigned int _midTextureColor;
- unsigned int _midRBODepth;
+ unsigned int _quadVAO;
+ unsigned int _weightFrameBuffer;
+ unsigned int _accumulationTexture;
+ unsigned int _revealTexture;
};
} // namespace visimpl
diff --git a/visimpl/particlelab/ParticleLabShaders.h b/visimpl/particlelab/ParticleLabShaders.h
index 896cc5756279e73a34d07a88e69b0fdc8eba4abe..0eb42eea18ddd9c92fae6b95d04fac10b4007533 100644
--- a/visimpl/particlelab/ParticleLabShaders.h
+++ b/visimpl/particlelab/ParticleLabShaders.h
@@ -28,7 +28,7 @@
namespace visimpl
{
-const static std::string PARTICLE_VERTEX_SHADER = R"(#version 400
+ const static std::string PARTICLE_VERTEX_SHADER = R"(#version 330
//#extension GL_ARB_separate_shader_objects: enable
uniform mat4 viewProjectionMatrix;
@@ -117,26 +117,56 @@ void main()
)";
-const static std::string PARTICLE_DEFAULT_FRAGMENT_SHADER = R"(
-#version 400
-in vec4 color;
+ const static std::string PARTICLE_DEFAULT_FRAGMENT_SHADER = R"(#version 330
+in vec4 color;
in vec2 uvCoord;
-out vec4 outputColor;
+
+layout (location = 0) out vec4 accumulation;
+layout (location = 1) out float reveal;
+
void main()
{
- vec2 p = -1.0 + 2.0 * uvCoord;
- float l = sqrt(dot(p,p));
- l = 1.0 - clamp(l, 0.0, 1.0);
- l *= color.a;
- outputColor = vec4(color.rgb, l);
+ vec2 p = -1.0 + 2.0 * uvCoord;
+ float l = sqrt(dot(p, p));
+ l = 1.0 - clamp(l, 0.0, 1.0);
+ l *= color.a;
+
+ vec4 c = vec4(color.rgb, l);
+
+ float weight = clamp(pow(min(1.0, c.a * 10.0) + 0.01, 3.0) * 1e8
+ * pow(1.0 - gl_FragCoord.z * 0.9, 3.0), 1e-2, 3e3);
+
+ accumulation = vec4 (c.rgb * c.a, c.a) * weight;
+ reveal = c.a;
}
)";
-const static std::string PARTICLE_SOLID_FRAGMENT_SHADER = R"(#version 400
+ const static std::string PARTICLE_ACC_DEFAULT_FRAGMENT_SHADER = R"(#version 330
in vec4 color;
in vec2 uvCoord;
-out vec4 outputColor;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec2 p = -1.0 + 2.0 * uvCoord;
+ float l = sqrt(dot(p, p));
+ l = 1.0 - clamp(l, 0.0, 1.0);
+ l *= color.a;
+
+ fragColor = vec4(color.rgb, l);
+}
+
+)";
+
+ const static std::string PARTICLE_SOLID_FRAGMENT_SHADER = R"(#version 330
+in vec4 color;
+in vec2 uvCoord;
+
+layout (location = 0) out vec4 accumulation;
+layout (location = 1) out float reveal;
+
void main()
{
vec2 p = -1.0 + 2.0 * uvCoord;
@@ -146,10 +176,37 @@ void main()
if( l > 0.8 )
discard;
- outputColor = vec4(color.rgb, 1.0f);
+ vec4 c = vec4(color.rgb, 1.0f);
+
+ float weight = clamp(pow(min(1.0, c.a * 10.0) + 0.01, 3.0) * 1e8
+ * pow(1.0 - gl_FragCoord.z * 0.9, 3.0), 1e-2, 3e3);
+
+ accumulation = vec4 (c.rgb * c.a, c.a) * weight;
+ reveal = c.a;
})";
-const static std::string PICK_VERTEX_SHADER = R"(#version 400
+ const static std::string PARTICLE_ACC_SOLID_FRAGMENT_SHADER = R"(#version 330
+in vec4 color;
+in vec2 uvCoord;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec2 p = -1.0 + 2.0 * uvCoord;
+ float l = sqrt(dot(p,p));
+ l = clamp(l, 0.0, 1.0);
+
+ if( l > 0.8 )
+ discard;
+
+ fragColor = vec4(color.rgb, 1.0f);
+}
+
+)";
+
+
+ const static std::string PICK_VERTEX_SHADER = R"(#version 330
#extension GL_ARB_separate_shader_objects: enable
uniform mat4 modelViewProjM;
@@ -189,7 +246,7 @@ void main()
id = gl_InstanceID;
})";
-const static std::string PICK_FRAGMENT_SHADER = R"(#version 400
+ const static std::string PICK_FRAGMENT_SHADER = R"(#version 330
uniform float radiusThreshold;
@@ -222,8 +279,7 @@ void main( )
outputColor = vec4(cc, 1.0);
})";
-const static std::string SHADER_PLANE_VERTEX = R"(
-#version 400
+ const static std::string SHADER_PLANE_VERTEX = R"(#version 330
in vec3 inPos;
@@ -243,8 +299,7 @@ void main( )
)";
-const static std::string SHADER_PLANE_FRAGMENT = R"(
-#version 400
+ const static std::string SHADER_PLANE_FRAGMENT = R"(#version 330
in vec4 outColor;
out vec4 outputColor;
@@ -256,6 +311,71 @@ void main( )
}
+)";
+
+
+ const static std::string SHADER_SCREEN_VERTEX = R"(#version 330
+
+// shader inputs
+layout (location = 0) in vec3 position;
+
+void main()
+{
+ gl_Position = vec4(position, 1.0f);
+}
+)";
+
+ const static std::string SHADER_SCREEN_FRAGMENT = R"(#version 330
+
+// shader outputs
+layout (location = 0) out vec4 frag;
+
+// color accumulation buffer
+uniform sampler2D accumulation;
+
+// revealage threshold buffer
+uniform sampler2D reveal;
+
+// epsilon number
+const float EPSILON = 0.00001f;
+
+// caluclate floating point numbers equality accurately
+bool isApproximatelyEqual(float a, float b)
+{
+ return abs(a - b) <= (abs(a) < abs(b) ? abs(b) : abs(a)) * EPSILON;
+}
+
+// get the max value between three values
+float max3(vec3 v)
+{
+ return max(max(v.x, v.y), v.z);
+}
+
+void main()
+{
+ // fragment coordination
+ ivec2 coords = ivec2(gl_FragCoord.xy);
+
+ // fragment revealage
+ float revealage = texelFetch(reveal, coords, 0).r;
+
+ // save the blending and color texture fetch cost if there is not a transparent fragment
+ if (isApproximatelyEqual(revealage, 1.0f))
+ discard;
+
+ // fragment color
+ vec4 accumulation = texelFetch(accumulation, coords, 0);
+
+ // suppress overflow
+ if (isinf(max3(abs(accumulation.rgb))))
+ accumulation.rgb = vec3(accumulation.a);
+
+ // prevent floating point precision bug
+ vec3 average_color = accumulation.rgb / max(accumulation.a, EPSILON);
+
+ // blend pixels
+ frag = vec4(average_color, 1.0f - revealage);
+}
)";
}