Point Cloud Uber Light Shader

NOTE: This has since been moved to:
http://blog.cameronleger.com/code/ptc_uber_light_shader/

I’ve compiled the shader as a light shader now.

You can’t have multiple atmosphere shaders on top of the same object, so that was limiting. With both ways, you can render out multiple effects at one time. The difference being that with the atmosphere shader, you have one shader with many effects and a pass for each effect, and with the light shader you have lots of light shaders you can link to objects however you want. The key downside for the light shader is that using custom AOVs won’t work unless you hardcode those AOVs into the surface shader. So, for every surface shader in your scene, you have to add in the code to allow them to pass along the custom AOVs. Whereas with the atmosphere shader, you don’t have to.

So for now, in this light shader, custom AOVs and passes are disabled. You can make a render pass for each light and render them out separately, but you lose the ability to render them all at once and save time.

Here are the several key differences in this shader vs. the atmosphere version.

• There is no baking function for the light shader. You can either use my ptc_uber or your own shader to bake
• AOVs are disabled. I’ve taken all the AOV sections out, because in 9.0.1, which I’m using, I don’t have an easy way to make them work. Besides going in to each shader and adding the custom AOVs, if anyone has a better idea, please let me know. If you want to add them back in, compare this shader to my ptc_uber to see what all goes where.
• Gamma correction is gone, but each section has an intensity multiplier so you can control the effect.
• No AO section under GI. I haven’t tested using multiple options at the same time, but there’s no use for that because you can very easily add another light with another instance of this shader for the added effects. That is also the reason for taking out AO under GI. If you want both, use two lights, one for AO, one for GI. Simple enough.

UPDATE:10/19/2010
It now works correctly with 3Delight materials. Still having trouble with mia materials.
Added SSS to PTC usage section.

UPDATE:11/2/2010
Added AOV support for the newest 3Delight versions.
Fixed numerous bugs.

UPDATE:11/9/2010
Added directional occlusion, a tweak on occlusion that makes it kind of like a soft directional light
Fixed some hints on the Max Variation parameter
IBL may not have been working before
Samplebase isn’t a PTC option, oops

UPDATE:11/22/2010
Added the ability to rebake and reuse PTC data to save rendertime when multiple renders are needed

