News:

Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

Hardware accelerated display, OpenGL back-end & Simutrans 3D

Started by eddielexx, January 02, 2010, 03:38:33 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ters

I've been contemplating doing blending between texture levels in hardware, though I haven't checked if it's doable without pixel shaders.

As for the bleeding at the edges, I think the solution is to offset the texture coordinates a little. I thought I did so in my demo/test. With mipmaps, there will be additional constraints. Adding a transparent border will cause bleeding into transparency rather than the next image, which isn't good for ground textures. Repeating the row and column on the opposite side of the image would work there.

prissi

Any object that has been modified has the dirty flag set. Unfourtunately objects that are modified heeds to trigger redraws of larger areas. That is why we made so much effort with the dirty tile buffer.

Markohs

@Ters: Yeah, maybe just offsetting will be enough, write the 128x128 tiles and just render the inner 126x126, so they overlap a bit might work, I'll test it. Anyway we can allways CLAMP as you did and wait for a complete 3D terrain render on the future that will look afc better.

@prissi: I'll have it a look. I guess you refer to ding_t::flags bit 1? Does grund_t::flags dirty *ONLY* refer to the ground or includes buildings and ways over it?

prissi

dirty gound means everything on it is dirty. Well and dirty things are dirty. Both are resetted during redraw.

Markohs

Ok, thank you prissi.

Just posting this, I know some people in the forum like to see some images of work in progress. ;)

Debugging that window, requires FOUR 1024x1024 texture atlas to be drawn each frame, Ters code creates those on-the-fly, posting them:

pak64 behaves better with this backend, because more images fit in each atlas. The current plan is making those atlas persistant in the video card memory and re-use them, saving bandwidth between the CPU and the video card.

in-game:



tex 1



tex 2:



tex 3:



tex 4:






Markohs

Making some tests I saw something I don't understand fully so I'll ask here for the case somebody knows.

I made atlas images form all the images generated in grund_besch_t::calc_water_level, and everything is going good, but on the pak128 atlas some dark tiles are generated (on the lower right of the image) and I can't figure out where are then used in, I raised one mountain in-game and can't see them really used anywere. Are they necessary? Do they come from an unused climate?

PAK128



PAK64:


Dwachs

Both atlases have the same number of images, so nothing seems to be wrong. Maybe you did not raise the mountain high enough?

There is a debug message at grund_besch_t::calc_water_level, line 444, which should tell you, which climate is present at which height.
Parsley, sage, rosemary, and maggikraut.

VS

It is climate "rocky", which is usually so high that it is covered with snow even in summer. Mind your snowline settings :) Further, game starts in January, which is definitely winter. Fast forward to July, any you may actually see something ;)

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!

Markohs


Markohs

