Menu Close

Category: OSL

OSL mini tutorial #2 Random map per tile for SimpleTiles map

Using only 1 map.

Welcome to my second OSL tutorial. Again, we will not write a single line of code in this tutorial. We will use SlateME as our OSL editor. Let me say it again, YOU DON’T NEED TO KNOW HOW TO CODE TO USE OSL IN 3dsMax.

I don’t want to spoil the ending. But, you should read til the end. 🙂

One of the advantage(or could be disadvantage for some users) of using OSL in 3dsMax is that it brings more granular and lower level of control which provide a greater flexibility. But, it also means that user need to learn and understand a new way of thinking(or workflow). Again it doesn’t mean you need to learn to code. But, you need to understand how and what kinds of data is flowing between lower level maps and how to control them. So, please try pay more attention to the explanation of “why” I’m connect port A to port B instead of memorizing map tree. 🙂

Today’s goal is randomizing textures in the tiles of Simple Tiles OSL shader so we can get infinite random tile texture from a few texture files.

    1. Open SlateME.
    2. Make a Simple Tiles map. Maps > OSL > Textures > Simple Tiles.
      This is an equivalent of Tiles legacy map. You can make a various tile or brick patterns.
    3. Double click the thumbnail so we can have a bugger thumbnail.
    4. Change Tiling Mode to Twist Box.

As you can see, OSL can output not only color information but also various data information. For this tutorial, we will mainly utilize Index data which is a integer index number for individual tiles. Let’s see that it means visually.

    1. Make 2 OSL > Math Vector > Random by Index.
    2. Connect Index port of Simple Tiles to Idx of both Random by Index map.

So, what’s happening here?

Random by Index map generates a random float number between Min and Max and drives the randomization with the Idx and Seed parameters.

Since Idx of Random by Index is provided by the Index value of Simple Tiles, all pixels in the same tile will get the same random value.You can see that well from the thumbnail, each tile has a different shade of gray.

But, you can see both map has exactly same pattern and color. That’s because both map has same Seed number by default. What is the Seed number? This is from the Wikipedia. “A random seed (or seed state, or just seed) is a number (or vector) used to initialize a pseudorandom number generator.”, which brings another important concept, pseudorandom.

In CG, we can not use true random number, if a number is truly random. That means every time when you render or even open file again. You will have a different number and different pattern! Therefore, all random number in CG is pseudorandom driven by Seed number. If Seed number is same you get the same ransom number just like the above image.

  1. Select the bottom Random by Index map
  2. Set Seed to “77”, You should get this.

OK. let’s make a bunch more maps and actually do something with these 2 random maps.

  1. Make the following maps
    OSL > Math Vector > Component (Vector)
    OSL > UVWCoordinates > UVW Transform
    OSL > BitmapLookUp
  2. Choose “C:\Program Files\Autodesk\3ds Max 2021\maps\uvwunwrap\uv_checker.png” for BitmapLookUp
    This is a new 4k UV template which is added in 2021.
  3. Connect Out of the top Random by Index > X of Component (Vector)
  4. Connect Out of the bottom Random by Index > Y of Component (Vector)
  5. Connect Out of the Component (Vector) > Offset of UVW Transform
    Do not connect anything to BitmapLookUp yet.

The 2 Random by Index we made were for the random Offset value of UVW, and it is a vector value. How do I know? If you see in UI, you can ses that it is made out of 3 values. The, it is a vector value.

So, we can not directly plug 2 float values into the Offset port. We need to assemble a vector data and plug into Offset. Component (Vector) map allow to compose or decompose a vector from/to 3 floats. Since we need to use only X and Y value. you don’t have to plug anything into Z. If no map is connected to the property, OSL map will use the value in the UI which was 0.

What we got so far? As you see in the thumbnail of UVW Transform, we randomly offset UV per tile. If you see more red, that means the pixel is offset more along U. If you see more green, that means the pixel is offset more along V. Remember Slate can only show any value range from 0-1 because it is made for color. Fortunately this case out data range is also 0-1. So, we could see what’s going on as image. But, it would be be the case all the time.

  1. Now Connect UVW of the UVW Transform > UV Coordinates of BitmapLookUp
    Tada! you can see your texture randomly offset by Tile ID.

Cool. Now how can I control the scale of texture? Yes, you change the Scale value of UVW Transform.

How can I control the size of tiles? Scale in Simple Tiles.

Let’s see what it looks like with a real texture. Remember this technique only works with seamless tileable texture. This is with the TexturesCom_RockSmooth0172_1_seamless_S.jpg from here. https://www.textures.com/. I use scale to 5.0 for UV.

