2

We are working on a Three.js based WebGL project, and have trouble understanding how transparency is handled in WebGL. The image shows a doublesided surface drawn with alpha = 0.7, which behaves correctly on its right side. However closer to the middle strange artifacts appear, and on the left side the transparency does not seem to work at all.

http://emilaxelsson.se/sandbox/vis1/alpha.png

The problem can also be seen here: http://emilaxelsson.se/sandbox/vis1/ Has anyone seen anything similar before? What could the reason be?

2 Answers2

1

Your problem is that transparent objects needs to be sorted and rendered in a back-to-front order (if you try to change the opacity of your mesh from 0.7 (transparent) to 1.0 (opaque), you can see that the z-buffer works just fine).

See:

In your case it might be less trivial to solve, since I assume that you only have one mesh.

Edit: Just to summarize the discussion below. It is possible to achieve correct rendering of such a double-sided transparent mesh. To do this, you need to create 6 versions of the mesh, corresponding to 6 sides of a cube. Each version needs to be sorted in a back-to-front order based on the 'side of the cube' (front, back, left, right, top, bottom). When rendering choose the correct mesh (based on the camera viewing direction) and render that single mesh.

Mortennobel
  • 3,383
  • 4
  • 29
  • 46
  • Thanks! So I guess we would have to sort all primitives back-to-front before sending them to the vertex shader? :/ – Emil Axelsson May 26 '12 at 15:48
  • My best advice would be that you should not use transparency for the surface mesh. You could try to sort the primitives (the vertex indices) or subdivide you mesh so these can be rendered in correct order - but both solutions is not pretty and performance may suffer. – Mortennobel May 26 '12 at 16:19
  • @EmilAxelsson Your mesh looks like it is a (procedural) height map. In that case, you don't need to do any explicit sorting — just construct the mesh in back-to-front order in the first place. If the camera is outside the horizontal extent of the mesh, there are only four interesting cases (depending on which quadrant the viewpoint is in), so you could precompute all four and draw the appropriate one. – Kevin Reid May 26 '12 at 16:35
  • @KevinReid Great idea :) The way the camera currently navigates, I guess you could pick the correct mesh based on how the camera is rotated around the y-axis. – Mortennobel May 26 '12 at 18:06
  • Thanks for the great responses! Unfortunately, we plan to add the possibility to move the camera freely with the mouse, so the current four angles will not be used more often than any other. We also want the whole thing to work with arbitrary function surfaces, so I guess doing an intelligent subdivision would be difficult. We mostly intend to use transparency as an effect when fading between different "modes", so maybe we could sort the primitives before fading, and keep the mesh still while the surface is partially transparent. However, other possible solutions are still very appreciated :) – Emil Axelsson May 26 '12 at 20:08
  • I still believe that the idea is valid even with a free camera. But you would need to create 6 vertions of the mesh (so one version for each side of the box; left, right, top, bottom, back, front). This should work for arbitrary surfaces and is not complicated to implement. – Mortennobel May 26 '12 at 20:54
  • I have now implemented the method with 6 differently sorted meshes, and it seems to work really nice :) Thanks again for the awesome answers – Emil Axelsson May 27 '12 at 11:13
  • Good to hear that the idea it works :) Remember to mark the question solved :) – Mortennobel May 27 '12 at 13:02
0

The easy solution for your case (based on the picture you attached), without going to expensive sorting and multiple meshes, is to disable depth test and enable face culling. That produces acceptable results if you do not have any opaque objects in front of the mesh.

user2555515
  • 779
  • 6
  • 20