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

Author Topic: Graphics Corruption?  (Read 1631 times)

0 Members and 1 Guest are viewing this topic.

lyptt

  • Guest
Graphics Corruption?
« on: May 26, 2012, 07:50:27 pm »
I'm drawing some tiled sprites in the background on a RenderTexture, and about 50% of the time it'll show completely corrupted graphics for the first frame, and then after that it'll be fine, here's an example:



Has anyone else had this problem? I'm using one of the newer revisions currently available in the repo

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Graphics Corruption?
« Reply #1 on: May 26, 2012, 08:11:57 pm »
Can you show your code?
Laurent Gomila - SFML developer

lyptt

  • Guest
Re: Graphics Corruption?
« Reply #2 on: May 26, 2012, 08:26:50 pm »
Sure, on each game loop's draw command the following takes place:

void VideoManager::Draw(){
    std::lock_guard<std::mutex> lk(videoMutex);
    // Clear screen
    Game.Application->clear();
   
    Game.CurrentMap->Draw();
        Game.Application->display();
    for(unsigned i=0;i<RenderQueue.size();++i) {
        if(RenderQueue[i]){
            RenderQueue[i]->Draw();
        }
    }
   
    if(consoleView->Visible()){
        consoleView->Draw();
    }
   
    // Finally, display the rendered frame on screen
    Game.Application->display();
}

Where RenderQueue is a vector of SSprites, which are shared pointers to my classes that implement drawing. One of these is the control shown above in the screenshot, that draws tiled images.

On the create method it currently defines some hard coded values, all of the images referenced exist, so the problem's not to do with that:

    //Create our section data
    std::vector<MapSection> sectionRow;
    MapSection section;
    //Create a fake tileset with our debug tiles
    Tileset[0] = Data.TextureResourceWithID("Data/Map/BlankTile.png");
    Tileset[1] = Data.TextureResourceWithID("Data/Map/DebugTile.png");
    Tileset[2] = Data.TextureResourceWithID("Data/Map/BlockedTile.png");
    //Fill our section data with tiles
    for(int X = 0; X < SECTION_TILE_COUNT_X; X++){
        std::vector<int> currentRow;
        for(int Y=0; Y < SECTION_TILE_COUNT_Y; Y++){
            currentRow.push_back(2);
        }
        section.Tiles.push_back(currentRow);
    }
    //Set up our data
    currentSectionX = 0;
    currentSectionY = 0;
    currentX = 0;
    currentY = 0;
    sectionRow.push_back(section);
    Sections.push_back(sectionRow);
    //Finally assign our Sprite & Texture, and refresh the view
    MapTexture.create(Video.GetScreenDimensions().width+TILE_WIDTH,Video.GetScreenDimensions().height+TILE_HEIGHT);
    MapSprite = sf::Sprite(MapTexture.getTexture());
    MapSprite.setPosition(-TILE_WIDTH, -TILE_HEIGHT);

the Draw command firstly calls Refresh, and then calls the RenderWindow's Draw command, pointing it to the MapSprite sprite:
Game.Application->draw(MapSprite);

The Refresh command looks like this:
void Map::Refresh(){
    MapTexture.clear(sf::Color::Transparent);
    MapTexture.display();
    for(int X = 0 - TILE_WIDTH; X < SECTION_TILE_COUNT_X; X++){
        for(int Y=0 - TILE_HEIGHT; Y < SECTION_TILE_COUNT_Y; Y++){
            sf::Texture *tex = Tileset[2].get();
            tileBlitter = sf::Sprite(*tex);
            tileBlitter.setPosition(X*TILE_WIDTH, Y*TILE_HEIGHT);
            MapTexture.draw(tileBlitter);
        }
    }
    MapTexture.display();
}


I should note that yes I know calling refresh on every draw is expensive, but it's the only way to ever get anything more than garbage displaying for this view.

I've used an identical method for another view and that seems to work fine, I think it might be my reuse of sprites, but I did remember trying creating a new sprite to draw each tile during the loop and that didn't help either. Does SFML require sprites to exist after the data is rendered to the texture?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Graphics Corruption?
« Reply #3 on: May 26, 2012, 10:54:24 pm »
It's hard to debug something which is part of such a big project.

Would you be able to write a complete and minimal example that reproduces the problem?
Laurent Gomila - SFML developer

lyptt

  • Guest
Re: Graphics Corruption?
« Reply #4 on: May 27, 2012, 10:34:26 am »
Sure, here's it all flattened down into a main.cpp. Note that the problem is still happening with this example:

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>
#include "ResourcePath.hpp"
#include <tr1/memory>
#include <map>
using namespace std;
class MapSection {    
public:
    std::vector<std::vector<int> > Tiles;
private:
};

typedef std::tr1::shared_ptr<sf::Texture> STexture;

#define TILE_WIDTH 128
#define TILE_HEIGHT 72
#define SECTION_TILE_COUNT_X 11
#define SECTION_TILE_COUNT_Y 11

