Can a 3D topdown camera render to 2D minimap?

I’ve been running through the various wiki posts and while I see mini-map/split screen setups, they don’t really cover what I’m trying to do…

I have a 2d interface which (will) contain the UI. Problem is, part of the UI needs to be a top-down camera of the 3D space that can be rendered to a 2D minimap on their UI. The minimap’s actual rendering quality does not need to be high, it is mainly just for seeing ‘behind’ your 3D character or whatever…

I saw some examples of camera output being rendered onto an object, but no editor was available and the code was gone from the answers page… so here I am again…

Thanks in advance! Hope this can be done…

Hey devnod,
you should be able to achieve that quite easily with a second camera.

  1. Attach a camera above your character and write a script, that the camera follows on the x & z axis (if you don’t care about the height). Alternatively, just group them under the same parent entity so it automatically follow on all axis.
  2. Set the priority of your mini-map camera to 1, so it renders in front of your normal camera
  3. The Camera component has an option to control its viewport dimensions, set it to something like 0.2 for its width & height and move it to the corner of the screen you want it to be.

It’s basically like this example project: https://playcanvas.com/project/443666/overview/multiple-viewport-rendering

That should do the trick. You could also control, which objects render on each camera via some camera masks, but that’s not too well documented yet and missed some things.

Greetings,

Martin

You can have a second camera render to a texture and use that texture in the UI. It’s expensive because you are rendering everything twice (once for the main view and another for the minimap) although you can reduce this by on rendering certain objects using cull masks (as shown here: https://developer.playcanvas.com/en/tutorials/camera-model-masking/)

There are a number of other ways to implement a minimap including:

  • Pre-rendering to texture at the start of the level and add the dynamic elements on top
  • Have the world represented in data (eg for RTS Command and Conquer where everything is grid based, it might be represented in a 2D grid) and populate the minimap using that data

The pre-rendering is probably most efficient performance wise.

Thanks for the replies!

While the game is going to be 3D, the graphics will be voxel based which should help to reduce the stress placed on the downloading and rendering…

Now my issue is trying to figure out the map itself. If you have any ideas in that regard, here’s my basic situation:

Small to Medium 3d world, the terrain is flat and everything is voxel based. Hills, trees, players, structures, etc will also be voxel based but exported in such a way that they are more ‘rounded’. Low polygons basically.

Originally I’d thought about adding each tile of the map as a plane but then read in the docs that if going up to 20 or so planes it would slow down performance. I would have hundreds… but each player would ideally only load the one they are in with a decent shader, with shaders getting progressively ‘less’ as its further away. How would one do this with a large map? Ideas?

To make voxels and planes work you are going to need to combine meshes as the overhead of many meshes with few points will kill your performance (it will make you CPU bound). If you want to do it in the editor you can use my PlayCanvas Editor ++ extension to combine the meshes. Ideally you shouldn’t have lots of objects with less than 300 verts, as this seems about the cut off point in my tests at least for CPU/GPU performance.

I have a runtime version which extends pc.Entity to enable combination of children at runtime. https://www.odrive.com/s/69bc6d37-c373-4347-b94a-de2ac9a55709-59d15369 add that to your project.

The signatures are:

pc.Entity.prototype.gridCombine = function (cols, rows, castShadows, receiveShadows, lightmapped, predicate)

Creates a grid of combined entities (to help with culling etc - this is the one I use)

pc.Entity.prototype.combine = function (castShadows, receiveShadows, lightmapped, predicate, cb)

Combine all children.

Predicate is passed a meshInstance and returns true or false to update it

1 Like

Interesting.

Would it then be better to have solid objects (structures, trees, etc) in a standard voxel square-rendered model? Currently, players are rendered with marching cubes to make them more ‘rounded’ and I’d like to keep that as voxel chars tend to be ugly otherwise.

Note that the voxel map will only be a 2D element in the end, I used a online map generation tool to get the shapes of continents, then opened in MagicaVoxel to set the colors to ones available (will be less than 10 solid colors total used in the map texture). Theoretically I could either put it back into a 2D texture image or use a graphics editor to replace the colors rather than using MagiaVoxel itself. Sadly I haven’t found any map terrain generators which could add depth to the map, so I was planning on having everything on a level plane and just modeling small hills but I wonder now if that would also be too resource hungry…

Hi Mike, thanks for releasing this!

Though I get the following error, just by adding this script in my project, on top of the scripts list. I haven’t tried calling it or anything. Are there any dependancies required?