Author Topic: [Solved] Textures  (Read 21247 times)

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
[Solved] Textures
« on: July 07, 2010, 10:07:26 pm »
I split this off from the lighting thread because they're not really related.

Problems with texture mapping
  • Textures drawn incorrectly
  • Black spots from polygon bounds
  • Slow as a snail in a coma



Addressing point 1

Had to change the way you approached texture bundles. I've modified the SurfaceSet class (code files should be attached to this post). Basically, rather than 1 big Surface (which was being tiled on the texturedPolygon routine, causing the weird image), it creates a seperate Surface for each texture.

Also, Globe.cpp was modified in the Globe::setTexture method, when enumerating polygons
Code: [Select]
void Globe::setTexture(SurfaceSet *texture)
{
_texture = texture;
_texture->setPalette( this->getPalette() );
draw();
}

and Globe::draw was modified thusly
Code: [Select]
texturedPolygon(getSurface(), (Sint16*)&x, (Sint16*)&y, (*i)->getPoints(), _texture->getFrame((*i)->getTexture())->getSurface(), 0, 0);

Addressing points 2 & 3
I'm going to have a play at trying to re-write the texturedPolygon, hoping to improve performance, and might fix the polygon edges... We'll see...
« Last Edit: July 20, 2010, 09:14:48 pm by pmprog »

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2162
    • View Profile
Re: Textures
« Reply #1 on: July 08, 2010, 12:11:17 am »
Thanks, your solution was the same one I had in mind, I just never got around to it. I'll have a look later and add it in.

For future reference, I'd appreciate it if you posted code changes as patch files instead, as they're much easier to manage. I even created a topic about it to feel all important. :P

As for the texturedPolygon() routine, I did consider rewriting it to use pixel-level drawing instead of blits (as they seem to be much slower), but then I found out my evil twin the other X-Com remake seems to use the exact same method for drawing their globe, only theirs actually works fast! I've pretty much compared the code line by line and can't really figure out what am I doing wrong compared to theirs.
« Last Edit: July 08, 2010, 12:15:07 am by SupSuper »

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: Textures
« Reply #2 on: July 08, 2010, 12:34:51 am »
Yeah, sorry, like I said in your other topic, didn't realise there was a Patch feature. I'm pretty new to SVN, we use SourceSafe at work.

Hmmm, interesting that theirs runs fine. Tell me, do you redraw the globe every frame?

Potentially, what you could do to speed things up, is buffering the globe post-world, but pre-objects (such as bases, UFOs and other craft). This way, when a draw request is done, then you simply blit that across, then overlay the objects.

Then, when the world is rotated, you update the buffered surface, again without objects. This means you're not having to calculate and recalculate and render 20+ textured polygons each frame, cutting down to a single blit.

After all, there's no point in recalcing everything if the view is exactly the same

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2162
    • View Profile
Re: Textures
« Reply #3 on: July 08, 2010, 01:34:35 am »
Hmmm, interesting that theirs runs fine. Tell me, do you redraw the globe every frame?

Potentially, what you could do to speed things up, is buffering the globe post-world, but pre-objects (such as bases, UFOs and other craft). This way, when a draw request is done, then you simply blit that across, then overlay the objects.

Then, when the world is rotated, you update the buffered surface, again without objects. This means you're not having to calculate and recalculate and render 20+ textured polygons each frame, cutting down to a single blit.

After all, there's no point in recalcing everything if the view is exactly the same
This is already how it worked (you can see for yourself if you comment out all the base markers stuff or just go back a few revisions), I just wanted to see the base placement in action so I didn't bother to optimize it and place the base markers in a separate surface, I'll do it eventually.