How about some mid tone variation? We can use Tweak/Levels OSL map for this. We will also need another Random by Index map driven by Index.

  1. Select one of Random by Index map and SHIFT+drag to make a copy.
  2. Set Min as 0.75, Max as 1.25. Seed as 131.
  3. Add a OSL > Tweak/Levels map.
  4. Connect Out of the new Random by Index map to MidTones of Tweak/Levels.
  5. Connect Out(RGB) of BitmapLookUp map to the Input of Tweak/Levels.

OK, I hope you get the hang of how to wrangle data to drive values at this point. Next, let’s put the gaps in. There are unlimited ways to how to handle gaps. But, I’ll just go easiest way since the main purpose of this post is tutorial. The Bump output of Simple Tiles map already give you a black gaps and white tiles. I’ll use that output to composite with Multiply mode.

  1. Make OSL > Compositing > Composite map.
  2. Connect Out of the Tweak/Levels > Bottom layer RGB of Composite
  3. Connect Bump of the Simple Tiles  > Top layer RGB of Composite
  4. Set Top layer Alpha as 0.7, BlendMode as Multiply.

OK, it is getting there. Let’s add one more randomization, the rotation. By now, you should already know what to do.Yes, you need to have another Random by Index (Float) with range 0.1 – 360 and feed into Rotate of UVW Transform. BUT, since it is a tutorial, let’s make things more complicate to learn. What if we want to rotate only at right angle like 90, 180, 270 degree?

Our goal is get only one of the 0, 90, 180. 270 per tile. How we do that? Right, we can get a random value between 0 – 3 and multiply 90.0. But, Random by Index (Float) generates float number, and we don’t have Random by Index (Integer) map. Well, don’t worry. Here comes Float-to-Int map to the rescue!

  1. Copy one of Random by Index (Float).
  2. Set Min as 0.0, Max as 3.99. Seed as 666.
  3. Make OSL > Math Float > Float-to-Int map
  4. Set Mode as floor.
  5. Make OSL > Math Float > Multiply map
  6. Set B as 90.0
  7. Connect Out of the new Random by Index map to Input of Float-to-Int.
  8. Connect Out of the Float-to-Int map to A of Multiply
  9. Connect Out of the Multiply map to Rotate of UVW Transform.
    You may wonder why 3.99 instead of 3.00, and what the heck is “floor”? Floor is a way to convert a float value to integer value by returning the largest whole number (integer) that is less than or equal to the number. if you had 1.24, you would get 1.o. So, it is a floor of the range 1.0-2.0. There is also “ceil” which is kinda opposite. The ceil of 1.24 would be 2.0. By setting range as 0.0-3.99 and mode as floor, we are trying to make sure all 4 numbers are getting even chance. 0.0-1;0 > 0.0. 1.0-1.99 > 1, 2.0-2.99 > 2.0. 3.0-3.99 > 3.0.
    Left is without the rotation randomization. Right is with the rotation randomization.

As you can see, you can randomize any parameters you want. You just need to know when to stop. Should we stop now then? No, not yet. So far, we have used only one map file and looks like getting a good result. But, what if we can use multiple map files and randomly use per file?

Here is a great news. One of the new feature of 3dsMax 2021.2 is 1-of-N(Filename) map. If we don’t have this map, we have to setup a small tree with multiple BitmapLookup , 1-of-N Switcher and Random by Index map. Now we just need 2 maps.

  1. Add a OSL > Switchers > 1-of-N(Filename) map.
  2. Choose all 5 maps.
  3. Add a OSL > Switchers > Random Index by Number/Color map. BTW, such a great map, I wonder who made this? 🙂
  4. Connect Index of the Simple Tiles map to Input Number of Random Index by Number/Color.
  5. Connect Out of the Random Index by Number/Color to Filename of BitmapLookUp.

OK… This is the full tree. I guess we end up with not-so-mini-tutorial.

BUT! Yes, there is always. “BUT”.

We went through all these to learn how to work with OSL maps to build own randomization. Now I have to tell you this. Sorry, we didn’t need to go through all these if you wanted to just use it. Why? Because Zap made the awesome Bitmap Random Tiling for 3dsMax 2021.2.

This is what it looks like if you use Bitmap Random Tiling. Youjust need to plug Index into Seed. Make sure to turn off Randomize by UV position.

You can even randomize color, too.

If you want to use multiple map file? Then, re-use the 1-of-N(Filename). Another 2021.2 feature.

