Eon Vue Clouds To Game Engine
Eon Vue is a fantastic program that has fascinated me for many years. Recently I played around with the software’s cloud features. This blog post is not dealing with the details of making clouds in Vue per say, but rather how to use the output to create a cube map for use in a game engine. For learning Vue, I highly recommend “Realism In Vue” by Dax Pandhi, a gorgeous book that gives you a multi year learning shortcut through Dax’s extensive experience with that software.
I will be talking about getting the result out of Vue into a gaming engine like Unity 3d (free). I searched high and low for a work flow to properly make a cube map from the panorama map I rendered out of Vue. When I couldn’t find a proper workflow, I made one myself that I would like to share with you.
In Vue, I set my render globals to render a 360 * 180 panorama.
If you enable multipass, you can also have Vue render out the alpha channel for the clouds which could be handy if you wanted to modify your cube map or add more stuff into it in Maya.
When the Vue render was done, I mapped the image to a sphere in Maya. I created a camera in Maya, set all the properties to properly cover a cube in 8 rotations, which I keyframed. There is a lot of settings to get this to work so instead, I wrote a script that creates the entire set up for you.
There are 2 potential workflows:
1. Cross – Use Maya’s images to construct a cross so that we can manipulate the clouds or add more layers in Photoshop, Gimp or another image editor.
2. Cube – Go straight from Maya render to a game engine like Unity 3d.
When you run the script, you will be promted for which way you want to go. If you choose “Cube”, the camera will not rotate upside down and to the sides for frame 3, 5, and 6
To run the script in Maya
- Hover the mouse in the code window. In the top right corner, you should see a tool box pop up. Click on the second icon (copy to clipboard). If you do not see such an icon, click the first icon (view source) then select all text and copy.
- In Maya, open the script editor (Window->General Editors->Script Editor).
- In the script editor, create a new python tab (Command->New Tab…->Python).
- Paste in the code (ctrl+v).
- Select all the code (ctrl+a).
- Run the code (push the Enter button on the numeric keyboard or click the blue play button in the script editor).
- When the code is run, the set up is created and the file node is selected.
- Browse to your panorama sky image in the file node.
from pymel.core import *
answer = confirmDialog(title='How do you want the setup?', message='Choose your preferred setup', button=['Cross', 'Cube','Cancel'])
if answer == 'Cross' or answer == 'Cube':
panoCam = camera()
rename (panoCam[0], 'cubeCam')
panoCamT = panoCam[0]
panoCamS = panoCam[1]
# Shape Settings
coi = 4.8830726286082049
panoCamS.horizontalFilmAperture.set(1)
panoCamS.verticalFilmAperture.set(1)
panoCamS.focalLength.set(12.7)
panoCamS.centerOfInterest.set(coi)
panoCamS.filmFit.set(0)
panoCamS.renderable.set(1)
panoCamS.displayResolution.set(1)
panoCamS.overscan.set(1.3)
# Render globals
mel.setCurrentRenderer('mayaSoftware')
defaultRenderGlobals = PyNode('defaultRenderGlobals')
defaultRenderGlobals.enableDefaultLight.set(0)
defaultRenderGlobals.byFrame.set(1)
defaultRenderGlobals.imageFilePrefix.set('cubeImage')
defaultRenderGlobals.imageFormat.set(19)
defaultRenderGlobals.byExtension.set(1)
defaultRenderGlobals.extensionPadding.set(2)
defaultRenderGlobals.startFrame.set(1)
defaultRenderGlobals.endFrame.set(6)
defaultRenderGlobals.byFrameStep.set(1)
defaultRenderGlobals.extensionPadding.set(2)
defaultRenderGlobals.putFrameBeforeExt.set(1)
defaultResolution = PyNode('defaultResolution')
defaultResolution.width.set(1024)
defaultResolution.height.set(1024)
defaultResolution.pixelAspect.set(1.0)
defaultResolution.deviceAspectRatio.set(1.0)
defaultResolution.lockDeviceAspectRatio.set(0)
defaultRenderQuality = PyNode('defaultRenderQuality')
defaultRenderQuality.shadingSamples.set(2)
defaultRenderQuality.maxShadingSamples.set(8)
# Set the keyFrame
# Unity Front
panoCamT.rotateX.set(0)
panoCamT.rotateY.set(-90)
panoCamT.rotateZ.set(0)
setKeyframe(time=1, at='rotate')
# Unity Down
panoCamT.rotateX.set(-90)
panoCamT.rotateY.set(-90)
panoCamT.rotateZ.set(0)
setKeyframe(time=2, at='rotate')
# Unity Back
if answer == 'Cross':
panoCamT.rotateX.set(-180)
panoCamT.rotateY.set(-90)
panoCamT.rotateZ.set(0)
else:
panoCamT.rotateX.set(0)
panoCamT.rotateY.set(90)
panoCamT.rotateZ.set(0)
setKeyframe(time=3, at='rotate')
# Unity Up
panoCamT.rotateX.set(-270)
panoCamT.rotateY.set(-90)
panoCamT.rotateZ.set(0)
setKeyframe(time=4, at='rotate')
# Unity Right
if answer == 'Cross':
panoCamT.rotateX.set(0)
panoCamT.rotateY.set(0)
panoCamT.rotateZ.set(-90)
else:
panoCamT.rotateX.set(0)
panoCamT.rotateY.set(0)
panoCamT.rotateZ.set(0)
setKeyframe(time=5, at='rotate')
# Unity Left
if answer == 'Cross':
panoCamT.rotateX.set(180)
panoCamT.rotateY.set(0)
panoCamT.rotateZ.set(90)
else:
panoCamT.rotateX.set(0)
panoCamT.rotateY.set(180)
panoCamT.rotateZ.set(0)
setKeyframe(time=6, at='rotate')
# Create the sphere
pSphere = sphere(n='panoSphere', ax=[0, 1, 0], ssw=0, esw=360, r=10, d=3, ut=0, tol=0.01, s=8, nsp=4, ch=0)[0]
# Create and assign the shader
pShader = shadingNode('lambert', asShader=1, n='panoMaterial')
pSG = sets(renderable=1, noSurfaceShader=1, empty=1, n='panoSG')
pShader.outColor.connect(pSG.surfaceShader)
pShader.color.set(0, 0, 0)
pShader.diffuse.set(0)
i_fileNode = shadingNode('file', asTexture=1, n = 'panoFile')
i_placeNode = shadingNode('place2dTexture', asUtility=1, n = 'panoP2d')
i_placeNode.coverage.connect(i_fileNode.coverage, f=1)
i_placeNode.translateFrame.connect(i_fileNode.translateFrame, f=1)
i_placeNode.rotateFrame.connect(i_fileNode.rotateFrame, f=1)
i_placeNode.mirrorU.connect(i_fileNode.mirrorU, f=1)
i_placeNode.mirrorV.connect(i_fileNode.mirrorV, f=1)
i_placeNode.stagger.connect(i_fileNode.stagger, f=1)
i_placeNode.wrapU.connect(i_fileNode.wrapU, f=1)
i_placeNode.wrapV.connect(i_fileNode.wrapV, f=1)
i_placeNode.repeatUV.connect(i_fileNode.repeatUV, f=1)
i_placeNode.offset.connect(i_fileNode.offset, f=1)
i_placeNode.rotateUV.connect(i_fileNode.rotateUV, f=1)
i_placeNode.noiseUV.connect(i_fileNode.noiseUV, f=1)
i_placeNode.vertexUvOne.connect(i_fileNode.vertexUvOne, f=1)
i_placeNode.vertexUvTwo.connect(i_fileNode.vertexUvTwo, f=1)
i_placeNode.vertexUvThree.connect(i_fileNode.vertexUvThree, f=1)
i_placeNode.vertexCameraOne.connect(i_fileNode.vertexCameraOne, f=1)
i_placeNode.outUV.connect(i_fileNode.uv, f=1)
i_placeNode.outUvFilterSize.connect(i_fileNode.uvFilterSize, f=1)
i_fileNode.outColor.connect(pShader.incandescence, f=1)
i_placeNode.rotateFrame.set(90)
# Assign the pano material to the panoSphere
sets(pSG, e=1, forceElement=pSphere.getShape())
select(i_fileNode, r=1)
setCurrentTime(1.0)
When you have mapped the image in the file node, batch render the 6 frames out of Maya.
Workflow 1 – Cross
Multiple Layers in image editor
Open Photoshop or other image editor and create a 3072 x 4096 (assuming you rendered 1K images out of Maya). Set and display the grid to 1024 x 1024 and enable “snap to grid”.
- Drag each image in and move it to the position that matches the image to the right.
- Add new layers and effects.
- When you are happy, use selection to copy and paste each grid square (image) into it’s own file. You will have to apply the appropriate rotations according to the image to the right when going into Unity.
Workflow 2 – Cube
Straight to game engine – we will use Unity for this example
- In the project browser, create a new material and set the material type to RenderFX->Skybox
- Copy the images you rendered out from Maya to somewhere within your Unity project.
- For each image in Unity, set the “Wrap Mode” to “Clamp”. The filter modes you can play around with to see which one gives you the best result (I used Bilinear).
- Pair each image with each side of the cube in Unity. Use the guide to the right to see what image goes where. If you choose the “straight to engine” mode out of Maya, you can disregard the rotation notes.
Below you can interactively see the result with Unity (gotta love Unity )
Hopefully someone will find this useful.
Thanks,
/Christian Akesson
Leave a Reply
Want to join the discussion?Feel free to contribute!