// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage

#include "../common/shaders/pretty.h"


shader
test ()
{
    {
        float x = 3;
        float y = 4;
        float z = 5;
        printf ("   hypot (%g, %g) = %g\n", pretty(x), pretty(y), pretty(hypot(x,y)));
        printf ("   hypot (%g, %g, %g) = %g\n", pretty(x), pretty(y), pretty(z), pretty(hypot(x,y,z)));
        vector vI = vector(1,-2,0);
        vI = normalize(vI);
        vector vN = vector(0, 1, 0);
        printf ("   reflect (%g, %g) =  %g\n", pretty(vI), pretty(vN), pretty(reflect (vI, vN)));
        vN = vector(-1, 0, 0);
        printf ("   reflect (%g, %g) =  %g\n", pretty(vI), pretty(vN), pretty(reflect (vI, vN)));
        vI = vector(0, -1, -1);
        vI = normalize(vI);
        vN = vector(0, 0, 1);
        printf ("   faceforward (%g, %g) =  %g\n",
                pretty(vN), pretty(vI), pretty(faceforward (vN, vI)));
        vector vNg = vector(0, 0, -1);
        printf ("   faceforward (%g, %g, %g) =  %g\n",
                pretty(vN), pretty(vI), pretty(vNg), pretty(faceforward (vN, vI, vNg)));
 
        // test total internal reflection (going from greater to lesser IOR)
        printf (" testing total-internal reflection:\n");
        float n1 = 1.42;
        float n2 = 1.0;
        float eta = n1/n2; // critical angle < 45 degrees
        vI = vector(1,-1,0);
        vI = normalize(vI);
        vN = vector(0,1,0);
        printf ("   refract (%g, %g, %g) =  %g\n",
                pretty(vI), pretty(vN), pretty(eta), pretty(refract (vI, vN, eta)));
        float Kr, Kt;
        vector fR, fT;
        fresnel(vI, vN, eta, Kr, Kt, fR, fT);
        printf ("   frensel:  Kr= %g  Kt = %g  R = %g  T = %g\n", pretty(Kr), pretty(Kt),
                pretty(fR), pretty(fT)); 
       
        // test regular refraction
        printf (" testing regular refraction:\n");
        n1 = 1.0;
        n2 = 1.16;
        eta = n1/n2;
        vN = vector(1,2,3);
        vN = normalize(vN);
        vI = vector(-2,-1,-4);
        vI = normalize(vI);
        vector rR = refract(vI, vN, eta);
        printf ("   refract (%g, %g, %g) =  %g\n", pretty(vI), pretty(vN), pretty(eta), pretty(rR));
        float cos_incid_angle = dot(vI,vN);
        float cos_refr_angle  = dot(rR, -vN);
        float sin1 = sqrt(1.0 - cos_incid_angle*cos_incid_angle);
        float sin2 = sqrt(1.0 - cos_refr_angle*cos_refr_angle);
        //  n1/n2 = sin(theta2)/sin(theta1);
        printf("   --> verify refract():  %g/%g = sin(%g)/sin(%g) => %g ?= %g\n",
              pretty(n1), pretty(n2), pretty(degrees(asin(sin2))), pretty(degrees(asin(sin1))),
              pretty(n1/n2), pretty(sin2/sin1));
        fresnel(vI, vN, eta, Kr, Kt, fR, fT);
        printf ("   fresnel:  Kr= %g  Kt = %g  R = %g  T = %g\n", pretty(Kr), pretty(Kt),
                pretty(fR), pretty(fT)); 
        cos_incid_angle = dot(vI,vN);
        cos_refr_angle  = dot(fT, -vN);
        sin1 = sqrt(1.0 - cos_incid_angle*cos_incid_angle);
        sin2 = sqrt(1.0 - cos_refr_angle*cos_refr_angle);
        //  n1/n2 = sin(theta2)/sin(theta1);
        printf("   --> verify fresnel():  %g/%g = sin(%g)/sin(%g) => %g ?= %g\n",
              pretty(n1), pretty(n2), pretty(degrees(asin(sin2))), pretty(degrees(asin(sin1))), pretty(n1/n2), pretty(sin2/sin1));
    }

    { 
    }

    printf (" Varying:\n");
    {
        float x = u;
        float y = v;
        float z = u+v;

        printf ("   hypot (%g, %g) = %g\n", pretty(x), pretty(y), pretty(hypot(x,y)));
        printf ("   hypot (%g, %g, %g) = %g\n", pretty(x), pretty(y), pretty(z), pretty(hypot(x,y,z)));
        vector vI = vector(u,-2,0);
        vI = normalize(vI);
        vector vN = vector(v, 1, 0);
        vN = normalize(vN);
        printf ("   reflect (%g, %g) =  %g\n", pretty(vI), pretty(vN), pretty(reflect (vI, vN)));

        float n1 = 1.0;
        float n2 = 1.33;
        float eta = n1/n2;
        vI = vector(u+0.5, v-0.5, -1.0);
        vN = vector(0,0,1);
        vI = normalize(vI);
        vector rR = refract(vI, vN, eta);
        printf ("   refract (%g, %g, %g) =  %g\n", pretty(vI), pretty(vN), pretty(eta), pretty(rR));
        float cos_incid_angle = dot(vI,vN);
        float cos_refr_angle  = dot(rR, -vN);
        float sin1 = sqrt(1.0 - cos_incid_angle*cos_incid_angle);
        float sin2 = sqrt(1.0 - cos_refr_angle*cos_refr_angle);
        //  n1/n2 = sin(theta2)/sin(theta1);
        printf("   --> verify refract():  %g/%g = sin(%g)/sin(%g) => %g ?= %g\n",
              pretty(n1), pretty(n2), pretty(degrees(asin(sin2))), pretty(degrees(asin(sin1))),
              pretty(n1/n2), pretty(sin2/sin1));
        float Kr, Kt;
        vector fR, fT;
        fresnel(vI, vN, eta, Kr, Kt, fR, fT);
        printf ("   fresnel() -> Kr= %g  Kt = %g  R = %g  T = %g\n", pretty(Kr), pretty(Kt),
                pretty(pretty(fR)), pretty(pretty(fT))); 
        cos_incid_angle = dot(vI,vN);
        cos_refr_angle  = dot(fT, -vN);
        sin1 = sqrt(1.0 - cos_incid_angle*cos_incid_angle);
        sin2 = sqrt(1.0 - cos_refr_angle*cos_refr_angle);
        //  n1/n2 = sin(theta2)/sin(theta1);
        printf("   --> verify fresnel():  %g/%g = sin(%g)/sin(%g) => %g ?= %g\n",
              pretty(n1), pretty(n2), pretty(degrees(asin(sin2))), pretty(degrees(asin(sin1))),
              pretty(n1/n2), pretty(sin2/sin1));

    }
    {
    }
}
