15
$\begingroup$

Usually, when I create environment maps I do it in Cycles. I render out a single equirectangular image, and it's easy.

But recently I find myself creating content that needs to work in Blend4Web, which means using the Blender Internal schema.

So the way BI handles environment maps is: It expects a cube-mapped texture with the six faces placed as follows:

Blender Internal Cube Map

The above image is from the Blend4Web Manual.

Here is another reference to this cube-map format: A rather old Blender Internal tutorial. (It lists incorrect Z axis values)

Cycles does not offer a cube-map option for panoramic rendering:

Cycles panorama options

Currently I am using a custom .blend I made to Cycles-bake the equirectangular environment map onto a UV-mapped "round cube" and the cube's faces are animated to unfold into the correct layout, which I can then render - but the seams are visible, and I think there must be a better way of doing this anyway.

How can I render out such a cube map directly from Cycles?

$\endgroup$
6
  • $\begingroup$ You could set up the camera with a focal length such that the FOV angle is 90 degrees, then render from all 8 directions. $\endgroup$
    – PGmath
    Commented Feb 14, 2016 at 2:36
  • $\begingroup$ @PGmath I had considered that, but I don't know how to calculate the focal length. Do you know how? $\endgroup$
    – Mentalist
    Commented Feb 14, 2016 at 2:56
  • $\begingroup$ @PGmath Wait, I think I figured it out. I think the focal length should be 16. I created a linked duplicate of a camera with a square aspect ratio, rotated one 90 degrees, and adjusted the focal length slider until they appeared to be touching in the viewport. I will test this out. :-) $\endgroup$
    – Mentalist
    Commented Feb 14, 2016 at 3:03
  • 2
    $\begingroup$ Update: I've got this solved, and plan to post a proper answer in a day or two. I keyframed rotation for all 6 directions once I knew the correct focal length. I've got a nice all-purpose .blend for cube-mapping now, as well as a compositing setup to instantly combine the 6 tiles into one image so seams are as smooth as possible. I will share those too. $\endgroup$
    – Mentalist
    Commented Feb 14, 2016 at 13:25
  • $\begingroup$ You can save a environment map generated by a material This is a cube map. blender.org/manual/render/blender_render/textures/mapping/… $\endgroup$ Commented Feb 18, 2016 at 2:09

1 Answer 1

17
$\begingroup$

Here is how I solved this - and there's a download link at the end.

(Coordinates written as 1,2,3 refer to X:1 Y:2 Z:3, for example.)

Setting up the "Cube Cam"

Add a Camera and an Empty at location 0,0,0 and set rotation of each to 90,0,0 degrees. If you choose "Arrows" for the Empty display type it may help avoid confusion later.

Parent the Camera to the Empty. The reasons for rotating and then parenting in this order are so that the Camera's coordinates will match the reference image above, and so that the Empty's -Z will point in the same direction as the Camera's when the Camera is facing forward.

The Empty allows the Camera to be easily repositioned, because the Camera's keyframed rotation will be relative to the Empty, not the World.

Set the Camera's Focal Length to 16mm (or 90° Field of View). This is necessary for the "faces" of the cube map to touch exactly.

Focal Length set to 16mm 90-degree Field of View

Set your render dimensions to a power of two, such as 512, 1024, etc.

Leave the Start Frame at 1. Set the End Frame to 6. There will be one frame for capturing each direction of a cube's faces.

Render resolution and frame range

Keyframe the Camera's rotation accordingly in these frame numbers:

  1. 90, 0, 90 (left)
  2. 90, 0, 180 (backward)
  3. 90, 0, 270 (right)
  4. 0, 0, 0 (down)
  5. 180, 0, 0 (up)
  6. 90, 0, 0 (forward)

Optionally, you can add a guide object containing text labeling the directions (visible in the viewport, but not in renders), and parent this to the empty as well. And you can group these three objects (Camera, Empty, text guide) together, so that they can be easily appended to other .blend files.

The "Cube Cam" setup

At this point the Cube Cam setup can be appended into any .blend file.

After appending, from within the new .blend:

  • Go to frame 6, where the Camera is facing forward.
  • Make sure the Cube Cam is the Active Camera, by selecting it and choosing View > Cameras > Set Active Object as Camera.
  • Use the Empty to position the "Cube Cam".
  • Set the frame range from 1 to 6, and specify the Output file name to be something like "cube_tile_".
  • Set the Render Dimensions for X and Y to a power of 2, for example, 1024x1024. This will be the resolution of each of the 6 tiles.
  • When ready to render, click the Animation button.