As a general rule, the draw() function in objects takes care of redrawing the buffered surface whenever a relevant property changes. While the blit() function takes care of rendering the buffered surface onto the screen (this is what happens every frame). So everything is blitted every frame onto the screen (as it should or you'd get horrible tearing effects) but everything isn't "redrawn" every frame (like, say, a button only redraws itself when it's pressed/released). It's kinda ambiguous naming because I'm not good with names. :P

It still doesn't solve the problem that merely attempting to move the globe will still bring the game to a near-halt (which, again, doesn't happen with X-Com Reloaded). Hell, even a DOS game could do it, it's kinda embarrassing. :P

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: Textures
« Reply #4 on: July 08, 2010, 01:55:54 pm »
I understand what you're saying, but I probably didn't explain myself very well.

Globe::draw() draws effectively two things: Firstly, the actual planet, and Secondly, any bases, craft and other overlays.

If you add line
Code: [Select]
cout << "Globe:draw();";to the top of the draw function, you'll find this is rendered every frame (which makes sense to animate the bases and craft). However, it also means you're rendering the globe using texturedPolygon 20+ times per frame, every frame.

Can I suggest adding the following to Globe
Code: [Select]
 private:
    Surface *_world;
    void drawWorld();

drawWorld() then does performs the polygon enumeration and texturedPolygons onto the _world surface
draw() would then perform a bit of _world onto this->getSurface(), as well as drawing the bases and craft.

Globe::zoom() and Globe::rotate() would then have a call to drawWorld() to update the planet as it is changed.

Does this make more sense? If not, if I get chance tonight I'll fix up the code and post a patch file.
« Last Edit: July 08, 2010, 02:01:07 pm by pmprog »

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: Textures
« Reply #5 on: July 08, 2010, 09:24:18 pm »
Okay, the attached patch file makes several changes.

1. Changes the SurfaceSet like my previous file uploads
2. Buffers the globe in _world
3. New drawWorld() method, only called when rotating or zooming
4. Reduced loop count in drawWorld() (was from draw())

This has sped things up q bit, and when not rotating, plays very nicely.
Rotating and zooming still locks up for about 3-5 tenths of a second.

Interestingly, if you comment out the following lines
Code: [Select]
 if( !backFace )
    texturedPolygon(_world->getSurface(), (Sint16*)&x, (Sint16*)&y, (*i)->getPoints(), _texture->getFrame((*i)->getTexture())->getSurface(), 0, 0);

Whilst you can't see the land, it rotates rapidly... your bottleneck must be here



Edit: Interestingly, if you leave drawWorld() alone, and comment out the draw() line:
Code: [Select]
SDL_BlitSurface( _world->getSurface(), &copyRct, this->getSurface(), &copyRct );
Again, it doesn't draw the world (at least to the screen, but it is blitting the textured polygons), and it's fast again... There must be something...
« Last Edit: July 08, 2010, 09:32:17 pm by pmprog »

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: Textures
« Reply #6 on: July 08, 2010, 09:45:09 pm »
Here you go... All working.

The bottleneck was on SDL_SetColorKey() in your Surface constructor. I removed the SDL_RLEACCEL flag, and bingo...

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2162
    • View Profile
Re: Textures
« Reply #7 on: July 08, 2010, 10:06:28 pm »
I'm sorry you still went to the trouble, but I said in my post that I had already took care of the marker slowdown and that wasn't what was slowing down textures. It's been with me from the beginning. :)

Edit:
Here you go... All working.

The bottleneck was on SDL_SetColorKey() in your Surface constructor. I removed the SDL_RLEACCEL flag, and bingo...
Oh hey, thanks for that. ;D Funny how things that are supposed to accelerate always end up backfiring.
« Last Edit: July 08, 2010, 10:09:45 pm by SupSuper »

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: Textures
« Reply #8 on: July 08, 2010, 10:35:00 pm »
I'm sorry you still went to the trouble, but I said in my post that I had already took care of the marker slowdown and that wasn't what was slowing down textures. It's been with me from the beginning. :)
Wasn't really much trouble, define a new function, copy and paste the code, make some minor alterations... Took longer to find out what the problem was than to fix it  ;D

Here you go... All working.

The bottleneck was on SDL_SetColorKey() in your Surface constructor. I removed the SDL_RLEACCEL flag, and bingo...
Oh hey, thanks for that. ;D Funny how things that are supposed to accelerate always end up backfiring.
Yeah, I must admit, when I saw all your surfaces being created as SDL_SWSURFACE, I was wondering if that was the bottleneck and switched them to SDL_HWSURFACE. It didn't work, so I moved on, where I noticed the SDL_RLEACCEL flag, I though, there's no RLE encoded images here, so I did a quick search and also saw several bug reports linked to it. That led me to remove it, and hey presto...

Edit: Oh, the code doesn't take into account the zoomed textures, but that should be trivial to add
« Last Edit: July 08, 2010, 10:37:00 pm by pmprog »

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2162
    • View Profile
Re: Textures
« Reply #9 on: July 08, 2010, 11:20:15 pm »
Ok it's all in the SVN now so there should be no more confusions. :)

Offline Eeyoocah5Moh

  • Sergeant
  • **
  • Posts: 28
    • View Profile
Re: [Solved] Textures
« Reply #10 on: July 10, 2010, 06:02:25 pm »
Why thread is marked as solved? Black dots are still here in last build.

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: [Solved] Textures
« Reply #11 on: July 10, 2010, 08:02:58 pm »
I did that, because yeah... I completely forgot about that point, despite writing it in the top of the post  ;D

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2162
    • View Profile
Re: Textures
« Reply #12 on: July 13, 2010, 05:26:44 am »
It's a bit weird that texturedPolygon() produces holes where filledPolygon() didn't. Maybe it's worth comparing both to find the problem.

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: Textures
« Reply #13 on: July 15, 2010, 09:19:51 pm »
Yeah, before I went on holiday, I had a quick play with the floor() function you were using on polarToCart(). Now I'm back I'll have another look.

Thanks for the mention on the blog BTW

Edit: Think I know the answer to the blit issue
Quote from: SDL_gfx
01210         switch (dst->format->BytesPerPixel) {
01211         case 1:
01212                 memset(pixel, color, dx+1);
01213                 break;
01214         case 2:
01215                 pixellast = pixel + dx + dx;
01216                 for (; pixel <= pixellast; pixel += pixx) {
01217                         *(Uint16 *) pixel = color;
01218                 }
01219                 break;
01220         case 3:
01221                 pixellast = pixel + dx + dx + dx;
Hello! On 256 color surfaces (as is OpenXcom), it sets dx (which is width) + 1 bytes. In the case of the other formats, and in the _HLineTextured function, which is used by texturedPolygon, it only draws dx (width) for each line.

This is why you didn't get the missing pixels on the single colour version. I'm going to contact the owner of SDL_gfx and ask him about it

Edit 2: Bug tracker on SDL_gfx
https://sourceforge.net/tracker/?func=detail&aid=3030674&group_id=294774&atid=1244910
« Last Edit: July 16, 2010, 08:44:21 pm by pmprog »

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: Textures
« Reply #14 on: July 20, 2010, 02:22:01 pm »
Had an email from the SDL_gfx tracker saying that the bug has been fixed, not downloaded and tried it yet though

Edit: It works!  ;D
« Last Edit: July 20, 2010, 09:15:19 pm by pmprog »