OpenGL terrain renderer does not dither between adjacent fields

Bug #722196 reported by Nicolai Hähnle
24
This bug affects 3 people
Affects Status Importance Assigned to Milestone
widelands
Fix Released
Low
Shevonar

Bug Description

In SDL/software rendering, the space between fields of different terrain types is made to look more fuzzy. The OpenGL terrain renderer should be extended to also do this, to make the changes between terrain types less harsh.

Tags: opengl terrain

Related branches

Nicolai Hähnle (nha)
Changed in widelands:
milestone: none → build17-rc1
Revision history for this message
Nicolai Hähnle (nha) wrote :
Changed in widelands:
status: New → Confirmed
Revision history for this message
SirVer (sirver) wrote :

Note that the OpenGL rendere does not necessarily need to dither. S2 did a special rendering round to draw the edges between triangles with different terrains. They had oval shaped images that were stretched to map on the edges. That looked really good and also removed the "triangle" feeling because the fields actually became rounded visually.

Revision history for this message
Shevonar (shevonar) wrote :

I looked at some S2 screenshots and think the ovals make really make a good look. However I think the edges are dithered additionaly. I wonder if we could have a look at RttR's code, how they produce S2-terrain with OpenGL. Just to get an idea ;)

Revision history for this message
SirVer (sirver) wrote :

Rttrs code is very readable and also open source (it is hosted here on launchpad as well, s25rttr). The dithering came from tansparent pixels in the textures.

Some fan uploded this to the internet
http://settlers2.net/wp-content/uploads/2011/08/Textures.png

You can see the "edge textures" on the bottom right site; they are formed like an arch with black pixels becoming transparent. That seems like they are dithered when in fact they are only overdrawn over the edges. Something like that should be easy to do with opengl, but of course one would need matching images for our textures. Also it could give an interesting effect to dither between some triangles (eg. water and steppe) and not others (eg wiese1 and wiese2).

Revision history for this message
Shevonar (shevonar) wrote :

