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

Transparent emissive voxels #504

Closed
9 of 12 tasks
kpreid opened this issue Aug 6, 2024 · 6 comments
Closed
9 of 12 tasks

Transparent emissive voxels #504

kpreid opened this issue Aug 6, 2024 · 6 comments
Labels
area: data Things related to the data structures underlying the world, and the functions that manipulate them. area: graphics kind: incomplete A feature is partially implemented; the current state of the code is inconsistent

Comments

@kpreid
Copy link
Owner

kpreid commented Aug 6, 2024

I suspect that there are bugs where blocks which are purely emissive, and neither absorb nor reflect light (that is, their .color.alpha() is zero), are not handled correctly, since visibility has previously been determined entirely in terms of “color”, i.e. reflectance. Whether or not there are bugs, there aren't enough tests.

  • Add test cases for rendering emissive blocks; make sure they and their voxels are not accidentally treated as invisible, or other alpha-related mistakes.
    • Purely emissive blocks (745d33c, but wgpu is not fixed yet and the test is marked to not count as a failure until then)
    • Emissive and also semi-transparent blocks (f5ed049)
  • Fix raytracing of emissive blocks (3faf0a5, 0faa5e5)
  • Fix GPU rendering of emissive blocks (ba98a0e for proper color math, ba0ba93 and e106660 for missing meshes and textures)
  • Ensure that all items that involve visibility (e.g. EvaluatedBlock::visible()) document that visibility is not the same thing as alpha ≠ 0. (Done-ish in ca2b069)
  • Figure out what we want TransparencyOption to do with emissive voxels. #512
  • Ensure that all uses of OpacityCategory are clearly defined. (Should it be renamed to VisibilityCategory, perhaps? Should it internally distinguish alpha from mixed cases?)
  • Consider renaming the color fields of Atom and Evoxel to reflectance, to remind readers that this is not the only optical property.
  • Work out the proper per-voxel calculation of transparent+emission vs. material thickness are and
    • update the docs (01d1af0, 417632e)
    • update the renderers and block evaluation to perform that calculation (7aab55c)
@kpreid kpreid added kind: incomplete A feature is partially implemented; the current state of the code is inconsistent area: graphics area: data Things related to the data structures underlying the world, and the functions that manipulate them. labels Aug 6, 2024
kpreid added a commit that referenced this issue Aug 8, 2024
…de emission.

Part of fixing <#504>.
This doesn't test or fix the rendering behavior.
@kpreid
Copy link
Owner Author

kpreid commented Aug 8, 2024

I have found a core problem in the raytracer: Surface::to_lit_color() has an incorrect signature, because it returns a non-premultiplied RGBA color, so it is not capable of representing emission properly, and it ends up applying the alpha to the emission.

I should replace it with premultiplied alpha, or whatever other combo of color and opacity/transmittance makes the arithmetic fit together efficiently.

@kpreid
Copy link
Owner Author

kpreid commented Aug 8, 2024

Poking at what should happen here has made me come to a new realization of how Premultiplied Alpha Really Is The Correct Representation (for this and several other applications). You know how one of the things people say about premultiplied alpha is that it trivially allows representing additive blending, by setting the alpha to zero and the RGB nonzero? And if you're like me, you've probably thought “okay cute trick but when would I ever actually want that in particular” or “I'm not sure the units work out”?