Forcing a 8192x8192 resident texture buffer and using your algorithm Ters, modified to re-use the same buffer each frame (only rebuilding it if it's completely full) and just mapping/unmapping if there is any change that frame, I got a quite significant performance boost, now you can use it completely zoomed out at a similar speed than the SDL version.

The texture corrupts itself in some strange way I could not identify still (I must have made an error somewere, on it), it looks funny:



VS


My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!


Ters

I just wonder if that texture might be too big for Simutrans players' hardware.

Markohs

I'll just let it use the biggest one he can use.

Well, I fixed the bug, did some tests. I was too optimistic. We were at 0,3 fps at max zoom out (more or less), we have 3 fps now with this implementation in the same situation. WinGDI gives 22 fps. This buffered texture display will be used in some things I think, mainly the GUI and maybe smokes and something else, we'll see.

Well, we improved 1000%, it's a start.

Next thing, static geometry buffers, working on it...

Markohs

Can anybody explain me why when drawing the landscape certain grunds are not drawn and are drawn later as dings? Why is this necessary? In the example I post here, whoudn't just draw them in this same pass render the exact same result?

The items are processed in rows, so why this objects are treated and drawn later?

Thank you!


Markohs

mmm... I think I understand why this happens, it's because of vehicles or pedestrians that need to be rendered too (later) and might become partially visible because of images that get extra heigh like that factory? That whould make sense since we don't have any z-buffer here, no? And slopes are affected too since they also can have the same effect (they can hide objects that are in the rear, but only slopes that go upwards, the ones going south don't force drawing as ding)?

Dwachs

Quote from: Markohs on November 20, 2012, 12:14:51 AM
The items are processed in rows, so why this objects are treated and drawn later?
For the first row of images it seems that this is not necessary. Could be room for optimization. (Also in the second row, too many tiles are drawn later imho)

In general, tiles are drawn later if tile graphics and/or vertical walls have to cover something on the tiles behind. Then there are bridge heads, which also are sometimes drawn differently. And there can be ways that carry a flag to trigger this behavior (used with rivers sometimes?).
Parsley, sage, rosemary, and maggikraut.

Markohs

 Thanks for the explanation, reading the code now. :) Yea, I *think^there are a few cases when display as ding is not 100% needed, and it's not allways cleared correctly on modifications. But the impact on performance is not really important I think.

I think I almost understand how this works now. Not trivial stuff at all, I'm not 100% sure I can simulate the complete current behaviour using a z-buffer, not on the station overlays at least. I'll see how can I manage this.

Markohs

I've been debugging my last code for about 25 hours, it was showing NOTHING. I rewrote vertex arrays objects code, debugged the vertex coordinates, wrote fragment shader programs, looked at OpenGL 4 , looked in forums like crazy, and at the end... I was rendering the quads against a texture I forgot to update from the PBO (but I didn't forget to initialize to full transparent, so the quads were invisible). Don't you hate when you lose so much time looking everywere around and the problem was so trivial?

Oh man... Well, at least I advanced now. ;)


Fabio

It's horrible, man.
Like just when you work hours and you feel you must start it all over again until a light turns on and you get in a moment how you should have done from the start.

Markohs


Ters

The last few years, I've begun saying "If you want to do <something>, then you must do <something>." An example would be "If you want to show a window on the screen, then you must show the window on the screen", which means that I've spent lots of time figuring out why my window doesn't appear, only to realize I've coded everything (making the window, population it with items, giving it the right size and position) except the one line of code that tells the window to become visible.

Markohs


isidoro

Quote from: Markohs on November 26, 2012, 01:16:37 AM
[...]
I rewrote vertex arrays objects code, debugged the vertex coordinates, wrote fragment shader programs, looked at OpenGL 4 ,
[...]

Have you considered the people with cards not capable of OpenGL 3+?  For instance, in Linux, with each version of xserver, most over two years old ATI/AMD cards are kept away...  In this computer, I have to go to the free drivers and have OpenGL 2.1 with a 2010 card...


Ters

I think it's best to stay at the 2.1 level, though there are a few nice things in 3.x. OpenGL 4.0 is likely too new for the Simutrans target group, based on how I recently had to help out ensuring that the nightlies were able to tun on a pre-Pentium III CPU.

Markohs

I'm just using the primitives described in 3.2 document:

http://www.opengl.org/registry/doc/glspec32.core.20091207.pdf

But I think all the code I used so far is compatible to 2.1 (an maybe even older), I don't use any shading language still, but maybe when I have to deal with player colors and night colors I'll have to use some of that. 2.1 supports shading language too, I'll try to stick to 2.0 ofc.

I discarded using the 4.0 language, that required modifying lots of Ters code and I feared of backwards compatibility as isidoro mencioned already. And required vertex and fragment shaders.

Markohs

Advancing here, looks like I'm missing something on height mapping, using get_hoehe(), but not on all tiles maps correctly. Pasting the code hre for the case somebody has any suggestion.

position is filled in ground_t::calc_bild()