Ah okay now I understand. I think the road-drawing code could be reused to achieve this effect. But instead of roads these little half-moon pictures (which one of the graphicians will hopefully make) are drawn. Since we need the alpha channel for these textures, there might be the chance to change the road-drawing code to use the alpha-channel as well. I remember that Astuur has requested this once in the forums (http://wl.widelands.org/forum/topic/839/?page=1#post-5788).

Revision history for this message
Shevonar (shevonar) wrote :

My progress is quite good I think: Have a look at the attachement. However there are some problems: The mountains look strange and there is a false row of pixels on the south west edges sometimes. That might get better, if one of the graphics team could give some love to the edge textures.
Another thing I don't like yet is that all the round edges look the same. The solution might be to provide more than one edge texture for every edge and choose one randomly. Currently I use only one fourth of the edge texture, so there could be at least 3 more differnt ones in the same file. This would need some modifications in code and of course someone who makes the graphics :)
Tell me what you think thus far and what should be improved. Next I will have a look at the roads.

Revision history for this message
Shevonar (shevonar) wrote :

Maybe this one looks better (checkmate is not a good map to show this feature, but it made finding bugs easier).

Revision history for this message
Nicolai Hähnle (nha) wrote :

Let me suggest a simpler way to implement those edges that should avoid the visual strangeness in the mountains and on grass.

Instead of having edge textures for every terrain individually, we can exploit the multi-texturing capabilities of OpenGL. We will have one single edge texture which has a single channel (i.e. greyscale, or luminance, or only an alpha channel) which is combined (via a glTexEnv) with the normal terrain texture when rendering the edges.

If, on top of that, you make sure to set up the texture coordinates for the normal terrain texture so that it is consistent with the texture coordinate computation for regular rendering, there should be no weirdness at all around the edges.

Revision history for this message
SirVer (sirver) wrote :

This looks really nice already. My main gripe (besides the bug line) is the edges to the water: it looks like the water was made convex, I feel it gives a more natural look if you make the terrain convex. See for example this screeny of S2 [1].

Also what nicolai suggests sounds reasonable. I wasn't aware that this could be done with opengl, but I assume that it will give superior results with less graphical work to be done which is a nice benefit.

[1] http://jh-isch.de/s2/images/patch152.jpg

Revision history for this message
Shevonar (shevonar) wrote :

I like Nicolai's idea too. I should have looked in the OpenGl reference more closely. I will make the changes.
I also agree with you SirVer, the problem is, that the drawing function just draws the terrain not being aware of what kind of terrain it is. But I will also see what I can do here. I think the change should also apply to other "liquid" terrains like lava and swamp.

Shevonar (shevonar)
Changed in widelands:
status: Confirmed → In Progress
assignee: nobody → Shevonar (shevonar)
Revision history for this message
Nasenbaer (nasenbaer) wrote :

I just tested your branch and I have to say: Wow very, very nice! The terrain looks already a lot nicer than in software rendering mode. Just the small line printed everywhere is of course annoying. I only had a very short look at your code and couldn't really figure out how it works, so my comments are kind of "non coder like", however:

* May it be, that the edge texture is used at an offset of one pixel? (I believe that's the first you checked, however still asking)
* May it be, that there is a function, that draws the transition between two textures, that is called after the edge was drawn and thus overwrites a part of the drawn texture with that line?
* May it be, that this has something to do with height calculation? The edges look fine, if the two nodes (the line is drawn between) have a different height -> e.g. i wondered why Crater.wmf had almost no places where these lines where drawn and checked it in the editor.

By the way the rendering does only work in greenland as you use a black and white picture there instead of black and transparent as in the other worlds.

Revision history for this message
Shevonar (shevonar) wrote :

I just fixed the edge texture bug. Really stupid bug, but on Windows the thumbnail background color is white, so you cannot say if it is white or transparent at a glance.

I will investigate the line problem in the next days. Maybe I can find the problem. Thanks for your ideas and feedback :)

Revision history for this message
Jens Beyer (qcumber-some) wrote :

I guess the thin line is coming from the missing texture border.
I don't have much experience with OpenGL but I can remember from reading this somewhere.

Just had a quick look, it's the function glTexImage2D which takes a border which then is 'replaced' by the first 'real' lines in the filtering procedure... but I'm not firm enough to verify if that's really the problem.

Revision history for this message
Shevonar (shevonar) wrote :

I could remove the line by setting the texture wrapping of the mask texture to GL_CLAMP_TO EDGE.

Merged at revision 6242

Changed in widelands:
status: In Progress → Fix Committed
Revision history for this message
Tino (tino79) wrote :

I just did a quick test, but it seems it does only work for horizontal edges.
I've attached 2 screenshots of my testmap, 0003 is software rendering, 0004 the opengl renderer.

Revision history for this message
Shevonar (shevonar) wrote :

I guess your system does not support multitexturing with 6 textures which is necessary for the edges to render properly. I though nowadays this is no problem. I cannot do much about that. The only thing I can think of is to draw the edges as separate triangles as I did before. The multitexturing solution is the better one IMHO.

Revision history for this message
Tino (tino79) wrote :

Ok, this would be a pity. I've only a nvidia notebook chipset...

Could you please have a last look at my glewinfo.txt/visualinfo.txt? Just to make sure it is really not supported.
Not that is some misconfiguration/linking in my buildsystem. Or a general problem with the win32 builds...

Revision history for this message
SirVer (sirver) wrote : Re: [Bug 722196] Re: OpenGL terrain renderer does not dither between adjacent fields

I also have some trouble to report. One of my system (Mac Os X 10.5,
intel 32bit) crashes in GameviewOpengl::draw_field without much comment
(I do not have a debugger on this system, I can install one if more
information is needed).
On my second system (OS X 10.6, 64bit) everything works wonderful (and
looks beautiful!).

Revision history for this message
Shevonar (shevonar) wrote :

@Tino #17: I couldn't find the capabilities of interest in the file you provided. Could you install the GPU Caps Viewer [1] and look in the OpenGL tab under GL_VERSION_2_0 for GL_MAX_TEXTURE_COORDS and GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS. The greater one of this two values is the maximum number of textures for multitexturing [2]

[1] http://www.geeks3d.com/20120202/gpu-caps-viewer-1-15-0-opengl-opencl-cuda-graphics-card-utility/
[2] http://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml

@SirVer #18: In your case the glewinfo file would be of interest: could you check if glActiveTexture, glMultiTexCoord2f, glMultiTexCoord2i are OK? These are the only OpenGL1.3 functions I use. Everything else should be supported since OpenGL 1.0 and should at least not crash the game.

I am a bit surprised that there are that many problems. Everything I use is very old or even depricated (maybe that is causing problems). OpenGL 1.3 is 10 years old and should be supported by every graphics card from the last 8 years I guess.

Revision history for this message
Shevonar (shevonar) wrote :

Some research brought me to this: "We have now learned that this bug is caused by a problem with OpenGL. Any Macs with openGL 1.2, which include most Leopard (10.5) computers will encounter this problem. Windows computers with openGL will also have this problem. The latest update of minecraft (specifically the lighting) requires graphics cards which support opengl 1.3 or higher. If you have GMA X3100 or GMA 950 (card jargon) you only have opengl support up to 1.2. Apple will NOT be updating their graphics cards or opengl support for Leopard 1.5." [1]
The problem is I use OpenGL 1.3 features and Mac OSX 10.5 supports only OpenGL 1.2. We can now blame Apple for such bad OpenGL support or I can try to work with OpenGL 1.2 only, but I think this will blow the code up, slow down the rendering speed or might even be impossible (haven't though it through yet). IMHO OpenGL 1.3 is 10 years old and should be supported everywhere but since this is not the case we should try not to rely on its features. Tell me what you think about the problem. Maybe we should open a new bug for this case.

[1] http://www.minecraftforum.net/topic/629182-mac-os-x-105-crash/

Revision history for this message
Tino (tino79) wrote :

Ok, i think it at least for me it is not caused by an obsolete graphic card and/or driver:
GPU Caps Viewer shows: OpenGL 3.3 (NVS 3100M/PCI/SSE2 with 229 ext.)

The parameters you are interested in are:
GL_VERSION_2_0
-- GL_MAX_TEXTURE_COORDS 8
-- GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 96

Revision history for this message
SirVer (sirver) wrote :

#20: We have to face reality. If this is not supported on 10.5 we have to work around that. Is it possible to detect on runtime the capabilities of installed OpenGL? If so, it would be easy to just instantiate another Renderer/Graphics class where this particular function is written without dithering (e.g. the old looks of OpenGL). We do not need to try that it looks as good on those systems, but a crash is not acceptable.

Revision history for this message
Shevonar (shevonar) wrote :

@Tino #21: In this case I have no idea what your OpenGL implementation is getting wrong. However it might be that I am using multitexturing in a way that is not exactly specified. For the vertical edges I use layers 1, 4, 5 and 6 with inactive layers 2 and 3. Maybe that is the problem. The fog of war shouldn't work on your system too.

@SirVer #22: I already found a way to work around the problem. On Mac OSX 10.5 multitexturing is not part of the OpenGL core but of the extension ARB_multitexturing. I just have to change some method names and it should work.

I try to provide a patch for both problems in the next day, maybe even until tonight.

Changed in widelands:
status: Fix Committed → In Progress
Revision history for this message
Shevonar (shevonar) wrote :

I was quicker than I though: Fixes for both problems are in trunk at revision 6245. Could you please check if your problems are fixed?

Revision history for this message
Tino (tino79) wrote :

Hi Shevonar, i've tested the latest trunk 6245, but unfortunately on my system still only horizonatal edged are dithered.
And you are right: The fog of war does not work, too.

I did some further tests:
- switching between 16/32bit depth
- updated the driver for my nvidia NV3100

The report from stdout.txt shows your new logs:
Graphics: Trying opengl
Graphics: Try to set Videomode 1024x768 32Bit
Graphics: Setting video mode was successful
Graphics: OpenGL: OpenGL enabled
Graphics: OpenGL: Double buffering enabled
Graphics: OpenGL: Max texture size: 8192
Graphics: OpenGL: Number of aux buffers: 4
Graphics: OpenGL: Number of stencil buffer bits: 0
Graphics: OpenGL: Maximum number of textures for multitextures: 96
Graphics: OpenGL: Version 3.3 "3.3.0"
Graphics: OpenGL: Textures may have any size
Graphics: OpenGL: Multitextures are supported

At the moment i am on a business trip, but i will check on my girlfriend's laptop (ati chipset) once i get home. Perhaps it is a hardware/driver issue ony my laptop.
I'll upload a new package and perhaps we can get some feedback from other windows users.
And the whole thing is not critical, because it does not lead to any crashes on win32. Perhaps we (better: you with your programming skills) can sort this out at some point...

Revision history for this message
Shevonar (shevonar) wrote :

Tino could you take a look at GL_VERSION_1_3 -> GL_MAX_TEXTURE_UNITS in the GPU Caps Viewer. I am really unsure which value is the correct one. The official specification says the bigger one of the two I asked you before, but most websites refer to GL_MAX_TEXTURE_UNITS. If this value is < 6 this is the right value. Thanks for your help again.

Revision history for this message
Tino (tino79) wrote :

GL_MAX_TEXTURE UNITS is 4.

A low value for this seems to be usual:
http://www.opengl.org/wiki/Textures_-_more
As i understand it, to avoid this limitation the rendering should be
done with a programmable (shader) pipeline and not with a fixed
pipeline.

But i suspect this would need much more code?

Am 21. Februar 2012 20:57 schrieb Shevonar <email address hidden>:
> Tino could you take a look at GL_VERSION_1_3 -> GL_MAX_TEXTURE_UNITS in
> the GPU Caps Viewer. I am really unsure which value is the correct one.
> The official specification says the bigger one of the two I asked you
> before, but most websites refer to GL_MAX_TEXTURE_UNITS. If this value
> is < 6 this is the right value. Thanks for your help again.
>
> --
> You received this bug notification because you are subscribed to
> widelands.
> https://bugs.launchpad.net/bugs/722196
>
> Title:
>  OpenGL terrain renderer does not dither between adjacent fields
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/widelands/+bug/722196/+subscriptions

Revision history for this message
Shevonar (shevonar) wrote :

Okay so I should test this constant to determine if the system is capable to use the multitexturing. My current implementation (not yet in trunk) will disable the edges completely if GL_MAX_TEXTURE_UNITS is not >= 6 (I use 6 texture units). I would love to learn GLSL (OpenGL Shader Language) to improve Widelands but the problem is Mac OSX 1.5 with its marginal OpenGL which Widelands should be compatible to (SirVer in #22). Mac OSX 10.5 supports only OpenGL 1.2 on some hardware [1] - GLSL was introduced with OpenGL 2.0.
The only way is to support both systems (yours and SirVer's) is to stack partly transparent triangles with 2 or 3 textures each. This is even more difficult than what I do now. Nevertheless I will try to implement it this way cause I have just now seen that Mac OSX 10.5 has GL_MAX_TEXTURE_UNITS = 4 on most hardware and will not draw the edges properly even if it does not crash after my last patch.
Still work to do for me. Expect more in the next days (as always ;-)).

[1] https://developer.apple.com/graphicsimaging/opengl/capabilities/GLInfo_1058.html

Revision history for this message
SirVer (sirver) wrote :

Shevonar, old systems will die out. If opengl runs stable on old systems without dithering the edges this will be fine. No need to provide all features on all systems. I suggest reverting to the original implementation that was in trunk before your merge on old systems (like 10.5). Do not try to support all and everything.

Revision history for this message
Shevonar (shevonar) wrote :

The current version does the following: It checks if "dithering the edges" = "multitexturing" is possible: if yes dither the edges, else use OpenGL without dithering the edges. I guess this is the best way to go. I will not follow the multiple triangle idea and leave it as it is now. I guess this means this bug is "Fix Committed" again. Feel free to reopen it if new problems occur.

A last question: Did it work for you on 10.5?

Changed in widelands:
status: In Progress → Fix Committed
Revision history for this message
SirVer (sirver) wrote :

>A last question: Did it work for you on 10.5?
Yes, it works on 10.5 (without dither) and 10.6 (with dither). I think
this is solved from the Mac Point of View. Tino, what is with your
windows problems?

Revision history for this message
Shevonar (shevonar) wrote :

I know why it does not work on Tino's system, but there is no good way to work around it.
I don't like old OpenGL on old systems :/ There are to many different implementations and versions that support different features and extensions. I don't know what is the best way to go :S

Revision history for this message
Tino (tino79) wrote :

Yeah, this is really weird:
Multitexturing via fixed pipeline was introduced with 1.3, but only
the high-end cards were able to mix more than 4 textures.
With OpenGL 2.0 they introduced the shaders and GLSL which is very
powerful and can mix many more textures, but would need a
reimplementation of the current algorithm. And of course you would
exclude all chipsets which do not support 2.0.
And perhaps OpenGL 3 or 4 would need further adaption of the algorithms...

So for now we have a very nice solution for old but powerful
OpenGL-1.3-cards but people with current chipsets (powerful shaders
but low fixed texturing pipeline) have to pass on dithering at
triangle edges and the fog of war. But of course they benefit on much
lower cpu usage.

I vote for setting this bug fixed and opening a new one "Implement
GLSL dithering and fog of war for OpenGL > 2.0" and target it to post
build 17

Tino

Am 23. Februar 2012 14:36 schrieb Shevonar <email address hidden>:
> I know why it does not work on Tino's system, but there is no good way to work around it.
> I don't like old OpenGL on old systems :/ There are to many different implementations and versions that support different features and extensions. I don't know what is the best way to go :S
>
> --
> You received this bug notification because you are subscribed to
> widelands.
> https://bugs.launchpad.net/bugs/722196
>
> Title:
>  OpenGL terrain renderer does not dither between adjacent fields
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/widelands/+bug/722196/+subscriptions

Revision history for this message
Shevonar (shevonar) wrote :

Thanks for writing down my thoughts Tino :)

I just fixed the detection of the number of supported textures to the correct constant GL_MAX_TEXTURE_UNITS. So at least the fog of war should work on systems with few textures.

Revision history for this message
Tino (tino79) wrote :

The fog of war is still not working on my system, because here m_caps.gl.multitexture is set to false due to m_caps.gl.max_tex_combined = 4.
The fog of war code is only in the "if (g_gr->caps().gl.multitexture)"-codeblock, is that intended?

Revision history for this message
Shevonar (shevonar) wrote :

Yes that is intended. The "else" code is exactly the same code that was used before my changes, and back then the fog of war worked. The "fog of war code" is just the NEW fog of war code. The old implementation uses the glColor() functions (My new implementation uses them also but I need to explicitly tell OpenGL to use it. Thats what I do in the "for of war code".)

Revision history for this message
SirVer (sirver) wrote :

Released in build17-rc1.

Changed in widelands:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.