##    Main
#pragma annotation "grouping" "MAIN/composite;"
#pragma annotation composite "gadgettype=checkbox:0:1=custom value;label=Composite;hint=Add the effect on top of RGBA, otherwise just in the AOV;"
#pragma annotation "grouping" "MAIN/AO;"
#pragma annotation AO "gadgettype=checkbox:0:1=custom value;label=Ambient Occlusion;"
#pragma annotation "grouping" "MAIN/DO;"
#pragma annotation DO "gadgettype=checkbox:0:1=custom value;label=Directional Occlusion;"
#pragma annotation "grouping" "MAIN/RO;"
#pragma annotation RO "gadgettype=checkbox:0:1=custom value;label=Reflection Occlusion;"
#pragma annotation "grouping" "MAIN/GRefl;"
#pragma annotation GRefl "gadgettype=checkbox:0:1=custom value;label=Glossy Reflections;"
#pragma annotation "grouping" "MAIN/GRefr;"
#pragma annotation GRefr "gadgettype=checkbox:0:1=custom value;label=Glossy Refractions;"
#pragma annotation "grouping" "MAIN/IBL;"
#pragma annotation IBL "gadgettype=checkbox:0:1=custom value;label=Image Based Lighting;"
#pragma annotation "grouping" "MAIN/GI;"
#pragma annotation GI "gadgettype=checkbox:0:1=custom value;label=Color Bleeding (GI);"
#pragma annotation "grouping" "MAIN/SSS;"
#pragma annotation SSS "gadgettype=checkbox:0:1=custom value;label=Subsurface Scattering;"
#pragma annotation "grouping" "MAIN/filename;"
#pragma annotation "grouping" "MAIN/rebake;"
#pragma annotation rebake "gadgettype=checkbox:0:1=custom value;label=Rebake PTC Map;"
#pragma annotation "grouping" "MAIN/reuse;"
#pragma annotation reuse "gadgettype=checkbox:0:1=custom value;label=Reuse PTC Map;"
#pragma annotation filename "gadgettype=inputfile;label=PTC File;hint=A previously rendered .ptc file. A .ptc with color and direct lighting baked in is needed for GI and can be used by all, but only point values are needed for AO."
#pragma annotation "grouping" "MAIN/coordsyst;"
#pragma annotation coordsyst "gadgettype=inputfile;label=Coordinate System;hint=Default 'world'. The coordinate system used by the point cloud."
#pragma annotation "grouping" "MAIN/envmap;"
#pragma annotation envmap "gadgettype=inputfile;label=ENV File;hint=A .tdl environment map made from 3Delight's tdlmake. If this is loaded it, it will be used for whatever you have actived and gets used if a ray doesn't hit an object.."
#pragma annotation "grouping" "MAIN/envspace;"
#pragma annotation envspace "gadgettype=inputfile;label=Coordinate System;hint=Default 'world'. The coordinate system used by the environment map."
##    AO
#pragma annotation "grouping" "AO/AO_int;"
#pragma annotation AO_int "gadgettype=floadfield;label=Intensity;hint=Multiplied by the AO effect. Default is 1."
#pragma annotation "grouping" "AO/AO_hitsides;"
#pragma annotation AO_hitsides "gadgettype=optionmenu:front:back:both;label=Hitsides;hint=Which side of point sample is used."
#pragma annotation "grouping" "AO/AO_maxdist;"
#pragma annotation AO_maxdist "gadgettype=floatfield;label=Max Distance;hint=Only consider intersections inside this distance. Default 1e2. Change this based on the scale of your scene."
#pragma annotation "grouping" "AO/AO_falloff;"
#pragma annotation AO_falloff "gadgettype=floatfield;label=Falloff;hint=Shapes the curve of falloff. Set to 1 for linear falloff."
#pragma annotation "grouping" "AO/AO_falloffmode;"
#pragma annotation AO_falloffmode "gadgettype=floatslider;min=0;max=1;label=Falloff Mode;hint=0 is exponential. 1 is polynomial."
#pragma annotation "grouping" "AO/AO_coneangle;"
#pragma annotation AO_coneangle "gadgettype=floatslider;min=0;max=360;label=Cone Angle;hint=Solid angle considered per point. Default is a hemishpere (180 degrees)."
#pragma annotation "grouping" "AO/AO_bias;"
#pragma annotation AO_bias "gadgettype=floatfield;label=Bias;hint=Offsets points above surface to prevent self-occlusion on curved surfaces. Usually 0.0 - 0.01. Lower values will get rid of white lines in corners."
#pragma annotation "grouping" "AO/AO_clamp;"
#pragma annotation AO_clamp "gadgettype=checkbox:0:1=custom value;label=Clamping;hint=Reducing over-occlusion. Doubles render time but much better results."
#pragma annotation "grouping" "AO/AO_maxsolidangle;"
#pragma annotation AO_maxsolidangle "gadgettype=floatfield;label=Max Solid Angle;hint=Time vs Quality. Good values between 0.03 and 0.2 Higher values are faster."
#pragma annotation "grouping" "AO/AO_maxvariation;"
#pragma annotation AO_maxvariation "gadgettype=floatfield;label=Max Variation;hint=Interpolates low variations. Values around 30 are up to twice as fast to render but look almost the same."
##    DO
#pragma annotation "grouping" "DO/DO_int;"
#pragma annotation DO_int "gadgettype=floadfield;label=Intensity;hint=Multiplied by the DO effect. Default is 1."
#pragma annotation "grouping" "DO/DO_hitsides;"
#pragma annotation DO_hitsides "gadgettype=optionmenu:front:back:both;label=Hitsides;hint=Which side of point sample is used."
#pragma annotation "grouping" "DO/DO_dir;"
#pragma annotation DO_dir "label=Direction;hint=Direction of occlusion in world space, coming from the point at XYZ."
#pragma annotation "grouping" "DO/DO_maxdist;"
#pragma annotation DO_maxdist "gadgettype=floatfield;label=Max Distance;hint=Only consider intersections inside this distance. Default 1e2. Change this based on the scale of your scene."
#pragma annotation "grouping" "DO/DO_falloff;"
#pragma annotation DO_falloff "gadgettype=floatfield;label=Falloff;hint=Shapes the curve of falloff. Set to 1 for linear falloff."
#pragma annotation "grouping" "DO/DO_falloffmode;"
#pragma annotation DO_falloffmode "gadgettype=floatslider;min=0;max=1;label=Falloff Mode;hint=0 is exponential. 1 is polynomial."
#pragma annotation "grouping" "DO/DO_coneangle;"
#pragma annotation DO_coneangle "gadgettype=floatslider;min=0;max=360;label=Cone Angle;hint=Solid angle considered per point. Default is a hemishpere (180 degrees)."
#pragma annotation "grouping" "DO/DO_bias;"
#pragma annotation DO_bias "gadgettype=floatfield;label=Bias;hint=Offsets points above surface to prevent self-occlusion on curved surfaces. Usually 0.0 - 0.01. Lower values will get rid of white lines in corners."
#pragma annotation "grouping" "DO/DO_clamp;"
#pragma annotation DO_clamp "gadgettype=checkbox:0:1=custom value;label=Clamping;hint=Reducing over-occlusion. Doubles render time but much better results."
#pragma annotation "grouping" "DO/DO_maxsolidangle;"
#pragma annotation DO_maxsolidangle "gadgettype=floatfield;label=Max Solid Angle;hint=Time vs Quality. Good values between 0.03 and 0.2 Higher values are faster."
#pragma annotation "grouping" "DO/DO_maxvariation;"
#pragma annotation DO_maxvariation "gadgettype=floatfield;label=Max Variation;hint=Interpolates low variations. Values around 30 are up to twice as fast to render but look almost the same."
##    RO
#pragma annotation "grouping" "RO/RO_int;"
#pragma annotation RO_int "gadgettype=floadfield;label=Intensity;hint=Multiplied by the RO effect. Default is 1."
#pragma annotation "grouping" "RO/RO_hitsides;"
#pragma annotation RO_hitsides "gadgettype=optionmenu:front:back:both;label=Hitsides;hint=Which side of point sample is used."
#pragma annotation "grouping" "RO/RO_maxdist;"
#pragma annotation RO_maxdist "gadgettype=floatfield;label=Max Distance;hint=Only consider intersections inside this distance. Default 1e15. Change this based on the scale of your scene."
#pragma annotation "grouping" "RO/RO_falloff;"
#pragma annotation RO_falloff "gadgettype=floatfield;label=Falloff;hint=Shapes the curve of falloff. Set to 1 for linear falloff."
#pragma annotation "grouping" "RO/RO_falloffmode;"
#pragma annotation RO_falloffmode "gadgettype=floatslider;min=0;max=1;label=Falloff Mode;hint=0 is exponential. 1 is polynomial."
#pragma annotation "grouping" "RO/RO_coneangle;"
#pragma annotation RO_coneangle "gadgettype=floatfield;label=Cone Angle;hint=Value in radians of the cone angle. Smaller values are better for Reflection Occlusion. Default .2"
#pragma annotation "grouping" "RO/RO_bias;"
#pragma annotation RO_bias "gadgettype=floatfield;label=Bias;hint=Offsets points above surface to prevent self-occlusion on curved surfaces. Usually 0.0 - 0.01. Lower values will get rid of white lines in corners."
#pragma annotation "grouping" "RO/RO_clamp;"
#pragma annotation RO_clamp "gadgettype=checkbox:0:1=custom value;label=Clamping;hint=Reducing over-occlusion. Doubles render time but much better results."
#pragma annotation "grouping" "RO/RO_maxsolidangle;"
#pragma annotation RO_maxsolidangle "gadgettype=floatfield;label=Max Solid Angle;hint=Time vs Quality. Should use very low values for Reflection Occlusion. Default .005."
##    GRefl
#pragma annotation "grouping" "GRefl/GRefl_int;"
#pragma annotation GRefl_int "gadgettype=floadfield;label=Intensity;hint=Multiplied by the GRefl effect. Default is 1."
#pragma annotation "grouping" "GRefl/GRefl_hitsides;"
#pragma annotation GRefl_hitsides "gadgettype=optionmenu:front:back:both;label=Hitsides;hint=Which side of point sample is used."
#pragma annotation "grouping" "GRefl/GRefl_maxdist;"
#pragma annotation GRefl_maxdist "gadgettype=floatfield;label=Max Distance;hint=Only consider intersections inside this distance. Default 1e15. Change this based on the scale of your scene."
#pragma annotation "grouping" "GRefl/GRefl_falloff;"
#pragma annotation GRefl_falloff "gadgettype=floatfield;label=Falloff;hint=Shapes the curve of falloff. Set to 1 for linear falloff."
#pragma annotation "grouping" "GRefl/GRefl_falloffmode;"
#pragma annotation GRefl_falloffmode "gadgettype=floatslider;min=0;max=1;label=Falloff Mode;hint=0 is exponential. 1 is polynomial."
#pragma annotation "grouping" "GRefl/GRefl_coneangle;"
#pragma annotation GRefl_coneangle "gadgettype=floatfield;label=Cone Angle;hint=Value in radians of the cone angle. Smaller values are preferred. The larger the value the blurrier the reflections. Default 30"
#pragma annotation "grouping" "GRefl/GRefl_bias;"
#pragma annotation GRefl_bias "gadgettype=floatfield;label=Bias;hint=Offsets points above surface to prevent self-occlusion on curved surfaces. Usually 0.0 - 0.01. Lower values will get rid of white lines in corners."
#pragma annotation "grouping" "GRefl/GRefl_clamp;"
#pragma annotation GRefl_clamp "gadgettype=checkbox:0:1=custom value;label=Clamping;hint=Reducing over-occlusion. Doubles render time but much better results."
#pragma annotation "grouping" "GRefl/GRefl_sort;"
#pragma annotation GRefl_sort "gadgettype=checkbox:0:1=custom value;label=Sorting;hint=Clamping must be on for this to have an effect. The color bleed is sorted by distance and gives more correct colors and shadows."
#pragma annotation "grouping" "GRefl/GRefl_maxsolidangle;"
#pragma annotation GRefl_maxsolidangle "gadgettype=floatfield;label=Max Solid Angle;hint=Time vs Quality. Should use very low values. Default .005."
##    GRefr
#pragma annotation "grouping" "GRefr/GRefr_readme;"
#pragma annotation GRefr_readme "gadgettype=floatfield;label=README;hint=For this to work properly, THE OBJECT WITH THIS EFFECT ON IT SHOULD NOT BE IN THE POINT CLOUD."
#pragma annotation "grouping" "GRefr/GRefr_int;"
#pragma annotation GRefr_int "gadgettype=floatfield;label=Intensity;hint=Intensity of the effect;"
#pragma annotation "grouping" "GRefr/GRefr_ior;"
#pragma annotation GRefr_ior "gadgettype=floatfield;label=IOR;hint=Index of Refraction;"
#pragma annotation "grouping" "GRefr/GRefr_hitsides;"
#pragma annotation GRefr_hitsides "gadgettype=optionmenu:front:back:both;label=Hitsides;hint=Which side of point sample is used."
#pragma annotation "grouping" "GRefr/GRefr_maxdist;"
#pragma annotation GRefr_maxdist "gadgettype=floatfield;label=Max Distance;hint=Only consider intersections inside this distance. Default 1e15. Change this based on the scale of your scene."
#pragma annotation "grouping" "GRefr/GRefr_falloff;"
#pragma annotation GRefr_falloff "gadgettype=floatfield;label=Falloff;hint=Shapes the curve of falloff. Set to 1 for linear falloff."
#pragma annotation "grouping" "GRefr/GRefr_falloffmode;"
#pragma annotation GRefr_falloffmode "gadgettype=floatslider;min=0;max=1;label=Falloff Mode;hint=0 is exponential. 1 is polynomial."
#pragma annotation "grouping" "GRefr/GRefr_coneangle;"
#pragma annotation GRefr_coneangle "gadgettype=floatfield;label=Cone Angle;hint=Value in radians of the cone angle. Smaller values are preferred. The larger the value the blurrier the refractions. Default 30"
#pragma annotation "grouping" "GRefr/GRefr_bias;"
#pragma annotation GRefr_bias "gadgettype=floatfield;label=Bias;hint=Offsets points above surface to prevent self-occlusion on curved surfaces. Usually 0.0 - 0.01. Lower values will get rid of white lines in corners."
#pragma annotation "grouping" "GRefr/GRefr_clamp;"
#pragma annotation GRefr_clamp "gadgettype=checkbox:0:1=custom value;label=Clamping;hint=Reducing over-occlusion. Doubles render time but much better results."
#pragma annotation "grouping" "GRefr/GRefr_sort;"
#pragma annotation GRefr_sort "gadgettype=checkbox:0:1=custom value;label=Sorting;hint=Clamping must be on for this to have an effect. The color bleed is sorted by distance and gives more correct colors and shadows."
#pragma annotation "grouping" "GRefr/GRefr_maxsolidangle;"
#pragma annotation GRefr_maxsolidangle "gadgettype=floatfield;label=Max Solid Angle;hint=Time vs Quality. Should use very low values. Default .005."
##    IBL
#pragma annotation "grouping" "IBL/IBL_int;"
#pragma annotation IBL_int "gadgettype=floadfield;label=Intensity;hint=Multiplied by the IBL effect. Default is 1."
#pragma annotation "grouping" "IBL/IBL_hitsides;"
#pragma annotation IBL_hitsides "gadgettype=optionmenu:front:back:both;label=Hitsides;hint=Which side of point sample is used."
#pragma annotation "grouping" "IBL/IBL_maxdist;"
#pragma annotation IBL_maxdist "gadgettype=floatfield;label=Max Distance;hint=Only consider intersections inside this distance. Default 1e15. Change this based on the scale of your scene."
#pragma annotation "grouping" "IBL/IBL_falloff;"
#pragma annotation IBL_falloff "gadgettype=floatfield;label=Falloff;hint=Shapes the curve of falloff. Set to 1 for linear falloff."
#pragma annotation "grouping" "IBL/IBL_falloffmode;"
#pragma annotation IBL_falloffmode "gadgettype=floatslider;min=0;max=1;label=Falloff Mode;hint=0 is exponential. 1 is polynomial."
#pragma annotation "grouping" "IBL/IBL_coneangle;"
#pragma annotation IBL_coneangle "gadgettype=floatslider;min=0;max=360;label=Cone Angle;hint=Solid angle considered per point. Default is a hemishpere (180 degrees)."
#pragma annotation "grouping" "IBL/IBL_bias;"
#pragma annotation IBL_bias "gadgettype=floatfield;label=Bias;hint=Offsets points above surface. Usually 0.0 - 0.01. Go as low as you can go without artifacts."
#pragma annotation "grouping" "IBL/IBL_clamp;"
#pragma annotation IBL_clamp "gadgettype=checkbox:0:1=custom value;label=Clamping;hint=Doubles render time but much better results."
#pragma annotation "grouping" "IBL/IBL_maxsolidangle;"
#pragma annotation IBL_maxsolidangle "gadgettype=floatfield;label=Max Solid Angle;hint=Time vs Quality. Good values between 0.03 and 0.1 Higher values are faster."
#pragma annotation "grouping" "IBL/IBL_maxvariation;"
#pragma annotation IBL_maxvariation "gadgettype=floatfield;label=Max Variation;hint=Interpolates low variations. Values around 30 are up to twice as fast to render but look almost the same."
##    GI
#pragma annotation "grouping" "GI/GI_int;"
#pragma annotation GI_int "gadgettype=floatfield;label=Intensity;hint=Multiplied by the GI result. Default is 1."
#pragma annotation "grouping" "GI/GI_hitsides;"
#pragma annotation GI_hitsides "gadgettype=optionmenu:front:back:both;label=Hitsides;hint=Which side of point sample is used."
#pragma annotation "grouping" "GI/GI_maxdist;"
#pragma annotation GI_maxdist "gadgettype=floatfield;label=Max Distance;hint=Only consider intersections inside this distance. Default 1e15. Change this based on the scale of your scene."
#pragma annotation "grouping" "GI/GI_falloff;"
#pragma annotation GI_falloff "gadgettype=floatfield;label=Falloff;hint=Shapes the curve of falloff. Set to 1 for linear falloff."
#pragma annotation "grouping" "GI/GI_falloffmode;"
#pragma annotation GI_falloffmode "gadgettype=floatslider;min=0;max=1;label=Falloff Mode;hint=0 is exponential. 1 is polynomial."
#pragma annotation "grouping" "GI/GI_coneangle;"
#pragma annotation GI_coneangle "gadgettype=floatslider;min=0;max=360;label=Cone Angle;hint=Solid angle considered per point. Default is a hemishpere (180 degrees)."
#pragma annotation "grouping" "GI/GI_bias;"
#pragma annotation GI_bias "gadgettype=floatfield;label=Bias;hint=Offsets points above surface. Usually 0.0 - 0.01. Go as low as you can go without artifacts."
#pragma annotation "grouping" "GI/GI_clamp;"
#pragma annotation GI_clamp "gadgettype=checkbox:0:1=custom value;label=Clamping;hint=Doubles render time but much better results."
#pragma annotation "grouping" "GI/GI_sort;"
#pragma annotation GI_sort "gadgettype=checkbox:0:1=custom value;label=Sorting;hint=Clamping must be on for this to have an effect. The color bleed is sorted by distance and gives more correct colors and shadows."
#pragma annotation "grouping" "GI/GI_maxsolidangle;"
#pragma annotation GI_maxsolidangle "gadgettype=floatfield;label=Max Solid Angle;hint=Time vs Quality. Good values between 30 and 0.1 Higher values are faster."
##    SSS
#pragma annotation "grouping" "SSS/SSS_ior;"
#pragma annotation SSS_ior "gadgettype=floatfield;label=IOR;hint=Index of Refraction. Looks-wise, lower values are more contrasty and higher values produce a more even look with more scattering."
#pragma annotation "grouping" "SSS/SSS_scale;"
#pragma annotation SSS_scale "gadgettype=floatfield;label=Scale;hint=The scale the SSS is computed at, default 1 at millimeters. Higher values produce more scattering and make it look waxier."