const koord3d pos(pos.x,pos.y,this->get_hoehe());


    IMAGE_ATLAS *img = atlas->get_image(image->bild_nr);

    if (img == NULL) {
        return;
    }

    koord3d position = position_in;

    position.x = position_in.x;
    position.y = -position_in.y;
   
    KOORD_VAL w = get_tile_raster_width();

   
    const GLfloat image_w = (GLfloat) image->w;
    const GLfloat image_h = (GLfloat) image->h;
    const GLfloat image_x = (GLfloat) image->x;
    const GLfloat image_y = (GLfloat) image->x;

    const sint16 height = tile_raster_scale_y( 2*TILE_HEIGHT_STEP, w );


    GLfloat x = (GLfloat) (position.y*w/2) + (position.x*w/2);
    GLfloat y = (GLfloat) (position.x*height/2) - (position.y*height/2);

    // elevate acording tile height
    y = y - tile_raster_scale_y(position.z*TILE_HEIGHT_STEP,w);

    x = x+image_x;
    y = y+image_y;

    const GEOM_QUAD quad(
            x,y,
            x + image_w, y + image_h ,
            map_texel(img->u1), map_texel(img->v1),
            map_texel(img->u2), map_texel(img->v2),
            ATLAS_RGBAVAL(255, 255, 255, 255)
    );
    quads.push_back(quad);



Combuijs

This line:

const GLfloat image_y = (GLfloat) image->x;

does not look too healthy  8)
Bob Marley: No woman, no cry

Programmer: No user, no bugs



Markohs

Oh man, that was it, thanks a lot!! :)

four eyes see more than two, that's for sure. ;)

Markohs

Just storing the landscape on a persistant VBO boosted performance again from my tests:

Old optimized implementation is Ters one,  not resetting texture cache each frame
New one is the same old implementation but drawing the landscape from a persistant VBO and texture, saving CPU and PCI bandwidth.

Max zoom out, removing the outer water tiles.

Frame time    FPS
60 ms            16    Old
35 ms            25 (simutrans capped I think)

The display is still not perfect, misses slopes, sea, rivers and ways (even the number of elements in the VBO seems to not impact performance in a significant way) and it's not perfectly alligned with the rest of elements at all zoom levels. The old code contains lots of optimizations and hard to understand coordinate manipulations, I have to have them another look to fully understand them. If anyone wants to have a look at the code and suggest something I'll be happy to hear your oppinions. I know code is not optimized, and some decisions might be questionable, nothing is written on stone yet. Work in progress.

I tested on comic96 PAK, that pak is a bit special in the way that it loads a savegame instead of generating a new random world on the splash screen, pak128 and others will crash or render unexpected results (the geometry buffer has to be reset, just handled savegame loading so far) . Only initial geometry is displayed, it doesn't keep track of changed tiles yet.

EDIT: A binary here. Have in mind that at start it will give low fps until the images are cached on the video card, will give small freezes every time a new object appears to get drawn (as it happened before) Pak128.britain works too, just start the game, select the pak, press, "new game" and close the new dialog to be able to move around the map.

prissi

just put a file names demo.sve into the pak folder will load it on start. Or specify "-load xzy.sve" on the command line.

BTW: It crashed prior to any action and requires to switch of Data execution prevention.

Markohs

Thx. :)

About the data execution prevention, strange, here it runs without that setting on.

prissi

MAybe this was rather due to crashing. I mean I might have anyway not luck on this very old XP machine.

Markohs

Well, thx for trying anyway, soon I'll have a stable version with all the new code.

Markohs

I'm trying to find a good place in code where I can add calls to my texture atlas filling routines.

So far I was checking obj_reader_t::read_nodes , but that function is too generic, I thought it whould be a idea to check for their type and just register the ones I'm doing now, obj_way,  but saw that pak file format is not designed that way, and obj_way it's just a descriptor (besch), that might have images as child.

Is way_reader_t::register_obj the bast place to hook this code? examining the descriptor and add the images it might have?

Thanks