jonathanhogg / flitter

A functional programming language and declarative system for describing 2D and 3D visuals
https://flitter.readthedocs.io
BSD 2-Clause "Simplified" License
39 stars 1 forks source link

It would be useful to have distinct camera support in `!canvas3d` #26

Closed jonathanhogg closed 8 months ago

jonathanhogg commented 8 months ago

At the moment, the camera is specified with the viewpoint, focus, up, fov and orthographic attributes. This is OK unless you want to apply transformations to the camera, at which point it becomes a pain in the arse. One can sort of get around this with applying transforms to the world instead, but it'd be handy to be able to just place a camera in the world at an arbitrary position. Even neater would be to place multiple cameras inside the world and then switch between them at will.

I suggest adding a !camera object that can be placed in the normal object graph, within !transforms as desired. This would probably have pretty much the same attributes as the current top-level ones, with perhaps renaming viewpoint to position (to be consistent with other objects) and adding a direction alongside focus.

If these cameras had something like an id attribute, then a top-level camera selection could be done with something like camera=id.

jonathanhogg commented 8 months ago

Even more interestingly, could cameras have some kind of always render attribute that would give them their own framebuffer? I could then insert them into the references dictionary to allow multiple camera angles to be rendered in one iteration and used in other scene nodes. For instance, one could render a separate camera view and then overlay a canvas that draws this view as a "picture-in-picture" above the main view.

Much of the work in !canvas3d is collecting the models and lights. Dispatching instances multiple times to the GPU would probably be pretty efficient. If I'm ever going to implement shadow casting then I'll need to be able to do multi-pass rendering anyway.

jonathanhogg commented 8 months ago

OK, so what would this look like?

Cameras would probably want the following attributes:

If cameras are going to be full independent render passes, then they should also support:

These attributes on a !canvas3d node should set a default camera that will be used if no camera attribute is given (or a matching !camera is not found). It likely makes sense for !camera nodes to take default values from this.

I would guess that all positions, directions and distances need to take into account the local model matrix. I guess the easy way to do this is to just construct a local projection/view matrix and then multiply this by the inverse of the local model matrix? That ought to give me a matrix that will convert world coordinates into camera projection coordinates. Directions like up and distances like near and far can be used as they are given.

jonathanhogg commented 8 months ago

On second thoughts, a !camera should be like a !light. So position, direction and up should be transformed into the world coordinate system and the PV matrix should transform from world coordinates. All distances would be in world distances same as a light's falloff is in world distances.

jonathanhogg commented 8 months ago

Also, on third thoughts, I like focus better than direction. It allows for a default focus world position to be given on the !canvas3d and then a local camera can be moved around inside the world while retaining that focus.