I guess it is worth to upgrade??? 🙂

If you are really lazy, here is the max file. It has the full setup and simple 2021.2 setup. I can not include texture file. So, you probably need to download some seamless tileable maps. Here is another good news. Because ,max file actually embed the source OSL code in the scene file, you can even open this file in 2019. You will see the new 2021.2 OSL shader there. Save the OSL map in a material library. Then, you can even use the new map in 2019 or 2020.  Another nice thing about 3dsMax OSL implementation!

Click to download .max file of this tutorial (2019 version)

Since you follow me all the way down here, you need to check renderStacks. Click here!

A teaser for the future article! What is the difference between the following 4 images?

The answer is… they all rendered in a different renderer. From the left, Corona, VRay, VRayGPU, Arnold. Yes, all different renderer. You can have exactly same map tree across different renderer even CPU/GPU. I can say this is the first time I ever see this is possible in CG history. I’ll have a blog post with more examples in the future.

3dsMax 2021 OSL Advanced User Interface

3ds Max has many cool OSL shaders. It also has some under the hood improvement for OSL shader developers for better user experience.

For details, you can check Help document. Click here.

Here is some highlights.

  • Additional metadata
    widget type “null”
    metadata connectable
    metadata worldunits
  • Row Packing
  • Custom Widgets
    max:ramp0
    max:actionButton
  • Dynamic UI
    help of the “max:actionButton” shown above, a few helper scripts have been introduced that makes shaders dynamic – as in – the shader is actually modifying its own sourcecode!
    Thanks to this. Now 1-of-5 and 1-of-10 has been consolidated to 1-of-N.
  • Fully Custom UI via QT
    allows a custom layout to be provided in the form of a .ui fil
    You can design cool UI with QtDesigner!
    The following images are a few new OSL maps which is using new Qt UI.

Mini OSL tutorial #1 – Random map rotation per tile

Let me just borrow text from 3dsMax help. You guys should read manual all the time’ Three are many good in formation! I highlighted important aspect of 3dsMax OSL map for you!

Open shading language (OSL) is an open source shading language that is fairly simple to understand. It can be used in several different ways. You can use the OSL Map, which is an execution environment for OSL shaders inside of 3ds Max, and it works like any regular built-in 3ds Max map. There is also a category of pre-loaded OSL maps that you can easily use. In addition, you can use any OSL maps you download from the internet. Finally, you can creating a shader or map in OSL using our development tools. This is a much simpler method to create custom maps than developing the equivalent functionality as a 3ds Max C++ map.

OSL works in any renderer supporting the regular 3ds Max shading API (Scanline, vRay, Corona, etc.). It also works outside of renderers, anywhere in 3ds Max where a regular map is requested, such as in the Displacement modifier. It also works with renderers that support OSL natively, such as Arnold. In those cases, the execution environment inside the OSL map is not sued, instead, the OSL source code, the parameter values and shader bindings are sent to the renderer, which executes the OSL code. More renderers supporting OSL natively are appearing daily.

OSL uses “just-in-time” compilation and optimization of entire shade trees at once, as long as all the shaders in the shade tree are OSL shaders. You can mix OSL shaders and regular shaders, but the optimizations will suffer.

First of all, I really really want to make sure about this.

As I posted before, You don’t have to code to use OSL maps in 3dsMax.

3dsMax OSL is seamlessly integrated just like all other C++ maps. There is ZERO difference in terms of how to use and where you can use. Also if you chain OSL map together, 3dsMax combine them the entire OSL chain and make a single shader under the hood. Essentially Slate ME is acting as an OSL node editor for you. Even better 3dsMax 2021 ships with 123 build-in shaders to start with. At these point, almost all 3dsMax legacy map could be replace with OSL. This mini tutorial is a very good example of using Slate ME as an OSL node editor.

At a Stack post, we god a question.

In this tutorial, the blender guru is using a custom tool in order to randomize the uv’s rotation so we can’t see anymore the repetitive pattern on a large scale tiling texture. He says that, as far as he knows, this kind of tool doesn’t exist in any other 3d software because it involves maths tricks and vectors and nobody wants to deal with this.

Good news! you don’t need custom node for this. Master Zap let me know how to do this with built-in OSL node. I’m posting the master;s answer with my explanation so you can go further.

First, this is the graph. 4 nodes!

 

Let’s see one by one.

UVTransform : Tiling

This OSL map is like Coordinate rollout in other maps. It allows you to move, rotate and scale uv coordinate. I tiled uv coordinate here. So, I tilted here with Tiling parameters.

