Overview of OSL Shaders in Octane

Forums: Overview of OSL Shaders in Octane
A forum where development builds are posted for testing by the community.
Forum rules
NOTE: The software in this forum is not %100 reliable, they are development builds and are meant for testing by experienced octane users. If you are a new octane user, we recommend to use the current stable release from the 'Commercial Product News & Releases' forum.

Re: overview of OSL Shaders in Octane

Postby Renart » Wed Nov 08, 2017 6:32 pm

Renart Wed Nov 08, 2017 6:32 pm
Hello,

I'm experimenting with OSL and I'm trying to use it for some parallax mapping :
http://interiormapping.oogst3d.net/

This is the code I'm using at the moment (found on this guy's blog : http://julius-ihle.de/?p=2451)

Code: Select all
#include <stdosl.h>

shader ParallaxInterior(
   int zUpAxis = 0 [[ string widget = "boolean" ]],
        string filename = "" [[ string widget = "filename" ]],
        int textureFlip = 0 [[ string widget = "boolean" ]],
        int textureFlop = 0 [[ string widget = "boolean" ]],
        float roomDepth = 1 [[ float min = 0.1, float max = 100 ]],
        float widthOverscan = 0 [[ float min = 0.0, float max = 0.9 ]],
        float heightOverscan = 0 [[ float min = 0.0, float max = 0.9 ]],   
        int enableMidground = 0 [[ string widget = "boolean" ]],
        float midgroundDepth = 0.5 [[ float min = 0.05, float max = 99 ]], 
        float midgroundOffsetX = 0,
        float midgroundOffsetY = 0, 
        int enableCurtains = 0 [[ string widget = "boolean" ]],
        output color outRGB = 0.0,
)
{
    //user controls remapping
    float roomDepthMult = clamp(roomDepth,0.1,100);
    float heightOverscanMult = 1 - clamp(heightOverscan,0,0.9);
    float widthOverscanMult = 1 - clamp(widthOverscan,0,0.9);
    float midgroundDepthMult = clamp(midgroundDepth,0.05,roomDepthMult-0.01);
    float midgroundOffY = midgroundOffsetY * (textureFlip*2-1) * 0.1;
    float midgroundOffX = midgroundOffsetX * (textureFlop*2-1) * 0.1;
   
   
    //global variables & remapping
    vector objI = transform("object", -I);
    if (zUpAxis > 0){
      objI = vector(-objI[0],-objI[1],-objI[2]) * color(widthOverscanMult, heightOverscanMult, 1);      //reorder to match UV for Y up axis
    } else {
      objI = vector(-objI[0],objI[2],-objI[1]) * color(widthOverscanMult, heightOverscanMult, 1);      //reorder to match UV for Z up axis
    }
    color objPOrig = (color(u,v,0.5) * 2 - 1) * 0.5 + 0.5;                     //for curtains
    color objP = (color(u,v,0.5) * 2 - 1) * color(widthOverscanMult, heightOverscanMult, 1)  * 0.5 + 0.5;    //UV seems to be the better approach
   
   
    //bases for width/height/depth
    vector sections = step(0, objI);
    color baseDepth = (objP-sections)/(-objI * roomDepthMult);
    color mgDepth = (objP-sections)/(-objI * midgroundDepthMult);   
    color baseBack = (objP-sections)/(-objI);
    color baseWidth = baseDepth * roomDepthMult;
   
   
   
    //depth and width ramps
    color baseDepthX = (baseDepth[1]*objI+objP + 1);
    color baseDepthY = (baseDepth[0]*objI+objP + 1);
    color baseWidthX = (baseWidth[1]*objI+objP + 1);
    color baseWidthY = (baseWidth[0]*objI+objP + 1);

    float horizU = baseDepthY[2] - 0.5;
    float vertU = baseWidthX[0] - 1;
    float horizV = baseWidthY[1] - 1;
    float vertV = baseDepthX[2] - 0.5;
   
   
    //convert ramps to UV/ST... WIP - not very efficient
    float sideWallsMask = step(0,horizU) * step(0,1-max(horizV, 1-horizV));
    color sideWallsUV = color(horizU, horizV, 0) / 3;
    color rWallUV = (sideWallsUV + color(2.0/3.0, 1.0/3.0, 0)) * sideWallsMask * sections[0];
    color lWallUV = (sideWallsUV + color(0.0, 1.0/3.0, 0)) * sideWallsMask * (1-sections[0]);
    lWallUV[0] = (1.0/3.0 - lWallUV[0]) * sideWallsMask * (1-sections[0]);     
   
    float FloorCeilMask = step(0,vertV) * step(0,1-max(vertU, 1-vertU));
    color FloorCeilUV = color(vertU, vertV, 0) / 3;
    color ceilUV = (FloorCeilUV + color(1.0/3.0, 2.0/3.0, 0)) * FloorCeilMask * sections[1];
    color floorUV = (FloorCeilUV + color(1.0/3.0, 0, 0)) * FloorCeilMask * (1-sections[1]);
    floorUV[1] = (1.0/3.0 - floorUV[1]) * FloorCeilMask * (1-sections[1]);
   
    color backWallUV = ((baseBack[2]*objI + (objP/2)/(roomDepthMult)) * (roomDepthMult*2) / 3 + color(1.0/3.0, 1.0/3.0, 0) ) * (1 - max(step(0,horizU), step(0,vertV)));

   
    color midgroundUV = (1.0/3.0 - (baseBack[2]*objI + (objP)/(midgroundDepthMult*2)) * (midgroundDepthMult*2) / 3);
    float midgroundMask = step( 0, midgroundUV[1] * 3 * (1-midgroundUV[1]*3) ) * step( 0, midgroundUV[0] * (1.0/3.0-midgroundUV[0]) );
    midgroundUV = (color(midgroundOffX, midgroundOffY, 0) + midgroundUV) * midgroundMask;
    midgroundUV[1] = 1-midgroundUV[1]; 
   
    color curtainsUV = objPOrig * color(1.0/3.0, 1.0/3.0, 1);
    curtainsUV[0] = 1.0/3.0 - curtainsUV[0];


   
    color finalUV = ceilUV + floorUV + rWallUV + lWallUV + backWallUV;
   
   
   
   
    //flipping ctrl
    if (textureFlop > 0){
        midgroundUV[0] = 1.0/3.0 - midgroundUV[0];
        curtainsUV[0] = 1.0/3.0 - curtainsUV[0];
    }else
        finalUV[0] = 1-finalUV[0];
    if (textureFlip > 0){
        finalUV[1] = 1-finalUV[1];
        midgroundUV[1] = 1 - midgroundUV[1] + 2.0/3.0;
        curtainsUV[1] = 1.0/3.0 - curtainsUV[1];
    }
   

    color roomRGB = texture(filename, finalUV[0], finalUV[1]);
       
    color finalRGB;
   
   
   
   
    //midground switch
    if (enableMidground > 0){
        float midgroundA;
        color midgroundRGB = texture(filename, midgroundUV[0], midgroundUV[1], "alpha", midgroundA);
        finalRGB = mix(roomRGB,midgroundRGB,midgroundA);
    }
    else{
        finalRGB = roomRGB;
    }
   
   
   
   
    //curtains switch
    if (enableCurtains > 0){
        float curtainsA;
        color curtainsRGB = texture(filename, curtainsUV[0], curtainsUV[1], "alpha", curtainsA);
        finalRGB = mix(finalRGB,curtainsRGB,curtainsA);
    }


   

    outRGB = finalRGB;

}


