Ground Shadows for in-Program-Generated Meshes in RealityKit

Apparenrly, shadows aren’t generated for procedural geometry in RealityKit: https://codingxr.com/articles/shadows-lights-in-realitykit/

Has this been fixed? My projects tend to involve a lot of procedurally-generated meshes as opposed to importes-models. This will be even more important when VisionOS is out.

On a similar note, it used to be that ground shadows were not per-entity. I’d like to enable or disable them per-entity. Is it possible?

Since currently the only way to use passthrough AR in Vision OS will be to use RealityKit, more flexibility will be required. I can‘t simply apply my own preferences.

Answered by Graphics and Games Engineer in 755731022

Agreed, we've gotten lots of feedback about this point last week. It's something we are thinking about, but for now the suggestions I've talked about above are what we are recommending if you need to do something custom.

Hi, not sure about the first part of your question, if this is still an issue when the visionOS simulator is released next month, please file a bug report on feedback assistant. Regarding the second part of your question, yes you will be able to disable shadows per-entity on visionOS with a new API. Stay tuned for the documentation for more information.

Thanks! I’m glad RealityKit will have more updates to come.

On the subject of RealityKit and VisionOS, I did want to raise the following (pardon the walls of text):

My note about procedural generation relates to generating geometry programmatically. I am admittedly concerned about RealityKit being “The” way for rendering in visionOS when passthrough AR is enabled. There are a lot of things that are actually more straightforward in a plain Metal application like render to texture or just updating buffers per frame.

During WWDC, a suggestion was just to recreate a MeshResource per-frame, but that seems like a lot of work just to do something that would be very simple in plain Metal.

I do have concerns about the choice to limit the renderer. Mainly, I don’t think I should have to worry about it having these sorts of standard rendering features to create the content I want in AR mode. I think some lower-level integration like compositorservices for full VR mode would be very useful to have for passthrough AR mode.

Would Apple take feedback for or consider possibilities for lower-level Metal integration separate from RealityKit (via feedback assistant or discussion here?) I understand why the choice was probably made to use RealityKit: you want consistent visuals mixed with the real world camera view.

That said, I think a lot of people including myself will still want custom renderer support in passthrough mode, even though it’s nice to have an all-in-one engine like RealityKit. The thing with builtin renderers is that they limit the creative choices each developer / artist can make, and content will tend to start looking the same between apps. Also, it’s probably going to be hard for Apple to keep updating RealityKit consistently as more and more advances in graphics come in. Usually we’d have the choice to write our own renderers it the builtin libraries didn’t suffice, so I‘m not sure RealityKit-only for passthrough mode is scalable.

I’d be interested in sharing some more use cases for custom rendering and ideas for how to deal with the privacy / visual consistency issues, though I realize the teams at Apple have probably thought all of this through.

A little tangential to my own question, but are custom materials available on VisionOS? That might make things a little easier.

Overall, I think that as VisionOS develops, it will be great to see pure Metal support in passthrough mode, perhaps with some VisionOS extensions, rather than just RealityKit. Something in-between the high-level and the low level functionality to make it possible for graphics people to have a little more autonomity.

The CustomMaterial API, as well as our post processing API are not available on visionOS. We are definitely aware of the limitations of custom Metal rendering on visionOS, and you are welcome to file feedback with your specific use case.

Ah, that is really quite a shame and limiting. I mentioned some of the use cases above (stylistic choice, custom geometry offsets and shading, custom algorithms). Yes, I can file feedback. The high-level feedback, while on the subject, would be to enable lower level control via metal shaders and / or custom materials. However, can you/Apple say anything more about the reasons why these limitations are currently in-place? i.e. what are some of the problems that are making arriving at a solution with more rendering control hard? For example, is it related to privacy or something in the way the OS requires rendering to be done? Is Apple also thinking about how to improve the situation? (Again, fully understood this is a V1 product.) That way, I could think more about my feedback to see if I could arrive at some reasonable ideas and suggestions, rather than simply requesting a feature with nothing else to contribute. I'm pretty invested in this platform already and would like to see if grow to support more creative rendering and interactive experiences. I'm pretty sure that the limitations will be a bit too much down the line.

The restrictions are due to the OS architecture. On visionOS, rendering happens out of the app’s process in a shared simulation, and allowing apps to provide the render server with arbitrary Metal code is a security risk. This is similar to how other Apple platforms render CALayer content. The final rendering and compositing of CALayers is done by a separate process, and apps are similarly not allowed to provide arbitrary Metal code to the window server, and must use an intermediate API like CAMetalLayer.