Tip! You can connect one UVTransform to many OSL maps whicn means you can control the coordinate of all those map at once.

Noise : Give random value per tile

This map generates a random 0-1 value per tile which will be used as rotation value later.

As the name says, it is an OSL version of Noise map. It has 6 types of noise in a map. We will use Cell type which makes random pixel bitmap patter.

Then, set Scale to 1.0 and Octave to 1. This makes the noise function generates one value per tile. If you increase Scale or Octave, it will essentially divide each tile.

Then, turn off Step Function to prevent blending.

Multiply : convert to degree

Multiply 360 so we can get rotation value between 0-360. As you can see, you don’t have to make a map for value B. You can just type in B parameters of the map.

UVTransform : randomize uv rot

This map rotates UV per tile. You don;t need to set any value here. Just connect UVTransform : Tiling to Input(UVW) which inherit tiling from UVTransform : Tiling map. Then, connect Multiply : convert to degree to Rotate.

Now you can connect this map to any maps UVW port.

Download random rotation per tile OSL setup max file

Do you like to work smart? Just like this map? Then, you will like renderStacks. Click here and check it out!

3dsMax 2020 – OSL update

3dsMax developer has changed their delivery model to continuous delivery. Instead of delivering a feature at one release, now a feature will be delivered continuously until all the planned feature is finished. The automatic OSL > HLSL conversion for viewport was the one of them. It has been improved in every PU since tisinception. Now almost all OSL shader will be automatically converted to HLSL including 3rd party OSL shaders.

Also, the viewport playback performance of animated OSL map has been greatly improved.

This is the viewport playback of the sample file for my OSL shader pack1 in 3dsMax 2019/2020.

3dsMax 2019.3 – OSL Viewport Support : OSL > HLSL

Since it is introduced in 3dsMax 2019, OSL Map has been comtinuously improved in every release.
There has been many updated on performance, OSL editor useability and viewport display.
The most important improvement among all is the viewport display.

Now 3dsMax viewpot can display almost all shippinig OSL and many 3rd party OSL shaders properly even as 3D procedural map.
How canit even support random 3rd party OSL shader?
The 3dsMax rendering team has developed automatic OSL > HLSL converter instead of making HLSL shader for each OSL shader.

The OSL shaders in the following images are all 3rd party OSL as 3D procedural map.
It is oddly satisfying to see all the 3D shaderes in the viewport exactly as renders.

And,,, a little bird told me even more stuff might come in the future. 🙂

3dsMax 2019 – OSL shader pack 1

You don’t need to download this shaders anymore. 3dsMax 2020 has a better version of all these shaders built-in.

While I was beta testing 3dsMax 2019, I made a few OSL maps. Nothing spectacular. Most of them are just “artist-friendly” pre-made setups to save some nodes.

Download OSL shader pack 1 or at http://UncleBobsShaders.com. Make sure to visit Uncle Bobs Shader Emporium for cool OSL shaders!

UVW > MatCapUV

This is a renderable version of my superClayMode script. Plug into the UVW slot of Bitmap Lookup.

Value > Color by Colorspace

You can conver to a vector value of other color space to RGB.

Math\Color > RGB to Other(Color)

You can convert a color from RGB to other color space. Output value is vector. after you process it, you can convert back to RGB with Color By Colorspace

Switchers > Random Index by Number/Color

It generates random integer index by number or color input. When you need to randomize something by Object ID, Materaal ID, Node Name and Node Handle, this map will be very handy. Of course you can also do the same thing by assembing a few other maps. I just made as one map for your convinience.

Math\Float > Sine wave function of frames

You can generate sine wave of time. It supports amplitude, period, phase value and square wave option. Check my sample animation. This map is very handy when you need to make some cyclic map animation.

!!! You DON”T need to connect Frame Number input. It already has float expression controller assigned. !!!

Scene > Normal

You can get normal value of pixel in various spaces.

Falloff

Falloff map OSL version. It supports Perpendicular/Parallel and Towards/Away.

BlendModel

Legacy Composite map OSL version. It supports all bklending mode in legacy Composite map. I was trying to support all Photoshop mode. But, I gave up on Vivid Light and Linear Light.

Here is a QC image that shows this map and legacy Composite map are producing the same result.

How to Install

1. Make “OSL” subfolder in any plugin folder
2. Unzip and copy *.osl files into the folder

A sample max file

Here is the shader tree for the animation. I used the distance from local center and random sin wave as the light intensity. No keyframes al all. The max file is included in the shader pack .zip file.