It works but I was wondering how to have a classic Octane Texture File input and not using just a string like this?

If I use just a Color command to create the input, it can't be read later since it's looking for a String (Filename variable) when he is creating the final output, line 104.

I'm very nooby in coding and some help would be appreciated :)
Attachments
parallaxmapping.jpg
Renart
Licensed Customer
Licensed Customer
 
Posts: 70
Joined: Mon Jul 04, 2016 8:21 pm

Re: overview of OSL Shaders in Octane

Postby mojave » Wed Nov 08, 2017 8:56 pm

mojave Wed Nov 08, 2017 8:56 pm
Renart wrote:If I use just a Color command to create the input, it can't be read later since it's looking for a String (Filename variable) when he is creating the final output, line 104.

I'm very nooby in coding and some help would be appreciated :)


Hi Renart,

You can use delayed evaluation (_evaluateDelayed()) to achieve this. To do so, you should replace the input argument as well as all texture access calls and that should just do the trick.

I hope that helps.
User avatar
mojave
OctaneRender Team
OctaneRender Team
 
Posts: 1259
Joined: Sun Feb 08, 2015 10:35 pm

Re: Overview of OSL Shaders in Octane

Postby Renart » Thu Nov 09, 2017 12:02 pm

Renart Thu Nov 09, 2017 12:02 pm
Thanks Mojave for the reply.
I think I get the idea of delaying the evaluation but I can't manage to make it works.

