Home Creators Posts Import Register Favorites Logout

Videos

  • 388672716.mp4

Downloads

Content

A common complaint I hear is that when creating textures for 3D assets it's difficult to quickly get a sense of what the finished result will look like. Apps like Substance Painter and Mari sacrifice photorealism in their viewports in favor of quick visual feedback. They will never look remotely as good as a finished render in RenderMan or similar. Plus, it's not very convenient to manage multiple lighting rigs and cameras in a painting app.

The dream is to have a sort of "live link" setup with Painter or Mari. Update your textures, save the project, and swap over to another app to get an immediate production-quality render. I had the idea to create this very setup using USD and usdview.

This ties in nicely with my earlier articles about building OpenUSD and scripting texture conversion. Check those out as we'll be taking advantage of a lot of the work done in them.

https://www.patreon.com/posts/building-openusd-117179765https://www.patreon.com/posts/99745842

While a true live link is not 100% possible when interfacing these very different apps, we can get close. Here's what I wanted to accomplish:

1. Create a USD lookdev scene with template RenderMan materials and multiple lighting setups.2. Paint textures in any app, then export the textures as usual to EXR.3. Click a single button in usdview to refresh the scene with the updated textures.

I'm happy to report that this was all eminently achievable! You can see my setup in action in the clip at the top of the article.

Here's how I did it:

The first task was to create a reusable USD scene that contains a set, multiple lighting rigs and template RenderMan materials. I chose RenderMan since it's easy to interface with usdview as it's all Pixar technology.

Call me crazy, but I ended up creating all the USD in a text editor, no DCC required. I wouldn't necessary recommend this, but it is possible and gives you unmatched control. Of course, it's just as productive to create the template in any USD-enabled DCC. Solaris, Maya, Blender…

This works well with geometry, cameras and lights, but material assignments are a bit tricky as renderers often have unique features, attributes and syntax. Fortunately, it's not necessary for this project to have a complete implementation of a RenderMan shader network. We don't need color correction or displacement, for example. These would likely be used in the final render, but the narrow goal here is to check our texturing work.

Color correction would run counter to that goal since we want to get the textures right and not "fix" anything in render at this stage. Displacement is also overkill. Bump will look just as good for previewing the look and it will be much faster and easier to set up. Displacement is the ultimate goal most of the time, but compromises are needed for speed and interactivity.

Here are some examples of the USD syntax I created. The lights, backdrop and cameras are all reusable.

The asset being worked on is referenced by file name and materials are assigned.

Materials are created based on a template I created in advance. If the asset needs, say, 5 basic RenderMan materials with color, roughness, specular and bump inputs, then it's just a matter of copying the code and renaming the materials.

Moving on to the usdview portion of this project. There are two main challenges here: automating the conversion from EXR to RenderMan's TEX format and automating the scene update. RenderMan locks textures while a render is active, so we have to turn off the render temporarily, update the textures, then restart the render.

Fortunately, usdview is very scriptable using Python and all of this is easy to do. The entirety of the script amounts to 3 steps: switch the active render to Storm, update the textures using my PowerShell txcnv script, then restart the RenderMan Hydra delegate.

As a side note, I was somewhat amused that I wouldn't even have to rewrite txcnv in Python. You can just call PowerShell from Python. This probably isn't "optimal," but it works well enough and makes life easy. Which is why we do any of this stuff to begin with! Here's the entire Python script I ended up with:

usdviewApi.SetViewportRenderer('HdStormRendererPlugin')subprocess.run(["powershell", "-Command", "C:\\onedrive\\Scripts\\txcnv.ps1 r C:\\Users\\Brian\\Desktop\\lookdev\\tex"], capture_output=True)

usdviewApi.SetViewportRenderer('HdPrmanLoaderRendererPlugin')

You can run this using the usdview Python terminal, but that's annoying to do over and over. So, we'll add a button to the usdview interface and connect it to a function that runs our three lines of code.

We'll need to update only two files for this, mainWindowUi.ui and appController.py. The main window can be edited using Qt Creator, which is free for open source use. Download it here: https://www.qt.io/download-open-source 

Install Qt using the Qt Online Installer, then open mainWindowUi.ui in Qt Creator. In this case I just dragged a button into the design, gave it an internal name of btnMAGIC and changed the text to read "MAGIC."

Next, I added a function to connect to the button in appController.py. This line goes around line 1000 in the button click definition section:

selfui.btnMAGIC.clicked.connect(self.btnMAGIC)

And this goes around line 2300 where other functions are declared:

def _btnMAGIC(self):    self._usdviewApi.SetViewportRenderer('HdStormRendererPlugin')    subprocess.run(["powershell", "-Command", "path\\to\\txcnv.ps1 r path\\to\texfolder"], capture_output=True)    self._usdviewApi.SetViewportRenderer('HdPrmanLoaderRendererPlugin')

Note that appController.py does not need to recompiled. You can simply update it in situ in your USD build folder. Unfortunately, mainWindowUi.ui does need to be compiled.

You could redo the entire USD build, but it's much faster to use uic (Qt User Interface Compiler) to update only the UI file. Note that you need to use the correct version of Qt for this. You can open up mainWindowUi.py in your USD usdviewq build folder to see which version is required.

In my case the build used Qt 6, so I needed to make sure my Qt installation matches. Then, run the following command to compile the UI. Note that we need the -g python flag to compile to Python instead of the default C++.

./uic -g python path\to\mainWindowUI.ui -o path\to\mainWindowUI.py

That's it! Run usdview as admin (for RenderMan licensing purposes) and open your template USD scene. Check out how it looks, go back to Painter or Mari to make changes, export the textures, click MAGIC and that's all there is to it.

Expanding on this idea, I realized it would be possible to create the same setup using Houdini's Karma renderer. Houdini comes with a custom usdview build based on Houdini's versions of USD and Qt. You could easily run the 3-line Python script from within Houdini usdview, updating the last line to start Karma instead of RenderMan.

However, adding the interface button is a bit more complicated. Houdini currently uses Qt 5, so we'd need to compile the UI file using that version of Qt. Not insurmountable, just an extra consideration. I haven't taken the time to do it yet, but it should work great and would allow access to blazing fast previews using Karma XPU. Another thing to note is that the template scene would have to be updated to use MaterialX materials instead of RenderMan ones.

Conclusion

There you have it! We combined a lot of previous work to create a powerful way to quickly preview textures in a production renderer. This workflow can be a huge time saver, allowing you to focus on quickly iterating textures and getting near-immediate photorealistic feedback. Enjoy!

Files

Comments

No comments found for this post.