Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Scrolling background - maybe a shader?  (Read 2695 times)

0 Members and 1 Guest are viewing this topic.

Wedvich

  • Newbie
  • *
  • Posts: 2
    • View Profile
Scrolling background - maybe a shader?
« on: April 18, 2012, 03:06:03 pm »
Hi guys! I'm working on a game for a school project, and I've built my engine around SFML. It's a pretty basic vertical scroller, with a moving background to simulate movement. My current implementation of this scrolling background consists of using two sprites with the same seamless texture, moving both of them down for each frame in my game loop, and when one sprite falls out of the visible part of the screen, I move it up above the other sprite, etc. etc. I currently have three layers of this blended on top of eachother for a parallaxing effect, but they all function in the same way.

It's working as intended, but I'm having some problems with tearing between the two sprites when the framerate drops or it's otherwise disturbed. Not by much, but enough that I get an ugly 1-2 pixel gap between them. I've added a few pixels overlap to compensate somewhat for this, and it helps, but it still happens from time to time. Maybe the code I use would be helpful:

Code: [Select]
void TropoBackground::Update( float elapsedSeconds )
{
// Move layers
for ( int i = 0; i < LAYER_COUNT; ++i )
{
m_sprites[ i ][ 0 ].move( 0, m_parallaxSpeed[ i ] * elapsedSeconds );
m_sprites[ i ][ 1 ].move( 0, m_parallaxSpeed[ i ] * elapsedSeconds );

if ( m_sprites[ i ][ 0 ].getPosition().y >= m_maxY[ i ] - m_overlap )
{
m_sprites[ i ][ 0 ].setPosition( 0, -m_maxY[ i ] + m_overlap );
}

if ( m_sprites[ i ][ 1 ].getPosition().y >= m_maxY[ i ] - m_overlap )
{
m_sprites[ i ][ 1 ].setPosition( 0, -m_maxY[ i ] + m_overlap );
}
}
}

The render function is called after this, so I don't really see any obvious reason why this tearing would be happening. But I've been thinking that OpenGL might be able to help me with a simpler and better solution. What I have in mind is, wouldn't it be possible to use one sprite with a static position, then have OpenGL repeat the texture and use a sf::Shader to "scroll" it? Going from idea to implementation is harder though as I have no idea what I'm doing, but I'm assuming I can pass a time-scaled offset to the shader and let it move the texture for me? But then again, would I be using a vertex or a pixel shader for this? And how would I get the texture to repeat indefinitely, thus creating the seamless, endless scrolling effect? And should I just let the offset grow into infinity, or should I reset it at some interval to avoid it growing too large/wrapping (it would have to run for about 5,5 years for wrapping to occur at the current speed, but maybe it's a problem for the shader)? Or is using a shader for this just inherently a bad idea? Any input or pointers on this is appreciated.

Wedvich

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Scrolling background - maybe a shader?
« Reply #1 on: April 20, 2012, 05:09:31 pm »
Okay, after knocking my head against the wall very roughly for a while, I came up with a working solution. In case anyone else is having the same problems with how to do it, here's the new update logic:

Code: [Select]
void TropoBackground::Update( float elapsedSeconds )
{
// Move layers
for ( int i = 0; i < LAYER_COUNT; ++i )
{
m_offsets[ i ] += m_parallaxSpeed[ i ] * elapsedSeconds;
}
}

And the fragment shader used while rendering:
Code: [Select]
uniform sampler2D tex;
uniform float tex_offset;

void main()
{
vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s, gl_TexCoord[0].t - frac(tex_offset)));
gl_FragColor = texel;
}

tex_offset is set to its corresponding m_offsets value with setParameter in my render function, and tex is set to sf::Shader::CurrentTexture there as well. And remember setRepeated( true ); on the textures.

This is the first time I've ever touched GLSL (or shaders in general), so if anyone knows a better/faster implementation then please let me know!