#pragma annotation "grouping" "SSS/SSS_type;"
#pragma annotation SSS_type "gadgettype=optionmenu:apple:chicken1:chicken2:cream:ketchup:marble:potato:skimmilk:skin1:skin2:spectralon:wholemilk:custom;label=Preset;hint=Presets. If you choose custom, you can input values in the CUSTOM section. Default CUSTOM values are for skin2"
#pragma annotation "grouping" "SSS/CUSTOM/SSS_abs;"
#pragma annotation SSS_abs "gadgettype=colorslider;label=Absorption;hint=Absorption Coefficient."
#pragma annotation "grouping" "SSS/CUSTOM/SSS_sct;"
#pragma annotation SSS_sct "gadgettype=colorslider;label=Scattering;hint=Scattering Coefficient."
#pragma annotation "grouping" "SSS/SSS_smooth;"
#pragma annotation SSS_smooth "gadgettype=floatfield;label=Smoothing;hint=How much to smooth, from 0 being not and 1 being fully smoothed."
#pragma annotation "grouping" "SSS/SSS_weight;"
#pragma annotation SSS_weight "gadgettype=floatfield;label=Diffuse Weight;hint=How much of the diffuse is considered. 1 is purely diffuse, 0 is purely SSS"
## REBAKING
#pragma annotation "grouping" "REUSING/rebaked_file;"
#pragma annotation rebaked_file "gadgettype=inputfile;label=PTC Filename;hint=Where the .ptc file gets baked to."
#pragma annotation "grouping" "REUSING/rebaked_coordsyst;"
#pragma annotation rebaked_coordsyst "gadgettype=inputfile;label=Coordinate system;hint=Which coordsystem to bake to. Default world."

