kpreid / all-is-cubes

Yet another block/voxel game; in this one the blocks are made out of blocks. Runs in browsers on WebGL+WebAssembly.
https://kpreid.dreamwidth.org/tag/all+is+cubes
Apache License 2.0
160 stars 8 forks source link

Light model for transparency #338

Open kpreid opened 1 year ago

kpreid commented 1 year ago

If we want volumetric transparency to look consistent across block boundaries, then we need to compute the light within and across blocks in a way which will result in consistent rendering without seams between blocks. For example, if we have these two rays:

A   B
\   \
+\---\-+------+
| \   \|      |
|  \   \      |
|   \  |\     |
+----\-+-\----+
|######|######|
|######|######|
|######|######|
+------+------+

then ray A passes through a horizontal surface, then the transparent volume, and strikes a horizontal surface, but ray B passes through an additional vertical surface, and the two cube volumes that B passes through must combine to produce the same color (modulo intended local variations in lighting). The current light rendering model does not achieve this goal, because the smooth light calculation is completely different depending on the normal of the crossed/struck face — it interpolates light values in the two perpendicular (tangent) directions.

The obvious solution is to use a 3-dimensional interpolation analogous to our existing 2-dimensional interpolation, which can answer the question “what is the light at this 3d point”. This will cost more shader time — it may be worth trying again the idea I previously had of doing the texture loads in the vertex shader rather than the fragment shader. (That will mean doing a cube of 27 loads per triangle, but maybe that's still a win compared to doing 8 in the fragment shader.)

However, even given that interpolation we still need to work out what arithmetic on the light point samples will then produce the desired seamless volumetric light. We might have to integrate along the ray (which will not require more samples).

It might turn out that this is impractical, in which case we may want to drop the idea of light-scattering transparent substances entirely, and use only absorbing volumetric transparency, which is not affected by the illumination of the material, perhaps combined with diffuse reflection at the surface of the material (which will require rendering to do index-of-refraction comparisons to decide how much reflection versus transmission occurs at a boundary).

A different benefit of the 3-dimensional interpolation, though, is that it will improve the lighting of voxel surfaces that are not at the surface of their containing cube — right now, there's a sharp transition between the depth of the light sampling.

kpreid commented 1 year ago

Another fallback option for the overall lighting impression is to replace smooth lighting with intentionally pixelated lighting, so that the between-block variation is not as relatively prominent an artifact.