RenderKit / ospray

An Open, Scalable, Portable, Ray Tracing Based Rendering Engine for High-Fidelity Visualization
http://ospray.org
Apache License 2.0
997 stars 182 forks source link

OSPRay 2.x lacks cylinders/cones, leading to inefficient rendering of molecular graphics #421

Closed tachyon-john closed 3 years ago

tachyon-john commented 4 years ago

At present there does not seem to be an efficient way of rendering cylinders as required for molecular graphics. While I very much appreciate the new OSPRay 2.x "curves" geometry (some minor similarity to the motivation for the "polycylinder" primitive I put in Tachyon eons ago), unfortunately it is not possible to use the OSPRay 2.x "curve" geometry type to create cylinders that don't have extra sphere caps at the ends, which is undesirable in a wide variety of situations. OSPRay 1.x had an explicit cylinder type, which was effective for molecular scenes. I implemented a cylinder placeholder hack using the "curves" geometry type with OSP_LINEAR and OSP_ROUND, which is almost what is required, except for the extra spheres. It would be ideal to either add a new cross section shape type, like OSP_ROUND_NOJOINTS that behaves the same as OSP_ROUND but eliminates the extra spheres, or to re-add the cylinder geometry type explicitly. At present, while my proof of concept "curves" hack is cute, it can't be used in practice, so VMD has to fallback to generating huge triangle meshes for cylindrical geometry. The same issue(s) apply for cones that are often used to display vector fields and so-called "porcupine plots" of molecular dynamics action in manuscript figures.

johguenther commented 4 years ago

Hi John, we think about an option to choose the "cap style" for round linear curves. Should the alternative better be "open" (like previous cylinders), or "closed"/"flat" (i.e., a disk at the end)?

To the cones: I don't think OSPRay ever had an explicit "cones" geometry, but by varying the radius of the round linear curves (and a different cap style than a sphere, see above) you should get the cones, shouldn't you?

Cheers, Johannes

tachyon-john commented 4 years ago

Hi Johannes, VMD actually uses cylinders with both "open" and "flat" cap styles, so if OSPRay 2.x adds "curve" cap options for those, I will end up using both of them. You're right that the OSPRay 1.x lacked cones, but since the new "curves" API allows per-vertex radii, I assumed that you must have conic geometry in the embree back-end, yes? So if we get the open/flat cap style in the curves API, I think I can use the same trick to generate usable cones for the kinds of things VMD normally needs. BTW, I was trying to test the per-vertex radii in the curves API and I'm getting an unhelpful error callback, that just says: "embree internal error 'invalid argument'", but no errors from the higher level OSPRay calls. Any idea what that might be?

tachyon-john commented 4 years ago

One thing I forgot to mention regarding having the flat caps on cylinder/cone geometry: When drawing certain geometry, VMD actually controls the capping of the leading and trailing vertex/control point independently (two bits indicate whether the cylinder's leading vertex is capped, and whether the trailing vertex is capped). When drawing transparent geometry especially, it is useful to precisely control cap placement. Another option for partial capping, if you don't like the idea of offering that as part of the "curves" API, is to provide a disc primitive, which is just a minor specialization of a plane primitive with an inner and outer radius, so you can render both a solid disc (inner radius == 0.0), and an annular ring or "washer" (nonzero inner radius, and larger outer radius).

johguenther commented 4 years ago

Our plan is to add flags to control whether the start and/or end cap (sphere) is there.

And we consider adding a new disk geometry (rather generalize "spheres" to either be a sphere, oriented disk, or ray-facing disk ("splat"), via a type parameter similar to the "curves"). Yet, this would only have one (outer) radius – sufficient? Also note that to get cones, "manually" placing that closing disk is non-trivial, because the cone-segment connecting vertices with different radii in curves is always constructed to tangentially touch spheres at those vertices (even when not drawn that start / end).

tachyon-john commented 4 years ago

The described plan to generalize the cap geometry sounds like it would work fine for what VMD wants. I'm not sure what you mean by the "outer" radius? I understand the complexity for the placement/orientation of the interior cap geometry, those are definitely a case better handled by the back-end rather than the application. In the case of VMD, I would either be using the curves API to generate a large number of disjoint cylinders/cones (not connected), which is the case where VMD might want to control capping in more detail, or the case where VMD is drawing a field line, streamline, hair-like stringy primitves where letting Embree have total control of that makes sense to me.

johguenther commented 4 years ago

Update: the plan now is to not only have a flag, but an enum to select between open, sphere and disk for the start and for the end cap. Note that those enums are per geometry, not per individual curve.

Re "outer radius": you mentioned earlier to also have a ring (i.e. additional inner radius).

tachyon-john commented 4 years ago

@johguenther This sounds good to me!

johguenther commented 4 years ago

Update: plan's changed...

Because the cones are always constructed to touch the spheres at both ends it can be weird if those spheres are then skipped (because of the flag "open cap"), in particular if the cone segment is shorter than the radius of either end (it is then degenerated and thus also skipped).

So, all in all we think it is better to leave the curve geometry as is, and instead (re-)introduce a cylinder/cone geometry to OSPRay (via a newly added, native primitive in Embree). Now back to the "cap" question (open or closed=disk): do you need those flags (for start and end cap) for each individual cylinder/cone, or are those two flags controlling the start and end cap for all cylinders/cones in the geometry?

tachyon-john commented 4 years ago

Johannes, Going with separate geometry is fine with me. Also, I would argue it's more natural and doesn't tie your hands to "special behaviors" in your curves API, perhaps leaving you with greater flexibility to revise the curves API, or even just having a highly-optimal back-end, etc.

Regarding the caps, in the case of VMD, the caps are defined separately per-primitive internally but they could be sorted internally to batch up cylinders or cones that share the same capping flags/parameters. If you had a separate disc primitive, that would likely work fine also. The cylinders with caps are primarily used for so-called secondary structure representations, so the number per-molecule grows with the number of protein alpha helices, maybe in the tens per macromolecule. For drawing force arrows and vector fields, things might be a bit different as there are cases where fields of cones/cylinders get used to display vector fields or "porcupine plots" of the normal modes of protein dynamics, etc, where there are many thousands of cone/disc/cylinder/disc groupings typically. In the case of arrows, the cone gets capped and the cylinder gets capped on one end. To draw nice transparent cones, the cap on the cone would be a ring rather than a disc, so the ring/cap would have both an internal and external radius. I'm pretty flexible as there are lots of ways to draw these objects. Where possible I like using custom primitives for nice looking curved surfaces and reduced memory footprint, but it isn't the end of the world if you do cylinders and not cones, or you do cylinders and cones but don't implement capping, discs, or rings. We'll find a way to make it work. :-)

johguenther commented 3 years ago

Preview, coming soon:

cones