int main (int argc, const char * argv[])
{
    std::vector<std::vector<MapSection> >Sections;
    sf::RenderTexture MapTexture;
    sf::Sprite MapSprite;
    map<int, STexture> Tileset;
   
    // Create the main window
    sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML window");
   
    //Create our section data
    std::vector<MapSection> sectionRow;
    MapSection section;
    //Create a fake tileset with our debug tiles
    Tileset[0] = STexture(new sf::Texture());
    Tileset[0]->loadFromFile(resourcePath() + "BlankTile.png");
    Tileset[1] = STexture(new sf::Texture());
    Tileset[1]->loadFromFile(resourcePath() + "BlockedTile.png");
    Tileset[2] = STexture(new sf::Texture());
    Tileset[2]->loadFromFile(resourcePath() + "DebugTile.png");
    //Fill our section data with tiles
    for(int X = 0; X < SECTION_TILE_COUNT_X; X++){
        std::vector<int> currentRow;
        for(int Y=0; Y < SECTION_TILE_COUNT_Y; Y++){
            currentRow.push_back(2);
        }
        section.Tiles.push_back(currentRow);
    }
    //Set up our data
    unsigned int currentSectionX;
    unsigned int currentSectionY;
    unsigned int currentX; //These map the TOP LEFT viewable tile
    unsigned int currentY;
    sf::Sprite tileBlitter;
   
    currentSectionX = 0;
    currentSectionY = 0;
    currentX = 0;
    currentY = 0;
    sectionRow.push_back(section);
    Sections.push_back(sectionRow);
    //Finally assign our Sprite & Texture, and refresh the view
    MapTexture.create(1280+TILE_WIDTH,720+TILE_HEIGHT);
    MapSprite = sf::Sprite(MapTexture.getTexture());
    MapSprite.setPosition(-TILE_WIDTH, -TILE_HEIGHT);        

    // Start the game loop
    while (window.isOpen())
    {
        // Process events
        sf::Event event;
        while (window.pollEvent(event))
        {
                // Close window : exit
                if (event.type == sf::Event::Closed)
                        window.close();
           
                // Escape pressed : exit
                if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
                        window.close();
        }

        // Clear screen
        window.clear();
       
        MapTexture.clear(sf::Color::Transparent);
        MapTexture.display();
        for(int X = 0 - TILE_WIDTH; X < SECTION_TILE_COUNT_X; X++){
            for(int Y=0 - TILE_HEIGHT; Y < SECTION_TILE_COUNT_Y; Y++){
                sf::Texture *tex = Tileset[2].get();
                tileBlitter = sf::Sprite(*tex);
                tileBlitter.setPosition(X*TILE_WIDTH, Y*TILE_HEIGHT);
                MapTexture.draw(tileBlitter);
            }
        }
        MapTexture.display();
       
        // Draw the sprite
        window.draw(MapSprite);
       
        // Draw the string
        //window.draw(text);

        // Update the window
        window.display();
    }

        return EXIT_SUCCESS;
}
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Graphics Corruption?
« Reply #5 on: May 27, 2012, 10:44:14 am »
Thanks :)

But can't it be even simpler? Can't you get rid of all the "tilemap" logic, and just draw a simple sprite on a simple render-texture?

By the way, what's your OS and graphics card?
Laurent Gomila - SFML developer

lyptt

  • Guest
Re: Graphics Corruption?
« Reply #6 on: May 27, 2012, 10:52:20 am »
OS X 10.7, and I have a Radeon HD 6870.

I've simplified it a bit and discovered it's the RenderTexture I'm drawing to that's getting corrupted, specifically if I do this:

                sf::Texture *tex = Tileset[0].get();
                tileBlitter = sf::Sprite(*tex);
                tileBlitter.setPosition(X*TILE_WIDTH, Y*TILE_HEIGHT);
                MapTexture.draw(tileBlitter);

I get corruption, but if I do this:

sf::Texture *tex = Tileset[0].get();
                tileBlitter = sf::Sprite(*tex);
                tileBlitter.setPosition(X*TILE_WIDTH, Y*TILE_HEIGHT);
                window.draw(tileBlitter);

I don't.

I'm creating the RenderTexture and its Sprite the same way I always do, with the following code:

    MapTexture.create(1280+TILE_WIDTH,720+TILE_HEIGHT);
    MapSprite = sf::Sprite(MapTexture.getTexture());
    MapSprite.setPosition(-TILE_WIDTH, -TILE_HEIGHT);        

I've tested and it's not due to creating a large RenderTexture, any size seems to still cause the corruption.
« Last Edit: May 27, 2012, 11:04:29 am by lyptt »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Graphics Corruption?
« Reply #7 on: May 27, 2012, 08:18:23 pm »
Can't you just put these 4 lines in a typical minimal example? If you want us to help you, we need something that we can test quickly, and which focuses on the problem -- not on drawing tiles.
Laurent Gomila - SFML developer

lyptt

  • Guest
Re: Graphics Corruption?
« Reply #8 on: May 27, 2012, 11:51:48 pm »
Sorry, I didn't realize copying and pasting the sample I've given was such a time consuming process. Don't bother after all, I'll just go use something else.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Graphics Corruption?
« Reply #9 on: May 28, 2012, 10:22:04 am »
It's not copying and pasting which is time consuming, it's finding the error within all these lines of code. Since it's obvious that 75% of the code is still irrelevant to the problem, it's much easier if you remove it before posting the code.

There's no reason to draw a complete tilemap if your problem is about drawing a sprite on a render-texture. Unless you tell me that a simpler code doesn't reproduce the problem, of course.
Laurent Gomila - SFML developer