3dsMax 2019 – OSL map

3dsMax 2019 has been released.

The most noticable feature is the OSL(Open Shading Language) map. You should watch Mads video to see what it can do. Obviously this is a god send for technical minded users. It is like MCG for maps. You can make anything. Your imagination is the limit.

But, what does it brings to the artist who doesn’t/can’t/doesn’t want to code?

3dsMzx 2019 is shipped with 101 OSL maps from bitmap loading to procedural noise, color correction and utilities. Thisbrings some interesting features and workflows. Let’s see what we can do with them.

Random By Index

You can randomize any vaule type that OSL supports by index number. For example, You can randomize gain value(float) or UVW offset(vector) or diffuse color. Anything!

Object property access

Even better, OSL map allows to access various object data such as Material ID, Object ID, Wire(frame) Color, Node Handle(a unique id per object), Node(Object) name and User properties(!). If you combine these maps with Rendom By Index map, you can randomize almost every map/material paramateres per object. Here is an exmaple. All object have the same material with single bitmap texture.

Switcher

Finally the switcher map has been arrived. This map allow you choose a map among the multiple children map. You have 1-of-10 and 1-of-5. But, you can cascade them to support more than 10.

Independent UVW control

It is like Coordinate rollout is a seperate map, and you can plugin the UVW into multiple maps. Yes, now you can instance UVW across multiple maps. Also you can also randomize UV by using the above maps. Do you want to distort UV? then apply a noise map to UVW map.

Randomized Bitmap

“Randomly place (and alpha blend) a set of bitmaps on top of something else”.
Just try it. So much fun!

Shuffling channel

You can easily shuffle channels around. Find Compoments(Color) map and connect from where you want get to where you want to put.

 .tx /.dpx format loading

OSL uses OIIO for image IO. Therefore, the image formats which supported by OIIO will be supported in OSL map. But, you can read .tx and .dpx directly.

Filename as a map

When you have a single file which is needed be used in multiple map. You can use Filename map and feed to the path to multiple Bitmap Lookup maps(OSL version of bitmap map).

Gamma checkbox in the map

You don’t need to use file dialog anymore for gamma settings. Gamma setting is in the paramaters rollout! It also has AutoGanna option which will set gamma value depends on the file format.

Samplerinfo

OSL gives you access to various scene data such as position/normal/uv. You can get this data in various space. You can use local object position or world normal vector as map. Do you want to render out UV as texture? Just plug UVW to diffuse color.

Math, Math, Math

You can do all kinds of math you want to do. Many math functions are exposed as maps. You don’t have to “code” for simple math operations. Do you want to have a black and white mask for your mountain? Let world position value and remap to 0-1. Simple.

Granular color correction

Of course, you can use any math maps to do whatever you want. But, 3dsMax 2019 also has 2 OSL maps you can use for color correction, Lift/Gamma/Gain and Tweak. This should cover all features of legacy Color Correction map.

Procedural map that renders exactly same across renderer

Many renderers support 3dsMax noise map. But, the result of the noise map could be different for the renderer which doesn’t use 3dsMax map api because they have own implementation of noise map. In this case, your rendered noise mapptern would not match with other portion of 3dsMax such as Displace modifier. If you use OSL procedurals, the render result would be exactly same regardless of renderers. This is HUGE. OSL allow to have a foundation of unified map workflow across renderers. Check out these renders. The left one is rendered with VRay. The right one is rendered with Arnold.

3dsMax 2019 come with new noise map with the follwing 6 types of new noise. perlin/uperlin/simplex/cell/hash/gabor

New pattern maps

It also has a few interesting new pattern maps.
Checker(3D), Candy, Mandelbrot, Revets, Digits

Unified and portable map tree

The biggest chanllenge of moving shader around between renderer is the complicated map tree. One incompatible map in the middle of shader tree will break the shader tree from that point. Even thiough there are enough matching maps. It is almost impossible to reuse shader tree and produce exactly the same result. With OSL, you can. As long as you stay in OSL, the result map tree will always be same just like procedurals.

Possibility of rendering on Linux

You already can convert mesh data to a renderer scene file format like vrscene or ass, rib file for rendering. But, the nature of 3dsMax renderer integretion always requires 3dsMax to evaulate map tree unless you only uses the renderer native maps. This is the main obstacle to render max scene on linux.  Now with OSL, the renderer scene file format could include all map tree in the file and render. It opens a posibility of rendering 3dsMax scene on Linux.

This is a new era for rendering in 3dsMax. Enjoy!