Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Semi-transparent texture rendering #2

Closed
deathcap opened this issue Apr 24, 2014 · 7 comments
Closed

Semi-transparent texture rendering #2

deathcap opened this issue Apr 24, 2014 · 7 comments

Comments

@deathcap
Copy link
Member

Completely opaque or transparent voxels render well, but semi-transparent (0 < alpha < 1) looks like this:

screen shot 2014-04-23 at 8 24 32 pm

The reason for the problem is mostly clearly visible in voxel-example 90dd7cad53ba32358220114a1f7f77776565663c - on the lava at the bottom. When viewed from the side it renders as expected, through the ores and stone above it:

screen shot 2014-04-23 at 8 24 05 pm

but when viewed from the bottom, the faces from the very top of the terrain show through:

screen shot 2014-04-23 at 8 24 15 pm

something to do with sorting in depth order..

@deathcap
Copy link
Member Author

ref mikolalysenko/ao-shader#2

@mikolalysenko
Copy link
Member

Correct rendering requires z-sorting, but you can do a simpler/dumber thing that might look ok and get you 70% there.

Here is how it works:

  1. Split all translucent facets out into a separate buffer from the main vertex buffer. This will require modifying voxel-mesher almost certainly.
  2. When rendering the world you need to do 2 passes:
  • First draw all opaque/transparent voxels without using any blending and with the depthMask enabled.
  • Then disable depthMask (but keep the depthTest on!), turn on blending and draw all transparent faces.

This is how most games do transparency, though it is obviously not the "correct" solution. Still I think it should be possible to implement it within voxel.js, but it will just take some work.

@deathcap
Copy link
Member Author

deathcap commented May 1, 2014

Agreed the simplified scheme is probably sufficient. I think that's the technique Minecraft used, until recently.

edit: found MC calls this the "render pass" (0=opaque, 1=transparent).

@deathcap
Copy link
Member Author

Some progress testing in voxel/voxel-mesher#5

screen shot 2014-06-12 at 1 03 43 pm

still to do: separate voxel buffers

@deathcap
Copy link
Member Author

With the blockModel property, voxels are now meshed separately and drawn after - seems to solve the semi-transparency (translucency?) problem ok, water now shows as (with a 'custom' cube model):

screen shot 2014-06-13 at 11 39 34 pm

The interior faces (not shown here) can be annoying, also the artifacts at the boundaries between the voxels (quite visible in this screenshot), since each voxel is rendered on its own (not meshed together like 'solid' voxels). So this sort of works, but could use improvement.

Are these steps strictly necessary:

  • First draw all opaque/transparent voxels without using any blending and with the depthMask enabled.
  • Then disable depthMask (but keep the depthTest on!), turn on blending and draw all transparent faces.

? I'm drawing both passes with:

  gl.enable(gl.CULL_FACE)
  gl.enable(gl.DEPTH_TEST)
  gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
  gl.enable(gl.BLEND)
  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true)

all always enabled at the beginning of the render method. Haven't tried messing with gl.DEPTH_MASK yet.

Also, I'm thinking if maybe a fourth category of voxels would be worth it — in addition to 1. solid opaque 2. solid transparent 3. "porous" (= non-solid = custom block model), 4. translucent solid. These voxels (4) could be greedily meshed together, as with (1) and (2), but would be rendered in the second pass like (3), so 0<alpha<1 textures would display as expected. Full-height water, lava, and other fluids would fall into this category. Or grouping these together with custom block models may be sufficient..

@deathcap
Copy link
Member Author

to do: try gl.DEPTH_MASK, or some other way to fix these interior faces:

screen shot 2014-06-14 at 12 06 41 am

@deathcap deathcap changed the title Sort back-to-front for semi-transparent texture rendering Semi-transparent texture rendering Jun 14, 2014
@deathcap
Copy link
Member Author

Testing with gl.depthMask(gl.TRUE) in 2nd shader (and false in 1st shader).. needs more work:

screen shot 2014-06-14 at 2 12 33 pm

leaving it off for now, I think the current implementation is good enough for the time being. There are some other minor glitches in 0.13.0 dependent on the draw order:

screen shot 2014-06-14 at 1 45 39 pm

but when viewed from the other side:

screen shot 2014-06-14 at 1 45 31 pm

Also found this good article: http://stackoverflow.com/questions/3388294/opengl-question-about-the-usage-of-gldepthmask


Since the original problem of translucent rendering is now implemented as of 0.13.0, closing this issue, but opening new issues for the remaining problems:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants