OpenBVE icon indicating copy to clipboard operation
OpenBVE copied to clipboard

Fix: issue with partial transparency

Open s520 opened this issue 5 years ago • 6 comments
trafficstars

This PR fixes the issue pointed out in https://github.com/leezer3/OpenBVE/issues/466#issuecomment-619619294. This issue occurs in at least v1.4.3.0 and later main programs and v1.7.0.0 and later viewers. This PR reverts the drawing of partially transparent faces to the viewer's method up to 1.6.0.0.

  • v1.4.3.0 (Main program) 1 4 3 0-main

  • v1.6.0.0 (RouteViewer) 1 6 0 0-route

  • v1.7.0.0 (RouteViewer) 1 7 0 0-route

  • This PR (RouteViewer) 1 7 2 0-route_fix

  • This PR (Main program) 1 7 2 0-main-fix

s520 avatar Sep 29 '20 16:09 s520

Very nice.

I'll take a proper look later or tomorrow

leezer3 avatar Sep 29 '20 16:09 leezer3

If I read what you've done right, I'm not entirely sure this isn't just hiding the issue in this case.

Essentially, if I understand what you've done, this code is pulling the transparent and semi-transparent faces into two disparate lists & drawing the semi-transparent faces separately afterwards. The issue with the linked file is that the drawing order is wrong https://github.com/leezer3/OpenBVE/issues/466#issuecomment-622055633

It shouldn't matter which list they're in.

Our real issue is where it selects the vertices to sort by here: https://github.com/leezer3/OpenBVE/blob/master/source/LibRender2/Objects/ObjectLibrary.cs#L245 It's using a simple implementation of the painters algorithm, which breaks when dealing with overlapping polygons.

leezer3 avatar Sep 30 '20 18:09 leezer3

Definitely hiding the issue. You'll see what I mean if you drop this tree with a replacement PNG texture in:

trees2-snow.zip

leezer3 avatar Sep 30 '20 19:09 leezer3

See what you think of this, it's a hack based on https://www.alecjacobson.com/weblog/?p=2750

if (Interface.CurrentOptions.TransparencyMode == TransparencyMode.Performance)
{
	SetBlendFunc();
	SetAlphaFunc(AlphaFunction.Greater, 0.0f);
	GL.DepthMask(false);
	foreach (FaceState face in VisibleObjects.AlphaFaces)
	{
		face.Draw();
	}
}
else
{
	SetAlphaFunc(AlphaFunction.Greater, 0.0f);
	GL.Disable(EnableCap.CullFace);
	GL.DepthFunc(DepthFunction.Less);
	foreach (FaceState face in VisibleObjects.AlphaFaces)
	{
		face.Draw();
	}
	GL.Enable(EnableCap.CullFace);
	GL.CullFace(CullFaceMode.Front);
	GL.DepthFunc(DepthFunction.Always);
	foreach (FaceState face in VisibleObjects.AlphaFaces)
	{
		face.Draw();
	}
	GL.Enable(EnableCap.CullFace);
	GL.CullFace(CullFaceMode.Front);
	GL.DepthFunc(DepthFunction.Lequal);
	foreach (FaceState face in VisibleObjects.AlphaFaces)
	{
		face.Draw();
	}
	GL.Enable(EnableCap.CullFace);
	GL.CullFace(CullFaceMode.Back);
	GL.DepthFunc(DepthFunction.Always);
	foreach (FaceState face in VisibleObjects.AlphaFaces)
	{
		face.Draw();
	}
	GL.Disable(EnableCap.CullFace);
	GL.DepthFunc(DepthFunction.Lequal);
	foreach (FaceState face in VisibleObjects.AlphaFaces)
	{
		face.Draw();
	}
	ResetOpenGlState();
}

You also need to add the following to the ResetOpenGlState function:

GL.CullFace(CullFaceMode.Front);

This will be slower at the minute on the old renderer, as display lists are broken. (and it obviously adds 3 draw passes for each face) I suppose we could possibly add this (or another approach) under the quality option, and keep the current as the middle.

leezer3 avatar Oct 01 '20 10:10 leezer3

I'll take a look at it over the weekend.

s520 avatar Oct 01 '20 11:10 s520

My change may be wrong, but I've tried your suggestion and it doesn't seem to solve the problem. test1 test2

Can you push your changes to GitHub?

Well, I would like to investigate techniques such as order-independent transparency. (for both performance and quality)

Also, we should change the transparency option item names to "Performance" and "Quality". It's hard to tell what the current names "Sharp" and "Smooth" are.

s520 avatar Oct 03 '20 08:10 s520