The original line for the texture access is :
Code: Select all
color roomRGB = texture(filename, finalUV[0], finalUV[1])

Where filename is the string.

But if I replace by something like:

Code: Select all
color roomRGB = _evaluateDelayed(file, finalUV[0], finalUV[1])

where file is just a color input created at the beginning to be able to connect my texture node. It reads the texture but the entire effect stop working and it applies the image as a normal texture.

Here is the entire code:

Code: Select all
#include <stdosl.h>
#include <octane-oslintrin.h>

shader ParallaxInterior(
   int zUpAxis = 0 [[ string widget = "boolean" ]],
        string filename = "" [[ string widget = "filename" ]],
        //I've added this texture input
        color file = 0,
        //
        int textureFlip = 0 [[ string widget = "boolean" ]],
        int textureFlop = 0 [[ string widget = "boolean" ]],
        float roomDepth = 1 [[ float min = 0.1, float max = 100 ]],
        float widthOverscan = 0 [[ float min = 0.0, float max = 0.9 ]],
        float heightOverscan = 0 [[ float min = 0.0, float max = 0.9 ]],   
        int enableMidground = 0 [[ string widget = "boolean" ]],
        float midgroundDepth = 0.5 [[ float min = 0.05, float max = 99 ]], 
        float midgroundOffsetX = 0,
        float midgroundOffsetY = 0, 
        int enableCurtains = 0 [[ string widget = "boolean" ]],
        output color outRGB = 0.0,
)
{
    //user controls remapping
    float roomDepthMult = clamp(roomDepth,0.1,100);
    float heightOverscanMult = 1 - clamp(heightOverscan,0,0.9);
    float widthOverscanMult = 1 - clamp(widthOverscan,0,0.9);
    float midgroundDepthMult = clamp(midgroundDepth,0.05,roomDepthMult-0.01);
    float midgroundOffY = midgroundOffsetY * (textureFlip*2-1) * 0.1;
    float midgroundOffX = midgroundOffsetX * (textureFlop*2-1) * 0.1;
   
   
    //global variables & remapping
    vector objI = transform("object", -I);
    if (zUpAxis > 0){
      objI = vector(-objI[0],-objI[1],-objI[2]) * color(widthOverscanMult, heightOverscanMult, 1);      //reorder to match UV for Y up axis
    } else {
      objI = vector(-objI[0],objI[2],-objI[1]) * color(widthOverscanMult, heightOverscanMult, 1);      //reorder to match UV for Z up axis
    }
    color objPOrig = (color(u,v,0.5) * 2 - 1) * 0.5 + 0.5;                     //for curtains
    color objP = (color(u,v,0.5) * 2 - 1) * color(widthOverscanMult, heightOverscanMult, 1)  * 0.5 + 0.5;    //UV seems to be the better approach
   
   
    //bases for width/height/depth
    vector sections = step(0, objI);
    color baseDepth = (objP-sections)/(-objI * roomDepthMult);
    color mgDepth = (objP-sections)/(-objI * midgroundDepthMult);   
    color baseBack = (objP-sections)/(-objI);
    color baseWidth = baseDepth * roomDepthMult;
   
   
   
    //depth and width ramps
    color baseDepthX = (baseDepth[1]*objI+objP + 1);
    color baseDepthY = (baseDepth[0]*objI+objP + 1);
    color baseWidthX = (baseWidth[1]*objI+objP + 1);
    color baseWidthY = (baseWidth[0]*objI+objP + 1);

    float horizU = baseDepthY[2] - 0.5;
    float vertU = baseWidthX[0] - 1;
    float horizV = baseWidthY[1] - 1;
    float vertV = baseDepthX[2] - 0.5;
   
   
    //convert ramps to UV/ST... WIP - not very efficient
    float sideWallsMask = step(0,horizU) * step(0,1-max(horizV, 1-horizV));
    color sideWallsUV = color(horizU, horizV, 0) / 3;
    color rWallUV = (sideWallsUV + color(2.0/3.0, 1.0/3.0, 0)) * sideWallsMask * sections[0];
    color lWallUV = (sideWallsUV + color(0.0, 1.0/3.0, 0)) * sideWallsMask * (1-sections[0]);
    lWallUV[0] = (1.0/3.0 - lWallUV[0]) * sideWallsMask * (1-sections[0]);     
   
    float FloorCeilMask = step(0,vertV) * step(0,1-max(vertU, 1-vertU));
    color FloorCeilUV = color(vertU, vertV, 0) / 3;
    color ceilUV = (FloorCeilUV + color(1.0/3.0, 2.0/3.0, 0)) * FloorCeilMask * sections[1];
    color floorUV = (FloorCeilUV + color(1.0/3.0, 0, 0)) * FloorCeilMask * (1-sections[1]);
    floorUV[1] = (1.0/3.0 - floorUV[1]) * FloorCeilMask * (1-sections[1]);
   
    color backWallUV = ((baseBack[2]*objI + (objP/2)/(roomDepthMult)) * (roomDepthMult*2) / 3 + color(1.0/3.0, 1.0/3.0, 0) ) * (1 - max(step(0,horizU), step(0,vertV)));

   
    color midgroundUV = (1.0/3.0 - (baseBack[2]*objI + (objP)/(midgroundDepthMult*2)) * (midgroundDepthMult*2) / 3);
    float midgroundMask = step( 0, midgroundUV[1] * 3 * (1-midgroundUV[1]*3) ) * step( 0, midgroundUV[0] * (1.0/3.0-midgroundUV[0]) );
    midgroundUV = (color(midgroundOffX, midgroundOffY, 0) + midgroundUV) * midgroundMask;
    midgroundUV[1] = 1-midgroundUV[1]; 
   
    color curtainsUV = objPOrig * color(1.0/3.0, 1.0/3.0, 1);
    curtainsUV[0] = 1.0/3.0 - curtainsUV[0];


   
    color finalUV = ceilUV + floorUV + rWallUV + lWallUV + backWallUV;
   
   
   
   
    //flipping ctrl
    if (textureFlop > 0){
        midgroundUV[0] = 1.0/3.0 - midgroundUV[0];
        curtainsUV[0] = 1.0/3.0 - curtainsUV[0];
    }else
        finalUV[0] = 1-finalUV[0];
    if (textureFlip > 0){
        finalUV[1] = 1-finalUV[1];
        midgroundUV[1] = 1 - midgroundUV[1] + 2.0/3.0;
        curtainsUV[1] = 1.0/3.0 - curtainsUV[1];
    }
   
    //Original line
    //color roomRGB = texture(filename, finalUV[0], finalUV[1]);
    //Edited line
    color roomRGB = _evaluateDelayed( file, finalUV[0], finalUV[1] );
    color finalRGB;
   
   
   
   
    //midground switch
    if (enableMidground > 0){
        float midgroundA;
        color midgroundRGB = texture(filename, midgroundUV[0], midgroundUV[1], "alpha", midgroundA);
        finalRGB = mix(roomRGB,midgroundRGB,midgroundA);
    }
    else{
        finalRGB = roomRGB;
    }
   
   
   
   
    //curtains switch
    if (enableCurtains > 0){
        float curtainsA;
        color curtainsRGB = texture(filename, curtainsUV[0], curtainsUV[1], "alpha", curtainsA);
        finalRGB = mix(finalRGB,curtainsRGB,curtainsA);
    }


   

    outRGB = finalRGB;

}