Thank you for clarifying the core issue. I really appreciate it. It does seem like a hard-to-solve problem and I'm not about to request a rewrite of the system architecture. My follow-up question would be -- how can Metal be used with the compositor-services for full VR mode, but not for passthrough mode? I wonder what the difference is. Is it because in passthrough mode you have the additional need to compose with the camera feed and do occlusion, and THAT's where the issue comes up?

It sounds like in order to solve the problem, user-side rendering would need to be sandboxed away from the main simulation in step 1, and then results (not code, but the textures and resources, etc.) could be passed to the shared simulation to be composed with other things. (I am not an OS person, so forgive me if I'm showing a fundamental misunderstanding of how this works.)

Well, I hope that somehow the restrictions could be lessened, possibly through some additional sandboxing or moving the userside rendering to some secure space. Is it a problem that even can be solved with time?

I'll reference this in a feedback report if it helps. Thanks again for explaining and your patience.

When using CompositorServices, I believe you are the only app running and you submit the rendered frames for composition. Your rendering happens ‘in process’ and you are the main render server, so there is no security concerns there. You are welcome to reference this thread in your feedback, but it would be more helpful if you could provide some specific use cases you are trying to render with Metal in your feedback. Also, I believe there is (or will be) a specific tag for visionOS on feedback assistant, so you may want to wait for that to be available before filing feedback.

I think I understand. Are you referring to the case in which we're in a shared space with several different applications running in the same environment in the "shared space?"

Correct me if I am wrong, but additionally Isn't there also an AR passthrough mode in which just one application is running at one time -- just as there's a full immersive mode that uses CompositorServices?

If so, then that might be a starting place. If Metal could run with passthrough enabled with the restriction that the application is the only thing running, then that would make sense as a restriction. That is, it makes sense that you'd have more control over the visual style when you're not potentially conflicting with the visual styles of other applications, and also from a security standpoint when your application is isolated from others.

The challenge would then be less about security, but rather about how to support a custom raytracing / lighting function and occlusion with the camera passthrough enabled. I think this is an easier problem to solve because it's just more composition and perhaps extensions to Metal (speculating).

Yes, I understand about the need for more specific use cases. I felt I needed more context behind why the current system behaves the way it does.

For the sake of putting it in-writing here for others who might read this too -- while it's fresh in-mind (before the visionOS feedback tag appears), a lot of the use cases I have are more general and philosophical.

Higher-level general needs:

  • Many people have existing renderers in Metal that they want to reuse.
  • Metal allows for the use and experimentation with new and different graphics algorithms that can help optimize for specific needs. There is a large community of graphics programmers who prefer to "do the work themselves," not only for optimization, but also for control over 1> the visual style and expression of the rendering, and 2> the data structures for the renderer and the program that feeds data to the renderer. There isn't a "one-size fits all." For example, I often need to create a lot of per-frame procedural generated meshes. RealityKit prefers static meshes it seems. The suggestion I've received is to create a new MeshResource per frame. This does not scale well.
  • Apple probably should not be burdened with implementing new algorithms every time something new comes out. It doesn't scale well to put everything on Apple's renderer. I think that one should choose to use the RealityKit renderer or make their own if RealityKit doesn't fit the person's needs.

My Use Cases

  • Procedural generation of meshes, textures, and assets. Use of bindless rendering. Use of render to texture. All of these are cumbersome in RealityKit at the moment despite the existence of things like DrawableQueue. Extra work needs to be done to synchronize and generate assets. Lots of copying around, it seems. Overall, there's a lot of friction involved.
  • I want to be able to do vertex transformations in the shader in arbitrary ways, which currently only possible in either Metal or CustomMaterial.
  • I want to use traditional render-to-texture, masking, scissoring, etc. but RealityKit makes this hard and unintuitive.
  • RealityKit has its own entity-component / object system. My projects already have their own entity systems. Mapping to RealityKit's way of storing and managing data is a lot of redundant work and potentially non-optimal for performance. There's a lot of cognitive overhead to forcing my project to conform to this specific renderer when my own renderer and engine are optimized for what I want to make. (i.e. it would be useful to decouple a lot of the higher-level functionality in RealityKit.)
  • For spatial computing / VR, I want the ability to move around the environment, which in Vision Pro's case, is only possible in AR mode. This is a complementary issue. If VR/immersive mode were eventually to permit walking around in some future version, then that would be great.
  • As in the general cases above, I have interest in creating stylistically-nuanced graphics that don't necessarily map with what RealityKit's lighting models are doing. I want creative freedom.

Overall, I do like the idea of having something like RealityKit available, but if Metal or a slightly modified version of Metal with extensions or restrictions were made available, that would make it easier to create unique and optimized applications on the platform.

Anyway, thanks again for your time.

@Graphics and Games Engineer

if this is still an issue when the visionOS simulator is released next month

I am told that SDK is at the end of this month. Is the simulator being released next month? Or was the SDK release also delayed to next month?

Come to think of it: even if Metal cannot currently be used to do the final render in passthrough mode, am I still allowed to use Metal in passthrough mode for other things, period? I thought one thing I could conceivably do is use Metal to generate textures and meshes using vertex, fragment, and compute kernels in passes in my own command buffer, and then give the results to realitykit in the form of buffers and textures. That would be a temporary and clunky solution, but at least it could be workable and let me program some custom shaders. But if the system blocks Metal outright in that mode, then that’s a really strong limitation.

Please let me know. It’s all research to figure out what can and cannot be done now.

If this route is possible, however, then how would a Metal command buffer be synched with RealityKit so I could feed textures and buffer data generated in Metal to RealityKit in the same frame?

Thanks!

Yes, you should be able to do what you describe. Metal is not totally blocked on the system. If you want to use Metal to generate a texture, and then display that on a RealityKit mesh using the DrawableQueue API, that will work as expected.

Right, it’s good that DrawableQueue exists. I’d also like to be able to generate meshes dynamically to simulate vertex animations, but I’ve not seen a DrawableQueue equivalent for same-frame generation of buffer data to update for a RealityKit mesh. Is it possible? I’m not sure the bridge really exists for that. If it did, that would be an improvement to RealityKit for sure. Actually it would be really helpful to see an example of how to do this sort of synchronization.

The reason you need to update meshes and not just textures is that I believe this is the only way you could still compose with the passthrough video and occlusion. Otherwise it’s just going to render flat images. A direct link between say a MTLBuffer region for vertices and indices and a RealityKit mesh would make things pretty okay.

It makes me think a much simpler bare-bones API could be made for streaming custom Metal code results into a secure fixed function pipeline of sorts.

Either way, I don’t think this is a long-term solution, but but it’s something. I’ll still file feedback when the visionOS tag appears, as you suggested.

EDIT: Couldn’t I just use completion handlers on Metal and RealityKit? I’m not sure if RealityKit lets you get a completion handler or block it as you normally would maybe block metal using semaphores. —if I can just tell RealityKit to render on command. That would achieve what I’m looking for. —but the extra copying from buffers wouldn’t be as good as a direct link between metal buffers and RealityKit meshes.

Throwing out another idea: in full ar mode in which just the one application is running, couldn’t sandboxing and compositorservices be used like in full VR mode to isolate the process to make custom GPU code safe again? In shared mode, I agree it makes sense to have a unified renderer. To do custom lighting and enable occlusion, the GPU code could be sandboxed as well so reading the pixel data for lighting and depth occlusion happens in say a fixed function or MTLFunction pointer callback. Or, maybe protections could be put on the drawable and privaxy-sensitive textures so they can only be read on the GPU, but never written or copied/blitted in a shader or on the cpu.

I’d be pretty happy with some sort of fixed funcrion to enable these things, but yes, I think the only way for custom code to ever work in the near future would be to enable it in full immersive AR mode with some sandboxing and protections.

I’m not sure how lighting, transparency and occlusion would work without letting the custom code see the textures though. I get that’s a problem. Again, maybe sandboxing, copy protections, and user permissions are required. It’s tricky.

A lot of simple, but beautiful effects seem impossible without some form of access, like SDFs and Raymarching with environment lighting: https://github.com/quantumOrange/ARRay

I’d be great if eventually we could get to a place where we could do this freely.

Accepted Answer

Agreed, we've gotten lots of feedback about this point last week. It's something we are thinking about, but for now the suggestions I've talked about above are what we are recommending if you need to do something custom.

Fair enough. I'm glad you're all thinking about this issue and how to improve it based on the feedback. I do think that to scale-up and support those nicer advanced graphics, the sort of freer open system might be necessary. I understand that it's a challenging problem: balancing security and flexibility. It makes sense in the short term to get something out there. I agree, I can try the simpler solutions in the meantime.

One more idea: if you also wanted to support multiple apps open in a shared space, but within a safe space that won't clobber other apps or be visually inconsistent, you could use something like app groups. A developer could specify a group of apps that look visually appealing and consistent together, and which work together well and under their control without risk of interacting with something external that is malicious.

But I see this platform evolving in steps of course! Once the tag for visionOS comes out, if it's alright, I'll just officially file all of this feedback in more of a shortform.

Anyway, thanks again for discussing the problem. I appreciate being able to understand it at a deeper level.

Ground Shadows for in-Program-Generated Meshes in RealityKit
 
 
Q