1

I need to load 6 cubemap images each "frame" and apply them to a cube and render that as equirectangular panorama frames via Cycles (camera inside cube, nothing else in the scene).

How would you do it?

someonewithpc
  • 12,381
  • 6
  • 55
  • 89
Leo Ervin
  • 662
  • 2
  • 12
  • 32
  • who downvoted ? – Leo Ervin Sep 05 '15 at 07:40
  • 2
    Do you have any animations running? Does anything change at all between the different frames? Or do you simply want to change only the texture and render the cube with the 6 different maps? – TLousky Sep 05 '15 at 07:46
  • I said exactly what I need, no need to assume anything more. Yes, just a cube with changing textures each frame. – Leo Ervin Sep 05 '15 at 07:47
  • 3
    No need to be touchy :-) I'm asking because in that case the script is much simpler, you don't really need to change frames at all, just load each texture and render in a loop. – TLousky Sep 05 '15 at 07:51
  • oh, yeah... How though? – Leo Ervin Sep 05 '15 at 07:53
  • 3
    @LeoErvin Does this need to be done with python? Could you use an image sequence texture node instead? (related: http://blender.stackexchange.com/q/5773/599) – gandalf3 Sep 05 '15 at 07:54
  • Seems like that would work too, if could be done by code (selecting the folder of the image sequence by code) – Leo Ervin Sep 05 '15 at 07:56
  • What are you asking? My Python experience? What code I've tried? Are you just checking if I've done my "homework"? (if so, check my other questions). – Leo Ervin Sep 05 '15 at 08:01
  • 2
    @LeoErvin When you are asking a (complex) python question it's good practice here to show us some code or a bit effort at least. – p2or Sep 05 '15 at 08:19
  • check my comment under the answer to see code, teacher – Leo Ervin Sep 05 '15 at 08:31

1 Answers1

4

Try this [Modified according to comments].

It assumes that:

  1. You have one root folder (ReplaceMe1) that contains a subfolder for each cubemap. Each subfolder has 6 images, one for every side of the cube.
  2. Your cube is comprised of 6 separate objects, appropriately named ('side' / 'front', etc. See script for full list).
  3. Each side object has a separate cycles material with an image texture node.
  4. You want to save all your renders to a specific folder (RepalceMe2)

Code:

import bpy
from os import listdir
from os.path import join, isdir, isfile

# Root folder which contains a subfolder for each environment map
imgFolder = 'C:/ReplaceMe1'

# Subfolders, each containing 6 images - 1 per side of the cube
mapSubFolders = [ d for d in listdir( imgFolder ) if isdir( join( imgFolder, d ) ) ]

# Output Path (where your renders will be saved)
outputPath = 'C:/ReplaceMe2'

S = bpy.context.scene

sides = [ 'top', 'bottom', 'left', 'right', 'front', 'back' ] # Object names

for d in mapSubFolders:
    folderPath = join( imgFolder, d )
    imgFiles   = [ f for f in listdir( folderPath ) if isfile( join( folderPath, f ) ) ]

    for s in sides:
        # This line will crash the script if this folder doesn't contain an image
        # for each side, with the same name (for example: 'bottom.jpg'; format doesn't matter)
        sideImg = [ f for f in imgFiles if s in f ][0]

        imgPath = join( folderPath, sideImg )

        # Open image file or apply the relevant image path to an existing image object with the same name
        if sideImg not in bpy.data.images:
            bpy.ops.image.open( filepath = imgPath )
        else:
           bpy.data.images[ sideImg ].filepath = imgPath

        img = bpy.data.images[ sideImg ]

        sideObj = S.objects[ s ]
        t = sideObj.active_material.node_tree

        t.nodes['Image Texture'].image = img # Apply current side's image to image texture node

    outputFile = d + "_" + s + S.render.file_extension

    S.render.filepath = join( outputPath, outputFile ) # Set render output path

    bpy.ops.render.render( write_still = True )
TLousky
  • 16,043
  • 1
  • 40
  • 72
  • The cubemaps are separate images for left, right, top, down and front, back views, not a single image containing all 6 views. Such a thing can be rendered with Blender like this: http://www.pasteall.org/60978 I found no easy way to save all views as 1 image. Environment maps work but they do not support composite nodes being applied to them. And heres the code I use for that: http://www.pasteall.org/60979 – Leo Ervin Sep 05 '15 at 08:23
  • This script assumes that you have many images, not one - as long as all the images are in the same folder. – TLousky Sep 05 '15 at 08:24
  • No, I don't mean multiple "frames". I mean 6 images (the 6 sides) for each view for each frame. – Leo Ervin Sep 05 '15 at 08:25
  • Each side of the cube has a different image texture applied?

    Will probably need to see the node tree to adapt the script, or you could try do this based on the script above (which probably provides a good basis) and post your result.

    – TLousky Sep 05 '15 at 08:27
  • Node tree? I think it would be easiest Python-wise to have each side of cube as separate object, instead of applying 6 textures to one Object. The objects could have any name. This is my thought right now. – Leo Ervin Sep 05 '15 at 08:33
  • 3
    @LeoErvin, modified according to your comments. As you can see, a focused dialogue is often crucial to help you get the answer you need, so be nicer to the people asking questions next time :-P – TLousky Sep 05 '15 at 09:23
  • 1
    I got frustrated from the downote and was pretty furstrated today already, sorry about that. BTW, this, combined with the code I posted above allows to render equirectangular videos with Blender Internal. I really miss the halo and line particles in Cycles, I think some people who want to render panoramic images or videos from Blender Renderer will find this workflow tedious but a solution nonetheless. – Leo Ervin Sep 05 '15 at 14:54
  • Wait, this doesnt seem to work. "Each side object has a separate cycles material with an image texture node.". You mean like this lmgur link ? I get this error: " File "C:\Users\User\Desktop\cubemap_renderer\cycles.blend\Text", line 34, in < module> TypeError: 'in ' requires string as left operand, not list Error: Python script fail, look in the console for now..." – Leo Ervin Sep 07 '15 at 17:25
  • Did you add something to the script? Line 34 is empty in the original, so I'm not sure which line triggered the bug. Post the amended script somewhere? – TLousky Sep 07 '15 at 18:04
  • Oh sorry, I added comments to remember how the script works, its line 25. – Leo Ervin Sep 07 '15 at 18:18
  • Dammit, had a typo there. Replaced the 2nd "in" with the "if" it was supposed to be. – TLousky Sep 07 '15 at 20:18
  • Okay, now an error on line 35, "NameError: name 'f' is not defined" – Leo Ervin Sep 07 '15 at 20:53
  • Sorry, didn't have time to properly test this script after I updated it when you mentioned you have an object+texture per side. Made a bunch of other changes, hope it works for you now. – TLousky Sep 07 '15 at 21:24
  • It now outputs black images. – Leo Ervin Sep 08 '15 at 04:39
  • Try using an emission shader instead of a diffuse shader in your materials to generate shadeless materials (for my script). – TLousky Sep 08 '15 at 05:46
  • Maybe Cycles is too problematic for this in the end. If we use emissive material in Cycles, doesnt it illuminate other objects automatically? – Leo Ervin Sep 08 '15 at 06:36
  • Not other emission materials, but if you want to make sure, you can probably control that in the Ray Visibility section in the Properties Window --> Object tab – TLousky Sep 08 '15 at 06:41
  • This is odd, I see blackness. Have you tried it? You can use the script I posted to generate cubemaps from Blender Internal and test on them. – Leo Ervin Sep 08 '15 at 18:04
  • It seems we need this kind of node setup to tell Blender to not emit from one material to another, use UVs and also have the normals flipped inside the cube: http://i.imgur.com/2nljbbq.png However, results are still not quite right, it seems like the order the front, back, left, right and top, bottom images are read from folders are wrong. http://i.imgur.com/DATyzAw.png – Leo Ervin Sep 09 '15 at 13:40
  • Alrighty, seems linke you've made nice progress with this. Perhaps try loading different color images to each side to debug the order. – TLousky Sep 09 '15 at 13:54
  • I would but your code is slightly confusing to me Im afraid. – Leo Ervin Sep 09 '15 at 14:08
  • Make sure you named the face objects as expected ('top' for top, 'left' for left, etc), and that each such object has its own material (name doesn't matter, but each object should have a different material, each with an emission node fed by an image texture node). If this is correct, the script will try to load an image with the same name ('top.jpg' or another valid extension) to each of the objects' materials. Make sure these are consistent, and if you're sure they are (test with a different color image for each side), then you might have found another bug in the script. – TLousky Sep 09 '15 at 14:13
  • As I said, that node setup produces black output. I think we need this kind of node setup to tell Blender to not emit from one material to another, use UVs and also have the normals flipped inside the cube: http://i.imgur.com/2nljbbq.png . Here is the blend file: http://www.pasteall.org/blend/37931 .Here's the cubemap input images: http://imgur.com/a/B51i1 .And here's the render result: http://i.imgur.com/DjzjUnC.png . Here's the blend file with the script which generates the cubemaps: http://www.pasteall.org/blend/37932 . I believe we're pretty close but something is still wrong. – Leo Ervin Sep 09 '15 at 16:18