/*

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

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