Thank you very much if you can help me understand this, I'm a bit confused...
Renart
Licensed Customer
Licensed Customer
 
Posts: 70
Joined: Mon Jul 04, 2016 8:21 pm

Re: Overview of OSL Shaders in Octane

Postby mojave » Thu Nov 09, 2017 9:19 pm

mojave Thu Nov 09, 2017 9:19 pm
You may have missed to set the projection of your input texture to OSL UV, check the "Custom UV mapping" section at the end of the introduction for more details.
User avatar
mojave
OctaneRender Team
OctaneRender Team
 
Posts: 1259
Joined: Sun Feb 08, 2015 10:35 pm

Re: Overview of OSL Shaders in Octane

Postby roeland » Sun Nov 12, 2017 9:39 pm

roeland Sun Nov 12, 2017 9:39 pm
funk wrote:I was looking at the flakes how to use with triplanar projection ? on stadalone? Just a curiosity.


If you want similar behaviour as the octane texture nodes with a projection and a UV transform, add a matrix input and a point input.

Code: Select all
   point projection = 0
            [[string label = "Projection", string inputType = "projection"]],
   matrix uvTransform = matrix(.33333, 0, 0, -.5, 0, .33333, 0, -.33333, 0, 0, .33333, 0, 0, 0, 0, 1)
            [[string label = "UV transform", int dim = 2]],


