/*

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

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."
##    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."
## 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_gi (
    string filename = "<project>/3delight/ptc/<scene>.#.ptc";
    string envmap = "";
    string coordsyst = "world";
    string envspace = "world";
    string GI_hitsides = "both";
    float composite = 0,
    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,
    reuse = 0,
    rebake = 0;
    string rebaked_file = "<project>/3delight/ptc/<scene>.#.rebake.ptc",
    rebaked_coordsyst = "world";
    output varying color GI_Cl = 1;
    output varying color aov_envcolor = 1;)
{
    normal shading_normal = normalize(Ns);
    float AO_Cl = 0;
    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,
            "occlusion", AO_Cl);
    } else {
        texture3d(rebaked_file, Ps, shading_normal,
            "indirectdiffuse", GI_Cl,
            "coordsystem", rebaked_coordsyst);
    }
    outputchannel("aov_GI", GI_Cl);
    outputchannel("aov_AO", AO_Cl);
    if(composite == 1) {
        Cl = GI_Cl * (1-AO_Cl);
    } else {
        Cl = Cl;
    }
    Ol = Ol;
    if(rebake == 1) {
        bake3d(rebaked_file, "", Ps,  shading_normal,
            "indirectdiffuse", GI_Cl,
            "coordsystem", rebaked_coordsyst,
            "interpolate", 1);
    }
}

