// Copyright 2009 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "Dielectric.ih"

OSPRAY_BEGIN_ISPC_NAMESPACE

// Thin dielectric BSDF.
// It represents a transparent slab with unit thickness, and ignores refraction.
struct ThinDielectric
{
  BSDF super;

  float eta;
  vec3f attenuation;
};

inline BSDF_EvalRes ThinDielectric_eval(
    const varying BSDF *uniform, const vec3f &, const vec3f &)
{
  return make_BSDF_EvalRes_zero();
}

inline BSDF_SampleRes ThinDielectric_sample(
    const varying BSDF *uniform super, const vec3f &wo, const vec2f &, float ss)
{
  const varying ThinDielectric *uniform self =
      (const varying ThinDielectric *uniform)super;
  BSDF_SampleRes res;

  float cosThetaO = max(dot(wo, getN(super)), 0.f);

  // Fresnel term
  float cosThetaT; // positive
  float F = fresnelDielectricEx(cosThetaO, cosThetaT, self->eta);
  res.pdf = inf;

  // Sample the reflection or the transmission
  bool doReflection = (ss <= F);
  if (doReflection) {
    // Reflection
    res.wi = reflect(wo, getN(super), cosThetaO);
    res.type = BSDF_SPECULAR_REFLECTION;
    res.weight = make_vec3f(1.f);
  } else {
    // Transmission
    // Attenuation for crossing the slab once
    float length = rcp(cosThetaT);
    vec3f A = expf(self->attenuation * length);

    res.wi = neg(wo);
    res.type = BSDF_SPECULAR_TRANSMISSION;
    res.weight = A;
  }

  return res;
}

inline void ThinDielectric_Constructor(varying ThinDielectric *uniform self,
    const varying linear3f *uniform frame,
    float eta,
    vec3f attenuation)
{
  BSDF_Constructor(&self->super,
      expf(attenuation),
      BSDF_SPECULAR,
      BSDF_TYPE_THIN_DIELECTRIC,
      frame);
  self->eta = eta;
  self->attenuation = attenuation;
}

inline varying BSDF *uniform ThinDielectric_create(
    uniform ShadingContext *uniform ctx,
    const varying linear3f *uniform frame,
    float eta,
    vec3f attenuation)
{
  varying ThinDielectric *uniform self = (varying ThinDielectric * uniform)
      ShadingContext_alloc(ctx, sizeof(ThinDielectric));
  ThinDielectric_Constructor(self, frame, eta, attenuation);
  return &self->super;
}

// Helper function for transparent shadow rays
inline vec3f ThinDielectric_getTransparency(
    float cosThetaO, float eta, vec3f attenuation)
{
  // Fresnel term
  float cosThetaT; // positive
  float F = fresnelDielectricEx(cosThetaO, cosThetaT, eta);

  // Attenuation for crossing the slab once
  float length = rcp(cosThetaT);
  vec3f A = expf(attenuation * length);

  return (1.f - F) * A;
}

OSPRAY_END_ISPC_NAMESPACE