light
    cl_ptc_light_uber (
                string filename = "<project>/3delight/ptc/<scene>.#.ptc";
                string envmap = "";
                string coordsyst = "world";
                string envspace = "world";
                string AO_hitsides = "both";
                float composite = 0,
                AO_maxdist = 1e2,
                AO_int = .5,
                AO_coneangle = 180, 
                AO_falloff = 1, 
                AO_falloffmode = 1,
                AO_bias = 0.01,
                AO_clamp = 1, 
                AO_maxsolidangle = 0.05,
                AO_maxvariation = 0,
                AO = 0;
                string DO_hitsides = "both";
                float DO_maxdist = 1e2,
                DO_int = .5,
                DO_coneangle = 180, 
                DO_falloff = 1, 
                DO_falloffmode = 1,
                DO_bias = 0.01,
                DO_clamp = 1, 
                DO_maxsolidangle = 0.05,
                DO_maxvariation = 0,
                DO = 0;
                normal DO_dir = normal "world" (0,1,-2);
                string RO_hitsides = "both";
                float RO_maxdist = 1e15, 
                RO_int = 1,
                RO_falloff = 1, 
                RO_falloffmode = 1,
                RO_bias = 0.01,
                RO_clamp = 1, 
                RO_maxsolidangle = 0.05,
                RO_coneangle = 30,
                RO = 0;
                string GRefl_hitsides = "both";
                float GRefl_maxdist = 1e15,
                GRefl_int = 1, 
                GRefl_falloff = 1, 
                GRefl_falloffmode = 1,
                GRefl_bias = 0.01,
                GRefl_clamp = 1,
                GRefl_sort = 1, 
                GRefl_maxsolidangle = 0.05,
                GRefl_coneangle = 30,
                GRefl = 0;
                string GRefr_hitsides = "both";
                float GRefr_maxdist = 1e15,
                GRefr_readme = 0,
                GRefr_int = .3,
                GRefr_ior = 1.1,
                GRefr_falloff = 1, 
                GRefr_falloffmode = 1,
                GRefr_bias = 0.01,
                GRefr_clamp = 1,
                GRefr_sort = 1, 
                GRefr_maxsolidangle = 0.05,
                GRefr_coneangle = 0.1,
                GRefr = 0;
                string IBL_hitsides = "both";
                float IBL_maxdist = 1e15,
                IBL_int = 1, 
                IBL_coneangle = 180,
                IBL_falloff = 1, 
                IBL_falloffmode = 1,
                IBL_bias = 0.01,
                IBL_clamp = 1,
                IBL_maxsolidangle = 0.05, 
                IBL_maxvariation = 0,
                IBL = 0;
                string GI_hitsides = "both";
                float GI_maxdist = 1e15,
                GI_falloff = 1,
                GI_falloffmode = 1,
                GI_bias = 0.045,
                GI_clamp = 1,
                GI_sort = 1,
                GI_coneangle = 180,
                GI_maxsolidangle = .2,
                GI_int = 1,
                GI = 0;
                string SSS_type = "skin1";
                color SSS_sct = color(1.09, 1.59, 1.79), 
		SSS_abs = color(0.013, 0.070, 0.145);
                float SSS_ior = 1.3,
                SSS_scale = 1,
                SSS_smooth = 0,
                SSS_weight = .4,
		SSS = 0;
		float reuse = 0,
		rebake = 0;
		string rebaked_file = "<project>/3delight/ptc/<scene>.#.rebake.ptc",
                rebaked_coordsyst = "world";
                output varying color GI_Cl = 0;
                output varying color GRefl_Cl = 0;
                output varying color GRefr_Cl = 0;
                output varying color RO_Cl = 0;
                output varying color IBL_Cl = 0;
                output varying color AO_Cl = 1;
                output varying color DO_Cl = 1;
                output varying color SSS_Cl = 1;
                output varying color aov_envcolor = 1) 
    {
    normal shading_normal = normalize(Ns);
      
      if(AO == 1) {
		if (reuse != 1) {
        AO_Cl = AO_int*(1-occlusion( // performs occlusion with parameters from GUI, inverse AO and multiply by our intensity
                Ps, shading_normal, 0,
                "pointbased", 1,
                "filename", filename,
                "coordsystem", coordsyst,
                "coneangle", radians(AO_coneangle),
                "hitsides", AO_hitsides,
                "maxdist", AO_maxdist,
                "falloff", AO_falloff,
                "falloffmode", AO_falloffmode,
                "bias", AO_bias,
                "clamp", AO_clamp,
                "maxsolidangle", AO_maxsolidangle,
                "maxvariation", AO_maxvariation));
                
		} else {
		texture3d(rebaked_file, Ps, shading_normal,
		"occlusion", AO_Cl,
		"coordsystem", rebaked_coordsyst);
		}
		outputchannel("aov_AO", AO_Cl);
        if(composite == 1) {
            Cl = AO_Cl;
        } else {
			Cl = Cl;
		}
        Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps, shading_normal, 
			"occlusion", AO_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}
      }
    
    if(DO == 1) {
		if (reuse != 1) {
        DO_Cl = DO_int*(1-occlusion( // performs occlusion with parameters from GUI, inverse AO and multiply by our intensity
                Ps, DO_dir, 0,
                "pointbased", 1,
                "filename", filename,
                "coordsystem", coordsyst,
                "coneangle", radians(DO_coneangle),
                "hitsides", DO_hitsides,
                "maxdist", DO_maxdist,
                "falloff", DO_falloff,
                "falloffmode", DO_falloffmode,
                "bias", DO_bias,
                "clamp", DO_clamp,
                "maxsolidangle", DO_maxsolidangle,
                "maxvariation", DO_maxvariation));
                
		} else {
		texture3d(rebaked_file, Ps, DO_dir,
		"occlusion", DO_Cl,
		"coordsystem", rebaked_coordsyst);
		}
		outputchannel("aov_DO", DO_Cl);
        if(composite == 1) {
            Cl = DO_Cl;
        } else {
			Cl = Cl;
		};
        Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps, DO_dir, 
			"occlusion", DO_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}
      }
      
      if(RO == 1) {
           vector RO_refl = reflect(I, shading_normal); // Uses the reflected vector to compute occlusion, thus reflection occlusion
       if (reuse != 1) {
		RO_Cl = RO_int*(1-occlusion(Ps, RO_refl, 0,  
                "pointbased", 1, 
                "filename", filename,
                "coordsystem", coordsyst,
                "hitsides", RO_hitsides,
                   "clamp", RO_clamp,
                "maxdist", RO_maxdist, 
                "falloff", RO_falloff,
                "falloffmode", RO_falloffmode,
                "coneangle", radians(RO_coneangle),
                "maxsolidangle", RO_maxsolidangle,
                "bias", RO_bias));
            
		} else {
		texture3d(rebaked_file, Ps, RO_refl,
		"occlusion", RO_Cl,
		"coordsystem", rebaked_coordsyst);
		}
		outputchannel("aov_RO", RO_Cl);
        if(composite == 1) {
            Cl = RO_Cl;
        } else {
			Cl = Cl;
		}
        Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps, RO_refl, 
			"occlusion", RO_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}
      }
    
      if(GRefl == 1) {
          vector GRefl_refl = reflect(I, shading_normal); // Again, using a reflection vector for computation 
		if (reuse != 1) {
        GRefl_Cl = GRefl_int*indirectdiffuse(Ps, GRefl_refl, 0, 
                "pointbased", 1, 
                "filename", filename,
                "coordsystem", coordsyst,
                "hitsides", GRefl_hitsides, 
                "clamp", GRefl_clamp,
                "sortbleeding", GRefl_sort,
                "maxdist", GRefl_maxdist, 
                "falloff", GRefl_falloff,
                "falloffmode", GRefl_falloffmode,
                "coneangle", radians(GRefl_coneangle),
                "bias", GRefl_bias,
                "maxsolidangle", GRefl_maxsolidangle);

		} else {
		texture3d(rebaked_file, Ps, GRefl_refl,
		"reflection", GRefl_Cl,
		"coordsystem", rebaked_coordsyst);
		}
        outputchannel("aov_GRefl", GRefl_Cl);
         if(composite == 1) {
            Cl = GRefl_Cl;
        } else {
			Cl = Cl;
		}
          Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps, GRefl_refl, 
			"reflection", GRefl_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}
      }
    
      if(GRefr == 1) {
		if (reuse != 1) {
        extern point Ps;
        extern normal N;
        extern vector I;
        // normalizing
        vector IN = normalize(I);
        // stores reflection and refraction vectors
        vector reflDir, refrDir;
        float eta = (IN.shading_normal < 0) ? 1/GRefr_ior : GRefr_ior;
        float kr, kt;
        // computes fresnel effect
        fresnel(IN, shading_normal, eta, kr, kt, reflDir, refrDir);
        kt = 1 - kr; 
        
        vector RF = normalize(refrDir);
        GRefr_Cl = kt*GRefr_int*indirectdiffuse(Ps, RF, 0, //glossy refractions
                "filename", filename, 
                "pointbased", 1,
                "hitsides", GRefr_hitsides, 
                "coneangle", radians(GRefr_coneangle),
                   "clamp", GRefr_clamp,
                 "coordsystem", coordsyst,
                  "sortbleeding", GRefr_sort,
                 "maxdist", GRefr_maxdist, 
                "falloff", GRefr_falloff,
                  "falloffmode", GRefr_falloffmode,
                "bias", GRefr_bias,
                   "maxsolidangle", GRefr_maxsolidangle);

		} else {
		texture3d(rebaked_file, Ps,  shading_normal,
		"refraction", GRefr_Cl,
		"coordsystem", rebaked_coordsyst);
		}
		outputchannel("aov_GRefr", GRefr_Cl);
        if(composite == 1) {
            Cl = GRefr_Cl;
        } else {
			Cl = Cl;
		}
        Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps, shading_normal, 
			"refraction", GRefr_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}
      }
      
      if(IBL == 1) {
		if (reuse != 1) {
        color IBL_envcol = 0;
        vector IBL_envdir = 0;
        IBL_Cl = IBL_int*occlusion( // performs occlusion from HDRI with parameters from GUI 
                Ps, shading_normal, 0, 
                "pointbased", 1, 
                "filename", filename,
                "coordsystem", coordsyst,
                "hitsides", IBL_hitsides,
                "maxdist", IBL_maxdist, 
                "coneangle", radians(IBL_coneangle),
                "falloff", IBL_falloff,
                "falloffmode", IBL_falloffmode,
                "bias", IBL_bias,
                "clamp", IBL_clamp,
                "maxsolidangle", IBL_maxsolidangle,
                "maxvariation", IBL_maxvariation,
                "environmentmap", envmap,
                "environmentcolor", IBL_envcol,
                "environmentdir", IBL_envdir,
                "environmentcolor", aov_envcolor);

		} else {
		texture3d(rebaked_file, Ps, shading_normal,
		"ibl", IBL_Cl,
		"coordsystem", rebaked_coordsyst);
		}
		outputchannel("aov_IBL", IBL_Cl);
        if(composite == 1) {
            Cl = IBL_Cl;
        } else {
			Cl = Cl;
		}
        Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps,  shading_normal, 
			"ibl", IBL_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}
      }
      
      if(GI == 1) {
		if (reuse != 1) {
        GI_Cl = GI_int*indirectdiffuse(Ps,  // performs color bleeding with parameters from GUI
                shading_normal, 0, 
                "pointbased", 1, 
                "filename", filename,
                "hitsides", GI_hitsides, 
                "coneangle", radians(GI_coneangle),
                "clamp", GI_clamp,
                "coordsystem", coordsyst,
                "sortbleeding", GI_sort,
                "maxdist", GI_maxdist, 
                "falloff", GI_falloff,
                "falloffmode", GI_falloffmode,
                "bias", GI_bias,
                "maxsolidangle", GI_maxsolidangle,
                "environmentmap", envmap,
                "environmentspace", envspace);
                
		} else {
		texture3d(rebaked_file, Ps, shading_normal,
		"indirectdiffuse", GI_Cl,
		"coordsystem", rebaked_coordsyst);
		}
        outputchannel("aov_GI", GI_Cl);
        if(composite == 1) {
            Cl = GI_Cl;
        } else {
			Cl = Cl;
		}
		
		
		Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps,  shading_normal, 
			"indirectdiffuse", GI_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}

        }
        
        if(SSS == 1) {
color SSS_scatter, SSS_absorption;
if (SSS_type == "custom") {
	SSS_scatter = SSS_sct;
	SSS_absorption = SSS_abs;
} else if (SSS_type == "apple") {
	SSS_scatter = color(2.29, 2.39, 1.97);
	SSS_absorption = color(0.003, 0.0034, 0.046);
} else if (SSS_type == "chicken1") {
	SSS_scatter = color(0.15, 0.21, 0.38);
	SSS_absorption = color(0.015, 0.077, 0.19);
} else if (SSS_type == "chicken2") {
	SSS_scatter = color(0.19, 0.25, 0.32);
	SSS_absorption = color(0.018, 0.088, 0.20);
} else if (SSS_type == "cream") {
	SSS_scatter = color(7.38, 5.47, 3.15);
	SSS_absorption = color(0.0002, 0.0028, 0.0163);
} else if (SSS_type == "ketchup") {
	SSS_scatter = color(0.18, 0.07, 0.03);
	SSS_absorption = color(0.061, 0.97, 1.45);
} else if (SSS_type == "marble") {
	SSS_scatter = color(2.19, 2.62, 3.00);
	SSS_absorption = color(0.0021, 0.0041, 0.0071);
} else if (SSS_type == "potato") {
	SSS_scatter = color(0.68, 0.70, 0.55);
	SSS_absorption = color(0.0024, 0.009, 0.12);
} else if (SSS_type == "skimmilk") {
	SSS_scatter = color(0.70, 1.22, 1.9);
	SSS_absorption = color(0.0014, 0.0025, 0.0142);
} else if (SSS_type == "skin1") {
	SSS_scatter = color(0.74, 0.88, 1.01);
	SSS_absorption = color(0.032, 0.17, 0.48);
} else if (SSS_type == "skin2") {
	SSS_scatter = color(1.09, 1.59, 1.79);
	SSS_absorption = color(0.013, 0.07, 0.145);
} else if (SSS_type == "spectralon") {
	SSS_scatter = color(11.6, 20.4, 14.9);
	SSS_absorption = color(0, 0, 0);
} else if (SSS_type == "wholemilk") {
	SSS_scatter = color(2.55, 3.21, 3.77);
	SSS_absorption = color(0.0011, 0.0024, 0.014);
}
		if (reuse != 1) {
        float SSS_mult = SSS_weight;
        SSS_mult = (SSS_mult - 1)*(-1); // SSS_weight should be 0 for SSS and 1 for diffuse.
	SSS_Cl = subsurface( // performs subsurface with ptc 
                Ps, shading_normal,
                "coordsystem", coordsyst,
                "filename", filename,
                "scale", SSS_scale,
                "smooth", SSS_smooth,
		"scattering", SSS_scatter,
		"absorption", SSS_absorption,
                "ior", SSS_ior) * SSS_mult; // Multiply by the SSS_mult to control SSS intensity

		} else {
		texture3d(rebaked_file, Ps, shading_normal,
		"subsurface", SSS_Cl,
		"coordsystem", rebaked_coordsyst);
		}
        outputchannel("aov_SSS", SSS_Cl);
        if(composite == 1) {
            Cl = SSS_Cl;
        } else {
			Cl = Cl;
		}
        Ol = Ol;
		if(rebake == 1) {
			bake3d(rebaked_file, "", Ps,  shading_normal, 
			"subsurface", SSS_Cl,
			"coordsystem", rebaked_coordsyst,
			"interpolate", 1);
		}
      }
        
    }