It would be useful to have distinct camera support in `!canvas3d`
jonathanhogg opened this issue · 4 comments
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 !transform
s 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.
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.
OK, so what would this look like?
Cameras would probably want the following attributes:
position
– synonym for currentviewpoint
direction
– derived from currentfocus
if specified insteadup
fov
orthographic
width
near
far
fog_min
fog_max
fog_color
fog_curve
If cameras are going to be full independent render passes, then they should also support:
size
– framebuffer sizecolorbits
- framebuffer depthsamples
- MSAA control
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.
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.
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.