/*

Author:        Cameron Leger
Date:        11/28/2011
Version:    1.0
Title:        cl_ptc_light_sss

The rendered image will be the effect you've checked on top of the render.

Because this is a light shader, it obeys light linking. So, you can have many lights with this shader attached to different objects to get multiple effects in one run.

It is still used mainly the same way as my ptc_uber shader.

For space and efficiency's sake, you can bake PTC files for static objects separately than the animated objects and combine them at rendertime.
Bake them out however you want, but when you use them, include them as following:

path/to/file.ptc;path/to/file2.ptc

Without spaces between the paths and a ";" to separate PTCs

This shader also supports rebaking and reusing of PTC generated effects for speeding up renders when a look is finalized.

For more efficiency, you can also convert the 2nd PTC files to brickmaps and load those in the Rebaking section for Reusing.

NOTE:
The general concept and much of this code is based around:
http://www.cs.amherst.edu/~jer/cs32/RPS_15.0/pointbased.html

The follow links were very helpful towards compiling this shader:
http://www.3delight.com/en/modules/PunBB/viewtopic.php?id=1246&p=1
http://www.3delight.com/en/modules/PunBB/viewtopic.php?id=1847&p=1
*/


##    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/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."
##    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_sss (
    string filename = "<project>/3delight/ptc/<scene>.#.ptc";
    string envmap = "";
    string coordsyst = "world";
    string envspace = "world";
    float composite = 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;
    float reuse = 0,
    rebake = 0;
    string rebaked_file = "<project>/3delight/ptc/<scene>.#.rebake.ptc",
    rebaked_coordsyst = "world";
    output varying color SSS_Cl = 1;
    output varying color aov_envcolor = 1;)
{
    normal shading_normal = normalize(Ns);
    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);
    }
}