Well, that is exactly what we need in this situation. The RGB components are “what is the intensity of light toward the camera, from this object”, and the alpha component is “what fraction of the light behind this object is blocked”. These things in fact vary independently. (Well, not quite. Physics tells us, I think, that any process that emits light is also going to absorb some light. But that's not relevant at the level of PBR based on specifying bulk material properties.)

Notably, the ColorBuf accumulator type already represents color in premultiplied form (except that it stores transmittance, (1 − alpha), not alpha), so it already has the exact semantics we want. We can just pass a ColorBuf to Accumulator::add(), instead of a Rgba.

(This also implies that our current conversion through non-premultiplied Rgba for the output of ColorBuf is incorrect; we should, at a minimum, tone-map the output first so that the nonlinear transform is applied to the actual light intensity.)

kpreid added a commit that referenced this issue Aug 9, 2024
kpreid added a commit that referenced this issue Aug 9, 2024
Part of fixing <#504>.
With this change, the raytracer now correctly renders blocks that
have light emission only (at least, in volumetric mode; the surface-only
mode is multiplying the emission by the number of voxels, which is
not really the right outcome).

It is incoherent or at least undesirable to multiply light emissions
by the reflectance color’s alpha. To avoid doing that, the cleanest
solution is to switch to premultiplied alpha, where the accumulator
only uses the alpha to determine the effect on future (more distant)
surfaces.

Conveniently, we already have a type that implements exactly this
representation: `ColorBuf`! Or, not exactly — the alpha is actually
complemented (1 − α), making it transmittance instead, but that’s
what we actually need.

This commit breaks the `icons` rendering test, but we need to fix
the same bug in `wgpu` rendering and also update the icon to match
the new paradigm, so it's going to be broken sometime unless I were to
squash all three changes into one commit, which I don't want to do.
kpreid added a commit that referenced this issue Aug 9, 2024
Part of fixing <#504>.

Note that even though we replaced small values with references,
this has a neutral-to-positive effect on mesh benchmarks.
kpreid added a commit that referenced this issue Aug 9, 2024
Part of fixing <#504>.

Emissive-only blocks are still broken.
kpreid added a commit that referenced this issue Aug 9, 2024
Part of fixing <#504>.
Previously, emission would be reduced by alpha, which I am now defining
to be the wrong approach. So, within the new paradigm, the jetpack
exhaust needs to be dimmer to produce the desired visual results.
The good(?) news is, this means the jetpack no longer lights up brightly
because the new rendering better matches what light propagation does.

This commit makes the renderer tests pass again by blessing the new
`icons` output.
@kpreid
Copy link
Owner Author

kpreid commented Aug 9, 2024

As of e6f1dfe, emissive-only works in raytracer but not wgpu. I've fixed some bugs but the output is still blank; it seems likely that the entire mesh is missing for some reason, but I haven’t dug into that yet.

kpreid added a commit that referenced this issue Aug 12, 2024
kpreid added a commit that referenced this issue Aug 12, 2024
Part of fixing <#504>.
We still don’t have the right rendering, but at least the geometry
exists now.
kpreid added a commit that referenced this issue Aug 12, 2024
Part of fixing <#504>.
Multi-voxel emissive-only meshes are still not working in the
rendering test.
kpreid added a commit that referenced this issue Aug 12, 2024
Part of fixing <#504>.
This is the last of the bugs affecting the `emission_only` render test!
@kpreid
Copy link
Owner Author

kpreid commented Aug 12, 2024

As of e106660, I've fixed all the bugs preventing emissive-only rendering from working, but there is still a bunch of possibly desirable cleanup as listed above.

@kpreid
Copy link
Owner Author

kpreid commented Aug 17, 2024

As of 7aab55c, emission is correctly adjusted for semi-transparent voxels. 417632e adds public documentation of how block emission and opacity is interpreted.

@kpreid
Copy link
Owner Author

kpreid commented Aug 17, 2024

I'm going to call this close enough to done now. Of the un-done tasks:

  • Figure out what we want TransparencyOption to do with emissive voxels. #512 is its own issue now.
  • OpacityCategory didn’t prove to be particularly troublesome; let's just revisit it when we find another reason to.
  • Renaming color to reflectance, and maybe splitting out the alpha channel from it, might be a good idea but feels overly disruptive for now; again, let's revisit it whenever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: data Things related to the data structures underlying the world, and the functions that manipulate them. area: graphics kind: incomplete A feature is partially implemented; the current state of the code is inconsistent
Projects
None yet
Development

No branches or pull requests

1 participant