You can use 2 or 3 as the dim value to choose the appearance of transform value nodes in the UV transform input.

In your shader you can calculate the UVs to use as follows:

Code: Select all
    point p = transform(1 / uvTransform, projection);


This will closely emulate the behaviour of Octane texture nodes, the exception is that UVW transform textures don't have an effect on the transform inputs. This is something we may add later.

Also someone mentioned that mapping point inputs to projection pins is a bit arbitrary. We will add more explicit control over this, but we may end up requiring a metadata value for creating projection inputs in one of the next test releases, most likely string inputType = "projection".

-Roeland
User avatar
roeland
OctaneRender Team
OctaneRender Team
 
Posts: 1808
Joined: Wed Mar 09, 2011 10:09 pm

Re: Overview of OSL Shaders in Octane

Postby v-cube » Tue Nov 14, 2017 5:36 pm

v-cube Tue Nov 14, 2017 5:36 pm
Hello Forum,

is this now possible with osl scripting:

https://www.youtube.com/watch?v=7FmvMbFkh0s

this would be so helpfull for me, since I have to do a lot of large scale texturing and I constantly have to battle against tiling...

there is a lot of multi textures out there for example here to try out :

http://www.vizpark.com/shop/beech-wood-parquet/

best

Andreas
Architectural Rendering Services
1 x 4090 GTX, 1 x 3090 GTX
http://www.v-cube.de
User avatar
v-cube
Licensed Customer
Licensed Customer
 
Posts: 485
Joined: Fri Jul 22, 2011 11:02 am
Location: Aachen, Germany

Re: Overview of OSL Shaders in Octane

Postby coilbook » Wed Nov 15, 2017 7:51 pm

coilbook Wed Nov 15, 2017 7:51 pm
Can someone from Otoy answer. I asked many times but no answer.
Can you guys develop shaders like this for us (paint flakes, asphalt, wood etc) and sell it to us. Not everyone has time and knows coding well enough to take advantage of OSL otherwise it will be a useless tool for 90% of the users.
coilbook
Licensed Customer
Licensed Customer
 
