JiWindowBox_Examples.zip
// jiWindowBox - creates a fake "room" from a single plane// jiWindowBox.osl, by Julius Ihle// windowAspect wall distortion fix by David McDonnell// UI overhaul to Qt, filenmae widget & Color grading integrated by Mads Drøschler// External Grading function from the OSL CC base node// Mads Drøschler// Modified 4/15/21 by Saul Espinosa for Redshift 3d Support// Added ACES output, Gamma, and new page/min/max metadatacolor Grader (color Input, color InputMin, color InputMax, vector HSV, color OutputMax, color OutputMin, float MidTones, int Clamp){ color Out; color col = (Input - InputMin) / InputMax; color hsv = transformc("rgb", "hsv", col); hsv[0] += HSV[0]; hsv[1] *= HSV[1]; hsv[2] *= HSV[2]; col = transformc("hsv", "rgb", hsv); Out = mix(OutputMin, OutputMax, pow(col, 1.0/MidTones)); if (Clamp) Out = clamp(Out, 0.0, 1.0); return Out; }// UI overhaul port to QT for 3dsmax custom User interface// Mads Drøschler shader jiWindowBox_Redshift[[ string help = "Window Box Projection Shader", string label = "Window Box" ]]( // Filename node is not needed with the string widget "filename" in max with this addition. // User can load the texture directly into the shader. // Mads Drøschler string input_tex = "" [[ string widget = "filename", int connectable = 0, string page = "0 : Texture", ]], int zUpAxis = 0 [[ string widget = "checkBox", int connectable = 0, string page = "0 : Texture", ]], int textureFlip = 0 [[ string widget = "checkBox", int connectable = 0, string page = "0 : Texture", ]], int textureFlop = 0 [[ string widget = "checkBox", int connectable = 0, string page = "0 : Texture", ]], float Hue = 0 [[ int connectable = 0, string page = "1 : Color Correct", float min = 0, float max = 1 ]], float Saturation = 1 [[ int connectable = 0, string page = "1 : Color Correct", float min = 0, float max = 1, ]], float Value = 1 [[ int connectable = 0, string page = "1 : Color Correct", float min = 0, float max = 100 ]], float ManualGamma = 2.2 [[ string label="Gamma", string page = "1 : Color Correct", float min = 0, float max = 5 ]], color InputMin = 0.0 [[ string help = "The input value that maps to the darkest output. Incoming black level. ", int connectable = 0, string page = "2 : Color Clamp", ]], color InputMax = 1.0 [[ string help = "The input value that maps to the brightst output. Incoming white level. ", int connectable = 0, string page = "2 : Color Clamp", ]], float MidTones = 1.0 [[ string help = "Adjusts the MidTones/Gamma.",float min = 0.01, float max = 9.99, int connectable = 0, string page = "2 : Color Clamp", ]], color OutputMin = 0.0 [[ string help = "The output black level.", int connectable = 0, string page = "2 : Color Clamp", ]], color OutputMax = 1.0 [[ string help = "The output white level.", int connectable = 0, string page = "2 : Color Clamp", ]], float windowAspect = 1 [[ int connectable = 0, string page = "3 : Window Shape", float min = 0, float max = 10 ]], float roomDepth = 1 [[ float min = 0.1, float max = 100, int connectable = 0, string page = "3 : Window Shape", ]], float widthOverscan = 0 [[ float min = 0.0, float max = 0.9, int connectable = 0, string page = "3 : Window Shape", ]], float heightOverscan = 0 [[ float min = 0.0, float max = 0.9, int connectable = 0, string page = "3 : Window Shape", ]], int enableMidground = 0 [[ string widget = "checkBox", int connectable = 0, string page = "4 : Midground", ]], float midgroundDepth = 0.5 [[ float min = 0.1, float max = 100, int connectable = 0, string page = "4 : Midground" ]], float midgroundOffsetX = 0 [[ int connectable = 0, float min = -10.0, float max = 10.0, string page = "4 : Midground" ]], float midgroundOffsetY = 0 [[ int connectable = 0, float min = -10.0, float max = 10.0, string page = "4 : Midground" ]], int enableCurtains = 0 [[ string widget = "boolean", string page = "5 : Foreground", int connectable = 0, ]], int Clamp = 1 [[ string widget = "checkBox", string help = "Clamp the output to the 0-1 range for each component", string page = "6 : Extra", int connectable = 0, ]], int aces = 0 [[ string widget = "checkBox", string page = "6 : Extra", string label = "ACES", int connectable = 0 ]], output color outColor = 0.0){ // additional inits Mads Drøschler vector HSV = vector(Hue,Saturation,Value); //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*(1/windowAspect), heightOverscanMult, 1); //reorder to match UV for Y up axis } else { objI = vector(-objI[0],-objI[1],-objI[2]) * color(widthOverscanMult*(1/windowAspect), 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); midgroundUV[1] = (1-midgroundUV[1]) - 2.0/3.0; color curtainsUV = objPOrig * color(1.0/3.0, 1.0/3.0, 1); curtainsUV[0] = 1.0/3.0 - curtainsUV[0]; curtainsUV[1] = 2.0/3.0 + curtainsUV[1]; //VRay specific color finalUV = ceilUV + floorUV + rWallUV + lWallUV + backWallUV; //flipping ctrl if (textureFlop < 1){ //VRay specific 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.0/3.0 - midgroundUV[1]; // VRay specific curtainsUV[1] = 1 - curtainsUV[1] + 2.0/3.0; // VRay specific } color roomRGB = texture(input_tex, finalUV[0], finalUV[1], "width" , 0); color finalRGB; //midground switch if (enableMidground > 0){ float midgroundA; color midgroundRGB = texture(input_tex, midgroundUV[0], midgroundUV[1], "alpha", midgroundA, "width" , 0); finalRGB = mix(roomRGB,midgroundRGB,midgroundA * midgroundMask); //VRay specific } else{ finalRGB = roomRGB; } //curtains switch if (enableCurtains > 0){ float curtainsA; color curtainsRGB = texture(input_tex, curtainsUV[0], curtainsUV[1], "alpha", curtainsA, "width" , 0); finalRGB = mix(finalRGB,curtainsRGB,curtainsA); } // ACES sRGB Transform matrix aces_tm = matrix( 0.6131, 0.0701, 0.0206, 0, 0.3395, 0.9164, 0.1096, 0, 0.0474, 0.0135, 0.8698, 0, 0, 0, 0, 1); // Fetch the color grade function // Mads Drøschler finalRGB = Grader(finalRGB,InputMin,InputMax,HSV,OutputMax,OutputMin,MidTones,Clamp); color result = finalRGB; // Gamma & ACES { if (ManualGamma != 1.0) result = pow(finalRGB, ManualGamma); } float r = result[0], g = result[1], b = result[2]; // ACES Output if (aces == 0) outColor = result; else { outColor = transform(aces_tm, vector(r,g,b)); } }