@ -119,58 +119,83 @@ namespace MWRender
nullptr , shaderManager . getShader ( " core/ripples_simulate.comp " , { } , osg : : Shader : : COMPUTE ) ) ;
}
void RipplesSurface : : traverse( osg : : NodeVisitor & nv )
void RipplesSurface : : updateState( const osg : : FrameStamp & frameStamp , State & state )
{
if ( ! nv . getFrameStamp ( ) )
state . mPaused = mPaused ;
if ( mPaused )
return ;
if ( nv . getVisitorType ( ) = = osg : : NodeVisitor : : CULL_VISITOR )
constexpr double updateFrequency = 60.0 ;
constexpr double updatePeriod = 1.0 / updateFrequency ;
const double simulationTime = frameStamp . getSimulationTime ( ) ;
const double frameDuration = simulationTime - mLastSimulationTime ;
mLastSimulationTime = simulationTime ;
mRemainingWaveTime + = frameDuration ;
const double ticks = std : : floor ( mRemainingWaveTime * updateFrequency ) ;
mRemainingWaveTime - = ticks * updatePeriod ;
if ( ticks = = 0 )
{
size_t frameId = nv . getFrameStamp ( ) - > getFrameNumber ( ) % 2 ;
state . mPaused = true ;
return ;
}
const auto & player = MWMechanics : : getPlayer ( ) ;
const ESM : : Position & playerPos = player . getRefData ( ) . getPosition ( ) ;
const MWWorld : : Ptr player = MWMechanics : : getPlayer ( ) ;
const ESM : : Position & playerPos = player . getRefData ( ) . getPosition ( ) ;
mCurrentPlayerPos = osg : : Vec2f (
std : : floor ( playerPos . pos [ 0 ] / sWorldScaleFactor ) , std : : floor ( playerPos . pos [ 1 ] / sWorldScaleFactor ) ) ;
osg : : Vec2f offset = mCurrentPlayerPos - mLastPlayerPos ;
mLastPlayerPos = mCurrentPlayerPos ;
mState [ frameId ] . mPaused = mPaused ;
mState [ frameId ] . mStateset - > getUniform ( " positionCount " ) - > set ( static_cast < int > ( mPositionCount ) ) ;
mState [ frameId ] . mStateset - > getUniform ( " offset " ) - > set ( offset ) ;
mCurrentPlayerPos = osg : : Vec2f (
std : : floor ( playerPos . pos [ 0 ] / sWorldScaleFactor ) , std : : floor ( playerPos . pos [ 1 ] / sWorldScaleFactor ) ) ;
const osg : : Vec2f offset = mCurrentPlayerPos - mLastPlayerPos ;
mLastPlayerPos = mCurrentPlayerPos ;
auto * positions = mState [ frameId ] . mStateset - > getUniform ( " positions " ) ;
state . mStateset - > getUniform ( " positionCount " ) - > set ( static_cast < int > ( mPositionCount ) ) ;
state . mStateset - > getUniform ( " offset " ) - > set ( offset ) ;
for ( size_t i = 0 ; i < mPositionCount ; + + i )
{
osg : : Vec3f pos = mPositions [ i ]
- osg : : Vec3f (
mCurrentPlayerPos . x ( ) * sWorldScaleFactor , mCurrentPlayerPos . y ( ) * sWorldScaleFactor , 0.0 )
+ osg : : Vec3f ( sRTTSize * sWorldScaleFactor / 2 , sRTTSize * sWorldScaleFactor / 2 , 0.0 ) ;
pos / = sWorldScaleFactor ;
positions - > setElement ( i , pos ) ;
}
positions - > dirty ( ) ;
osg : : Uniform * const positions = state . mStateset - > getUniform ( " positions " ) ;
mPositionCount = 0 ;
for ( std : : size_t i = 0 ; i < mPositionCount ; + + i )
{
osg : : Vec3f pos = mPositions [ i ]
- osg : : Vec3f ( mCurrentPlayerPos . x ( ) * sWorldScaleFactor , mCurrentPlayerPos . y ( ) * sWorldScaleFactor , 0.0 )
+ osg : : Vec3f ( sRTTSize * sWorldScaleFactor / 2 , sRTTSize * sWorldScaleFactor / 2 , 0.0 ) ;
pos / = sWorldScaleFactor ;
positions - > setElement ( i , pos ) ;
}
positions - > dirty ( ) ;
mPositionCount = 0 ;
}
void RipplesSurface : : traverse ( osg : : NodeVisitor & nv )
{
const osg : : FrameStamp * const frameStamp = nv . getFrameStamp ( ) ;
if ( frameStamp = = nullptr )
return ;
if ( nv . getVisitorType ( ) = = osg : : NodeVisitor : : CULL_VISITOR )
updateState ( * frameStamp , mState [ frameStamp - > getFrameNumber ( ) % 2 ] ) ;
osg : : Geometry : : traverse ( nv ) ;
}
void RipplesSurface : : drawImplementation ( osg : : RenderInfo & renderInfo ) const
{
osg : : State & state = * renderInfo . getState ( ) ;
osg : : GLExtensions & ext = * state . get < osg : : GLExtensions > ( ) ;
size_t contextID = state . getContextID ( ) ;
size_t currentFrame = state . getFrameStamp ( ) - > getFrameNumber ( ) % 2 ;
const std : : size_t currentFrame = state . getFrameStamp ( ) - > getFrameNumber ( ) % 2 ;
const State & frameState = mState [ currentFrame ] ;
if ( frameState . mPaused )
{
return ;
}
auto bindImage = [ contextID , & state , & ext ] ( osg : : Texture2D * texture , GLuint index , GLenum access ) {
osg : : GLExtensions & ext = * state . get < osg : : GLExtensions > ( ) ;
const std : : size_t contextID = state . getContextID ( ) ;
const auto bindImage = [ & ] ( osg : : Texture2D * texture , GLuint index , GLenum access ) {
osg : : Texture : : TextureObject * to = texture - > getTextureObject ( contextID ) ;
if ( ! to | | texture - > isDirty ( contextID ) )
{
@ -180,52 +205,42 @@ namespace MWRender
ext . glBindImageTexture ( index , to - > id ( ) , 0 , GL_FALSE , 0 , access , GL_RGBA16F ) ;
} ;
// Run simulation at a fixed rate independent on current FPS
// FIXME: when we skip frames we need to preserve positions. this doesn't work now
size_t ticks = 1 ;
// PASS: Blot in all ripple spawners
mProgramBlobber - > apply ( state ) ;
state . apply ( frameState . mStateset ) ;
for ( size_t i = 0 ; i < ticks ; i + + )
if ( mUseCompute )
{
if ( mUseCompute )
{
bindImage ( mTextures [ 1 ] , 0 , GL_WRITE_ONLY_ARB ) ;
bindImage ( mTextures [ 0 ] , 1 , GL_READ_ONLY_ARB ) ;
bindImage ( mTextures [ 1 ] , 0 , GL_WRITE_ONLY_ARB ) ;
bindImage ( mTextures [ 0 ] , 1 , GL_READ_ONLY_ARB ) ;
ext . glDispatchCompute ( sRTTSize / 16 , sRTTSize / 16 , 1 ) ;
ext . glMemoryBarrier ( GL_ALL_BARRIER_BITS ) ;
}
else
{
mFBOs [ 1 ] - > apply ( state , osg : : FrameBufferObject : : DRAW_FRAMEBUFFER ) ;
state . applyTextureAttribute ( 0 , mTextures [ 0 ] ) ;
osg : : Geometry : : drawImplementation ( renderInfo ) ;
}
ext . glDispatchCompute ( sRTTSize / 16 , sRTTSize / 16 , 1 ) ;
ext . glMemoryBarrier ( GL_ALL_BARRIER_BITS ) ;
}
else
{
mFBOs [ 1 ] - > apply ( state , osg : : FrameBufferObject : : DRAW_FRAMEBUFFER ) ;
state . applyTextureAttribute ( 0 , mTextures [ 0 ] ) ;
osg : : Geometry : : drawImplementation ( renderInfo ) ;
}
// PASS: Wave simulation
mProgramSimulation - > apply ( state ) ;
state . apply ( frameState . mStateset ) ;
for ( size_t i = 0 ; i < ticks ; i + + )
if ( mUseCompute )
{
if ( mUseCompute )
{
bindImage ( mTextures [ 0 ] , 0 , GL_WRITE_ONLY_ARB ) ;
bindImage ( mTextures [ 1 ] , 1 , GL_READ_ONLY_ARB ) ;
bindImage ( mTextures [ 0 ] , 0 , GL_WRITE_ONLY_ARB ) ;
bindImage ( mTextures [ 1 ] , 1 , GL_READ_ONLY_ARB ) ;
ext . glDispatchCompute ( sRTTSize / 16 , sRTTSize / 16 , 1 ) ;
ext . glMemoryBarrier ( GL_ALL_BARRIER_BITS ) ;
}
else
{
mFBOs [ 0 ] - > apply ( state , osg : : FrameBufferObject : : DRAW_FRAMEBUFFER ) ;
state . applyTextureAttribute ( 0 , mTextures [ 1 ] ) ;
osg : : Geometry : : drawImplementation ( renderInfo ) ;
}
ext . glDispatchCompute ( sRTTSize / 16 , sRTTSize / 16 , 1 ) ;
ext . glMemoryBarrier ( GL_ALL_BARRIER_BITS ) ;
}
else
{
mFBOs [ 0 ] - > apply ( state , osg : : FrameBufferObject : : DRAW_FRAMEBUFFER ) ;
state . applyTextureAttribute ( 0 , mTextures [ 1 ] ) ;
osg : : Geometry : : drawImplementation ( renderInfo ) ;
}
}