Posts: 2984
Joined: Mon Mar 24, 2014 2:27 pm

Re: Overview of OSL Shaders in Octane

Postby roeland » Wed Nov 15, 2017 8:50 pm

roeland Wed Nov 15, 2017 8:50 pm
Yes, the plan is to have some OSL materials in the liveDB. The tile floor example is possible and is one of the main reason why we introduce the delayed evaluation feature. We will post an example shader later.
User avatar
roeland
OctaneRender Team
OctaneRender Team
 
Posts: 1808
Joined: Wed Mar 09, 2011 10:09 pm

Re: Overview of OSL Shaders in Octane

Postby coilbook » Wed Nov 15, 2017 9:09 pm

coilbook Wed Nov 15, 2017 9:09 pm
roeland wrote:Yes, the plan is to have some OSL materials in the liveDB. The tile floor example is possible and is one of the main reason why we introduce the delayed evaluation feature. We will post an example shader later.


thanks. But you also should sell some so your company will have motivation and resources to make a large variety of cool shaders.
coilbook
Licensed Customer
Licensed Customer
 
Posts: 2984
Joined: Mon Mar 24, 2014 2:27 pm

Re: Overview of OSL Shaders in Octane

Postby roeland » Wed Nov 15, 2017 9:41 pm

roeland Wed Nov 15, 2017 9:41 pm
A basic shader for a laminate floor looks like this:

Code: Select all
#include <octane-oslintrin.h>

shader Laminate(
    color plank1 = .3,
    color plank2 = color(0, 0, 1),
    color plank3 = color(0, 1, 0),
    color plank4 = color(0, 1, 1),
    color plank5 = color(1, 0, 0),
    color plank6 = color(1, 0, 1),
    color plank7 = color(1, 1, 0),
    color plank8 = 1,
    color plank9 = .1,
    float plankAspect = 5 [[float min = .01, float max=100, float sliderexponent=3]],
    matrix Transform = .25,
    point Projection = point(u, v, 0) [[string inputType = "projection"]],
    output color c = 0)
{
    int AMOUNT = 9;
    // use the projection and transform inputs
    point p = transform(1/Transform, Projection);
    float y = p[1] * plankAspect;
    // random offset for each row
    float x = p[0] + noise("cell", y, 0);
    // random plank and orientation for each cell
    float rnd = noise("cell", x, y) * AMOUNT;
    int flip = (rnd - floor(rnd)) < .5;
    // make UV mapping per cell and evaluate the right texture
    float plU = x - floor(x);
    float plV = y - floor(y);
    if (flip)
    {
        plU = 1 - plU;
        plV = 1 - plV;
    }
    if      (rnd < 1) { c = _evaluateDelayed(plank1, plU, plV); }
    else if (rnd < 2) { c = _evaluateDelayed(plank2, plU, plV); }
    else if (rnd < 3) { c = _evaluateDelayed(plank3, plU, plV); }
    else if (rnd < 4) { c = _evaluateDelayed(plank4, plU, plV); }
    else if (rnd < 5) { c = _evaluateDelayed(plank5, plU, plV); }
    else if (rnd < 6) { c = _evaluateDelayed(plank6, plU, plV); }
    else if (rnd < 7) { c = _evaluateDelayed(plank7, plU, plV); }
    else if (rnd < 8) { c = _evaluateDelayed(plank8, plU, plV); }
    else              { c = _evaluateDelayed(plank9, plU, plV); }
}


How to use: the OSL texture node node will have 9 texture inputs named plank1 to plank9. Connect each to an image texture, and for the image textures set the projection to “OSL UV”.

-Roeland
User avatar
roeland
OctaneRender Team
OctaneRender Team
 
Posts: 1808
Joined: Wed Mar 09, 2011 10:09 pm
PreviousNext

Return to Development Build Releases


Who is online

Users browsing this forum: No registered users and 5 guests

Thu Mar 28, 2024 11:57 am [ UTC ]