This method of rendering directly from the environment scene is quick and easy, but there is still some distortion that shows up, revealing the cube shape of the cube map if you look closely. The way to eliminate this is to first render an equirectangular (or mirror ball) environment map, and then render that to a cube map.

Equirectangular Map to Cube Map

First, let's review the steps for creating an equirectangular map to begin with. It's pretty simple.

Step 1: Adjust the Camera settings to be Panoramic, then choose Equirectangular for the type.

Equirectangular camera settings

Step 2: Set the render Resolution so that X is twice that of Y.

Choose a resolution that is significantly higher (perhaps double) the pixel detail of what one of the final cube map's tiles will be. So if one tile of the cube map will be 1024x1024, and two of those tiles will be stacked on the Y axis (doubled), then doubling that to 8192x4096 would give 200% pixel density on Y (and 266.6% on X because of the difference in ratio).

Here's a diagram to make it easier to understand:

Diagram for aiding in pixel density calculation

Equirectangular map resolution ratio

Render!

Now, back in the Cube Cam .blend file, in the World context World Context click the Use Nodes button and go to the Node Editor for the World. Create the node setup for a panoramic environment:

Editing Cycles World Material

A Cycles panoramic environment for the World

You won't need many samples for this. I did some testing and found that no sample count higher than 20 produces any visible improvement, so I recommend rendering at 20 samples.

Sample count set to 20

Save this .blend file to reuse later.

In the Environment Texture node, click Open to load a specific panoramic image, and render it out as an animation to 6 cube map images. Render Animation button

You can use an image editor such as GIMP, or Blender's compositor to combine the 6 image tiles into one cube map image. Two advantages of doing this in the compositor are that you won't need to rely on other software besides Blender, and you won't need to manually position each tile every time you create a cube map - once you've set it up, it's an automated process.

Edit: While it's really cool that Blender can composite tiles into a single cube map, I have since discovered a faster way to do this using imagemagick. Example syntax:

convert \( 0001.png 0002.png 0003.png +append \) \
        \( 0004.png 0005.png 0006.png +append \) \
        -background none -append +repage cube_map.png

If you still want to do it all in Blender, continue reading...

Putting it All Together With Compositing

In a new .blend (or new Scene, if you prefer), create this node setup in the Compositor:

Node setup for compositing the cube map

Let's examine it in more detail.

The Value node for "Tile Size" should be set to the X and Y resolution of one tile (or you can think of it as one "face" of the cube map). So the final image resolution should be this amount times 3 across (X) and this times 2 down (Y). For example, if one cube tile is 1024 pixels, the render resolution should be set to 3072x2048. You don't even have to do any math in your head - just type 1024*3 into input field X, and 1024*2 into input field Y. Blender will calculate it for you. (Okay, maybe 1024*2 is easy, but you can surely see how this shortcut is useful.)

Inputting a simple math function for the resolution value

"Tile Size" input value

Each Image node is set to load a tile of the cube map (1~6):

Image tile with correct file name loaded

These six nodes determine the position of each tile in relation to the whole image, or "canvas":

Node setup for positioning

Set the Multiply nodes to the following values:

Table of offset values

The Alpha Over nodes are just for layering the tiles, while preserving transparency (in case you ever need to composite a cube map that contains alpha data). These can be left at their default settings.

A Scale node, which I have labeled "Get Size" takes in the image data of one tile, then scales it to the size of the render (which, as mentioned, should be three times across and two times down in proportion to the size of one tile).

That image data is then sent through a Set Alpha node because the image data is not necessary - all we need it for is getting the correct dimensions. What we get out of the Set Alpha node is a transparent "canvas" that is the size of the render dimensions.

"Canvas Sizing" node setup

So that's basically it. You can render the image and it will be composited!

I've published a toolkit for creating cube maps to Blend Swap under a CC-0 license. You can Download it Here.

$\endgroup$
7
  • 4
    $\begingroup$ Excellent! It will be useful for many. $\endgroup$
    – Blend4Web
    Commented Feb 20, 2016 at 8:40
  • $\begingroup$ link is broken! $\endgroup$
    – Nolesh
    Commented Sep 14, 2019 at 5:50
  • $\begingroup$ @Nolesh Thanks, but which link specifically? $\endgroup$
    – Mentalist
    Commented Sep 14, 2019 at 7:34
  • $\begingroup$ this one: blendswap.com/blends/view/83386 $\endgroup$
    – Nolesh
    Commented Sep 14, 2019 at 16:57
  • $\begingroup$ @Nolesh Strange... it's working for me. Do other pages of BlendSwap load for you? $\endgroup$
    – Mentalist
    Commented Sep 14, 2019 at 17:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .