Toshihiro Shimizu 890ddd
/*------------------------------------
Toshihiro Shimizu 890ddd
Iwa_SpectrumFx
Toshihiro Shimizu 890ddd
参照画像を位相差として、干渉色を出力する
Toshihiro Shimizu 890ddd
------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "iwa_spectrumfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "iwa_cie_d65.h"
Toshihiro Shimizu 890ddd
#include "iwa_xyz.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
const float PI = 3.14159265f;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------
shun_iwasawa 4d2acf
 Calculate soap bubble color map
Toshihiro Shimizu 890ddd
------------------------------------*/
shun_iwasawa 4d2acf
void Iwa_SpectrumFx::calcBubbleMap(float3 *bubbleColor, double frame,
shun_iwasawa 4d2acf
                                   bool computeAngularAxis) {
shun_iwasawa 4d2acf
  int i, j, k;  /* bubbleColor[j][k] = [256][3] */
shun_iwasawa 4d2acf
  float d;      /* Thickness of the film (μm) */
shun_iwasawa 4d2acf
  int ram;      /* rambda iterator */
shun_iwasawa 4d2acf
  float rambda; /* wavelength of light (μm) */
Shinya Kitaoka 120a6e
  struct REFLECTIVITY {
shun_iwasawa 4d2acf
    /* transmission and reflection amplitudes for each boundary */
shun_iwasawa 4d2acf
    float r_ab, t_ab, r_ba, t_ba;
shun_iwasawa 4d2acf
    float r_real, r_img; /* reflection amplitude of the film */
shun_iwasawa 4d2acf
    float R;             /* energy reflectance */
Shinya Kitaoka 120a6e
  } p, s;
shun_iwasawa 4d2acf
  float R_final;                   /* combined energy reflectance */
shun_iwasawa 4d2acf
  float phi;                       /* phase */
shun_iwasawa 4d2acf
  float color_x, color_y, color_z; /* xyz color channels */
Shinya Kitaoka 120a6e
shun_iwasawa 4d2acf
  /* obtain parameters */
Shinya Kitaoka 120a6e
  float intensity       = (float)m_intensity->getValue(frame);
Shinya Kitaoka 120a6e
  float refractiveIndex = (float)m_refractiveIndex->getValue(frame);
Shinya Kitaoka 120a6e
  float thickMax        = (float)m_thickMax->getValue(frame);
Shinya Kitaoka 120a6e
  float thickMin        = (float)m_thickMin->getValue(frame);
Shinya Kitaoka 120a6e
  float rgbGamma[3]     = {(float)m_RGamma->getValue(frame),
Shinya Kitaoka 120a6e
                       (float)m_GGamma->getValue(frame),
Shinya Kitaoka 120a6e
                       (float)m_BGamma->getValue(frame)};
Shinya Kitaoka 120a6e
  float lensFactor = (float)m_lensFactor->getValue(frame);
shun-iwasawa 9d0856
  float shift      = (float)m_spectrumShift->getValue(frame);
shun-iwasawa 9d0856
  float fadeWidth  = (float)m_loopSpectrumFadeWidth->getValue(frame) / 2.0f;
Shinya Kitaoka 120a6e
shun_iwasawa 4d2acf
  /* for Iwa_SpectrumFx, incident angle is fixed to 0,
shun_iwasawa 4d2acf
     for Iwa_SoapBubbleFx, compute for all discrete incident angles*/
shun_iwasawa 4d2acf
  int i_max        = (computeAngularAxis) ? 256 : 1;
shun_iwasawa 4d2acf
  float3 *bubble_p = bubbleColor;
shun_iwasawa 4d2acf
shun_iwasawa 4d2acf
  /* for each discrete incident angle */
shun_iwasawa 4d2acf
  for (i = 0; i < i_max; i++) {
shun_iwasawa 4d2acf
    /* incident angle (radian) */
shun_iwasawa 4d2acf
    float angle_in = PI / 2.0f / 255.0f * (float)i;
shun_iwasawa 4d2acf
    /* refraction angle (radian) */
shun_iwasawa 4d2acf
    float angle_re = asinf(sinf(angle_in) / refractiveIndex);
shun_iwasawa 4d2acf
shun_iwasawa 4d2acf
    /* transmission and reflection amplitudes for each boundary, for each
shun_iwasawa 4d2acf
     * polarization */
shun_iwasawa 4d2acf
    float cos_in = cosf(angle_in);
shun_iwasawa 4d2acf
    float cos_re = cosf(angle_re);
shun-iwasawa f7a4d8
shun-iwasawa f7a4d8
    // compute the offset in order to make the seam of looped-spectrum curved
shun-iwasawa f7a4d8
    // along the stripe
shun-iwasawa f7a4d8
    float seam_offset = 0.0f;
shun-iwasawa f7a4d8
    if (fadeWidth != 0.0f) {  // if the fade width is 0, the seam does not curve
shun-iwasawa f7a4d8
      float base_light_diff =
shun-iwasawa f7a4d8
          (thickMax + thickMin) / cosf(asinf(1 / refractiveIndex));
shun-iwasawa f7a4d8
      float offset_width = 0.5f * (base_light_diff - thickMax - thickMin);
shun-iwasawa f7a4d8
      seam_offset        = 0.5f * (base_light_diff *
shun-iwasawa f7a4d8
                                cosf(asinf(cosf(angle_in) / refractiveIndex)) -
shun-iwasawa f7a4d8
                            thickMax - thickMin - offset_width);
shun-iwasawa f7a4d8
    }
shun-iwasawa f7a4d8
shun_iwasawa 4d2acf
    // P-polarized light
shun_iwasawa 4d2acf
    p.r_ab = (cos_re - refractiveIndex * cos_in) /
shun_iwasawa 4d2acf
             (cos_re + refractiveIndex * cos_re);
shun_iwasawa 4d2acf
    p.t_ab = (1.0f - p.r_ab) / refractiveIndex;
shun_iwasawa 4d2acf
    p.r_ba = -p.r_ab;
shun_iwasawa 4d2acf
    p.t_ba = (1.0f + p.r_ab) * refractiveIndex;
shun_iwasawa 4d2acf
    // S-polarized light
shun_iwasawa 4d2acf
    s.r_ab = (cos_in - refractiveIndex * cos_re) /
shun_iwasawa 4d2acf
             (cos_in + refractiveIndex * cos_re);
shun_iwasawa 4d2acf
    s.t_ab = 1.0f + s.r_ab;
shun_iwasawa 4d2acf
    s.r_ba = -s.r_ab;
shun_iwasawa 4d2acf
    s.t_ba = 1.0f - s.r_ab;
shun_iwasawa 4d2acf
shun_iwasawa 4d2acf
    /* for each discrete thickness */
shun_iwasawa 4d2acf
    for (j = 0; j < 256; j++) {
shun-iwasawa 9d0856
      // normalize within 0-1 and shift
shun-iwasawa 9d0856
      float t = (float)j / 255.0f + shift;
shun-iwasawa 9d0856
      // get fractional part
shun-iwasawa 9d0856
      t -= std::floor(t);
shun-iwasawa 9d0856
      // apply lens factor
shun-iwasawa 9d0856
      t = powf(t, lensFactor);
shun-iwasawa 9d0856
shun-iwasawa 9d0856
      float tmp_rgb[2][3];
shun-iwasawa 9d0856
      float tmp_t[2];
shun-iwasawa 9d0856
      float tmp_ratio[2];
shun-iwasawa 9d0856
shun-iwasawa f7a4d8
      if (t < seam_offset - fadeWidth) {
shun-iwasawa f7a4d8
        tmp_t[0]     = t + 1.0f;
shun-iwasawa f7a4d8
        tmp_t[1]     = 0;  // unused
shun-iwasawa f7a4d8
        tmp_ratio[0] = 1.0f;
shun-iwasawa f7a4d8
        tmp_ratio[1] = 0.0f;
shun-iwasawa f7a4d8
      } else if (t < seam_offset + fadeWidth) {
shun-iwasawa 9d0856
        tmp_t[0]     = t;
shun-iwasawa 9d0856
        tmp_t[1]     = t + 1.0f;
shun-iwasawa f7a4d8
        tmp_ratio[0] = 0.5f + 0.5f * (t - seam_offset) / fadeWidth;
shun-iwasawa 9d0856
        tmp_ratio[1] = 1.0f - tmp_ratio[0];
shun-iwasawa f7a4d8
      } else if (t > 1.0f + seam_offset + fadeWidth) {
shun-iwasawa f7a4d8
        tmp_t[0]     = t - 1.0f;
shun-iwasawa f7a4d8
        tmp_t[1]     = 0;  // unused
shun-iwasawa f7a4d8
        tmp_ratio[0] = 1.0f;
shun-iwasawa f7a4d8
        tmp_ratio[1] = 0.0f;
shun-iwasawa f7a4d8
      } else if (t > 1.0f + seam_offset - fadeWidth) {
shun-iwasawa 9d0856
        tmp_t[0]     = t;
shun-iwasawa 9d0856
        tmp_t[1]     = t - 1.0f;
shun-iwasawa f7a4d8
        tmp_ratio[0] = 0.5f + 0.5f * (1.0f - t + seam_offset) / fadeWidth;
shun-iwasawa 9d0856
        tmp_ratio[1] = 1.0f - tmp_ratio[0];
shun-iwasawa 9d0856
      } else {  // no fade
shun-iwasawa 9d0856
        tmp_t[0]     = t;
shun-iwasawa 9d0856
        tmp_t[1]     = 0;  // unused
shun-iwasawa 9d0856
        tmp_ratio[0] = 1.0f;
shun-iwasawa 9d0856
        tmp_ratio[1] = 0.0f;
shun-iwasawa 9d0856
      }
shun-iwasawa 9d0856
shun-iwasawa 9d0856
      /* compute colors for two thickness values and fade them*/
shun-iwasawa 9d0856
      for (int fadeId = 0; fadeId < 2; fadeId++) {
shun-iwasawa 9d0856
        // if composit ratio is 0, skip computing
shun-iwasawa 9d0856
        if (tmp_ratio[fadeId] == 0.0f) continue;
shun-iwasawa 9d0856
shun-iwasawa 9d0856
        /* calculate the thickness of film (μm) */
shun-iwasawa 9d0856
        d = thickMin + (thickMax - thickMin) * tmp_t[fadeId];
shun-iwasawa 9d0856
shun-iwasawa 9d0856
        /* there may be a case that the thickness is smaller than 0 */
shun-iwasawa 9d0856
        if (d < 0.0f) d = 0.0f;
shun-iwasawa 9d0856
shun-iwasawa 9d0856
        /* initialize XYZ color channels */
shun-iwasawa 9d0856
        color_x = 0.0f;
shun-iwasawa 9d0856
        color_y = 0.0f;
shun-iwasawa 9d0856
        color_z = 0.0f;
shun-iwasawa 9d0856
shun-iwasawa 9d0856
        /* for each wavelength (in the range of visible light, 380nm-710nm) */
shun-iwasawa 9d0856
        for (ram = 0; ram < 34; ram++) {
shun-iwasawa 9d0856
          /* wavelength `λ` (μm) */
shun-iwasawa 9d0856
          rambda = 0.38f + 0.01f * (float)ram;
shun-iwasawa 9d0856
          /* phase of light */
shun-iwasawa 9d0856
          phi = 4.0f * PI * refractiveIndex * d * cos_re / rambda;
shun-iwasawa 9d0856
          /* reflection amplitude of the film for each polarization */
shun-iwasawa 9d0856
          // P-polarized light
shun-iwasawa 9d0856
          p.r_real = p.r_ab + p.t_ab * p.r_ba * p.t_ba * cosf(phi);
shun-iwasawa 9d0856
          p.r_img  = p.t_ab * p.r_ba * p.t_ba * sinf(phi);
shun-iwasawa 9d0856
          // S-polarized light
shun-iwasawa 9d0856
          s.r_real = s.r_ab + s.t_ab * s.r_ba * s.t_ba * cosf(phi);
shun-iwasawa 9d0856
          s.r_img  = s.t_ab * s.r_ba * s.t_ba * sinf(phi);
shun-iwasawa 9d0856
shun-iwasawa 9d0856
          p.R = p.r_real * p.r_real + p.r_img * p.r_img;
shun-iwasawa 9d0856
          s.R = s.r_real * s.r_real + s.r_img * s.r_img;
shun-iwasawa 9d0856
shun-iwasawa 9d0856
          /* combined energy reflectance */
shun-iwasawa 9d0856
          R_final = (p.R + s.R) / 2.0f;
shun-iwasawa 9d0856
shun-iwasawa 9d0856
          /* accumulate XYZ channel values */
shun-iwasawa 9d0856
          color_x += intensity * cie_d65[ram] * R_final * xyz[ram * 3 + 0];
shun-iwasawa 9d0856
          color_y += intensity * cie_d65[ram] * R_final * xyz[ram * 3 + 1];
shun-iwasawa 9d0856
          color_z += intensity * cie_d65[ram] * R_final * xyz[ram * 3 + 2];
shun-iwasawa 9d0856
shun-iwasawa 9d0856
        } /* next wavelength (ram) */
shun-iwasawa 9d0856
shun-iwasawa 9d0856
        tmp_rgb[fadeId][0] =
shun-iwasawa 9d0856
            3.240479f * color_x - 1.537150f * color_y - 0.498535f * color_z;
shun-iwasawa 9d0856
        tmp_rgb[fadeId][1] =
shun-iwasawa 9d0856
            -0.969256f * color_x + 1.875992f * color_y + 0.041556f * color_z;
shun-iwasawa 9d0856
        tmp_rgb[fadeId][2] =
shun-iwasawa 9d0856
            0.055648f * color_x - 0.204043f * color_y + 1.057311f * color_z;
shun-iwasawa 9d0856
shun-iwasawa 9d0856
        /* clamp overflows */
shun-iwasawa 9d0856
        for (k = 0; k < 3; k++) {
shun-iwasawa 9d0856
          if (tmp_rgb[fadeId][k] < 0.0f) tmp_rgb[fadeId][k] = 0.0f;
shun-iwasawa 9d0856
shun-iwasawa 9d0856
          /* gamma adjustment */
shun-iwasawa 9d0856
          tmp_rgb[fadeId][k] = powf((tmp_rgb[fadeId][k] / 255.0f), rgbGamma[k]);
shun-iwasawa 9d0856
shun-iwasawa 9d0856
          if (tmp_rgb[fadeId][k] >= 1.0f) tmp_rgb[fadeId][k] = 1.0f;
shun-iwasawa 9d0856
        }
shun_iwasawa 4d2acf
      }
shun-iwasawa 9d0856
      bubble_p->x = tmp_rgb[0][0] * tmp_ratio[0] + tmp_rgb[1][0] * tmp_ratio[1];
shun-iwasawa 9d0856
      bubble_p->y = tmp_rgb[0][1] * tmp_ratio[0] + tmp_rgb[1][1] * tmp_ratio[1];
shun-iwasawa 9d0856
      bubble_p->z = tmp_rgb[0][2] * tmp_ratio[0] + tmp_rgb[1][2] * tmp_ratio[1];
shun_iwasawa 4d2acf
      bubble_p++;
shun_iwasawa 4d2acf
shun_iwasawa 4d2acf
    } /*- next thickness d (j) -*/
shun_iwasawa 4d2acf
  }   /*- next incident angle (i) -*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Iwa_SpectrumFx::Iwa_SpectrumFx()
Shinya Kitaoka 120a6e
    : m_intensity(1.0)
Shinya Kitaoka 120a6e
    , m_refractiveIndex(1.25)
Shinya Kitaoka 120a6e
    , m_thickMax(1.0)
Shinya Kitaoka 120a6e
    , m_thickMin(0.0)
Shinya Kitaoka 120a6e
    , m_RGamma(1.0)
Shinya Kitaoka 120a6e
    , m_GGamma(1.0)
Shinya Kitaoka 120a6e
    , m_BGamma(1.0)
Shinya Kitaoka 120a6e
    , m_lensFactor(1.0)
Shinya Kitaoka 120a6e
    , m_lightThres(1.0)
shun-iwasawa 9d0856
    , m_lightIntensity(1.0)
shun-iwasawa 9d0856
    , m_loopSpectrumFadeWidth(0.0)
shun-iwasawa 9d0856
    , m_spectrumShift(0.0) {
Shinya Kitaoka 120a6e
  addInputPort("Source", m_input);
Shinya Kitaoka 120a6e
  addInputPort("Light", m_light);
Shinya Kitaoka 120a6e
  bindParam(this, "intensity", m_intensity);
Shinya Kitaoka 120a6e
  bindParam(this, "refractiveIndex", m_refractiveIndex);
Shinya Kitaoka 120a6e
  bindParam(this, "thickMax", m_thickMax);
Shinya Kitaoka 120a6e
  bindParam(this, "thickMin", m_thickMin);
Shinya Kitaoka 120a6e
  bindParam(this, "RGamma", m_RGamma);
Shinya Kitaoka 120a6e
  bindParam(this, "GGamma", m_GGamma);
Shinya Kitaoka 120a6e
  bindParam(this, "BGamma", m_BGamma);
Shinya Kitaoka 120a6e
  bindParam(this, "lensFactor", m_lensFactor);
Shinya Kitaoka 120a6e
  bindParam(this, "lightThres", m_lightThres);
Shinya Kitaoka 120a6e
  bindParam(this, "lightIntensity", m_lightIntensity);
shun-iwasawa 9d0856
  bindParam(this, "loopSpectrumFadeWidth", m_loopSpectrumFadeWidth);
shun-iwasawa 9d0856
  bindParam(this, "spectrumShift", m_spectrumShift);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_intensity->setValueRange(0.0, 8.0);
Shinya Kitaoka 120a6e
  m_refractiveIndex->setValueRange(1.0, 3.0);
Shinya Kitaoka 120a6e
  m_thickMax->setValueRange(-1.5, 2.0);
Shinya Kitaoka 120a6e
  m_thickMin->setValueRange(-1.5, 2.0);
Shinya Kitaoka 120a6e
  m_RGamma->setValueRange(0.001, 1.0);
Shinya Kitaoka 120a6e
  m_GGamma->setValueRange(0.001, 1.0);
Shinya Kitaoka 120a6e
  m_BGamma->setValueRange(0.001, 1.0);
Shinya Kitaoka 120a6e
  m_lensFactor->setValueRange(0.01, 10.0);
Shinya Kitaoka 120a6e
  m_lightThres->setValueRange(-5.0, 1.0);
Shinya Kitaoka 120a6e
  m_lightIntensity->setValueRange(0.0, 1.0);
shun-iwasawa 9d0856
  m_loopSpectrumFadeWidth->setValueRange(0.0, 1.0);
shun-iwasawa 9d0856
  m_spectrumShift->setValueRange(-10.0, 10.0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Shinya Kitaoka 120a6e
void Iwa_SpectrumFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                               const TRenderSettings &settings) {
Shinya Kitaoka 120a6e
  if (!m_input.isConnected()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- 薄膜干渉色マップ -*/
Shinya Kitaoka 120a6e
  float3 *bubbleColor;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TDimensionI dim(tile.getRaster()->getLx(), tile.getRaster()->getLy());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- 256段階で干渉色を計算 -*/
Shinya Kitaoka 120a6e
  TRasterGR8P bubbleColor_ras(sizeof(float3) * 256, 1);
Shinya Kitaoka 120a6e
  bubbleColor_ras->lock();
Shinya Kitaoka 120a6e
  bubbleColor = (float3 *)bubbleColor_ras->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- シャボン色マップの生成 -*/
Shinya Kitaoka 120a6e
  calcBubbleMap(bubbleColor, frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- いったん素材をTileに収める -*/
Shinya Kitaoka 120a6e
  m_input->compute(tile, frame, settings);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*--------------------
Shinya Kitaoka 120a6e
   ここで、Lightが刺さっていた場合は、Lightのアルファを使用&HDRThresでスクリーン合成
Shinya Kitaoka 120a6e
  --------------------*/
Shinya Kitaoka 120a6e
  TRasterP lightRas = 0;
Shinya Kitaoka 120a6e
  if (m_light.isConnected()) {
Shinya Kitaoka 120a6e
    TTile light_tile;
Shinya Kitaoka 120a6e
    m_light->allocateAndCompute(light_tile, tile.m_pos, dim, tile.getRaster(),
Shinya Kitaoka 120a6e
                                frame, settings);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    lightRas = light_tile.getRaster();
Shinya Kitaoka 120a6e
    lightRas->lock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P ras32 = (TRaster32P)tile.getRaster();
Shinya Kitaoka 120a6e
  TRaster64P ras64 = (TRaster64P)tile.getRaster();
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    if (ras32) {
Shinya Kitaoka 120a6e
      if (lightRas)
Shinya Kitaoka 120a6e
        convertRasterWithLight<traster32p, tpixel32="">(</traster32p,>
Shinya Kitaoka 120a6e
            ras32, dim, bubbleColor, (TRaster32P)lightRas,
Shinya Kitaoka 120a6e
            (float)m_lightThres->getValue(frame),
Shinya Kitaoka 120a6e
            (float)m_lightIntensity->getValue(frame));
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        convertRaster<traster32p, tpixel32="">(ras32, dim, bubbleColor);</traster32p,>
Shinya Kitaoka 120a6e
    } else if (ras64) {
Shinya Kitaoka 120a6e
      if (lightRas)
Shinya Kitaoka 120a6e
        convertRasterWithLight<traster64p, tpixel64="">(</traster64p,>
Shinya Kitaoka 120a6e
            ras64, dim, bubbleColor, (TRaster64P)lightRas,
Shinya Kitaoka 120a6e
            (float)m_lightThres->getValue(frame),
Shinya Kitaoka 120a6e
            (float)m_lightIntensity->getValue(frame));
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        convertRaster<traster64p, tpixel64="">(ras64, dim, bubbleColor);</traster64p,>
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //メモリ解放
Shinya Kitaoka 120a6e
  // brightness_ras->unlock();
Shinya Kitaoka 120a6e
  bubbleColor_ras->unlock();
Shinya Kitaoka 120a6e
  if (lightRas) lightRas->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_SpectrumFx::convertRaster(const RASTER ras, TDimensionI dim,
Shinya Kitaoka 120a6e
                                   float3 *bubbleColor) {
Shinya Kitaoka 120a6e
  float rr, gg, bb, aa;
Shinya Kitaoka 120a6e
  float spec_r, spec_g, spec_b;
Shinya Kitaoka 120a6e
  float brightness;
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix = ras->pixels(j);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; i++) {
Shinya Kitaoka 120a6e
      aa = (float)pix->m / PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      if (aa == 0.0f) /*- アルファが0なら変化なし -*/
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        pix++;
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*- depremutiplyはしないでおく -*/
Shinya Kitaoka 120a6e
      rr         = (float)pix->r / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      gg         = (float)pix->g / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      bb         = (float)pix->b / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      brightness = 0.298912f * rr + 0.586611f * gg + 0.114478f * bb;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- 反転 -*/
Shinya Kitaoka 120a6e
      brightness = 1.0f - brightness;
Shinya Kitaoka 120a6e
      /*- 輝度MAXの場合 -*/
Shinya Kitaoka 120a6e
      if (brightness >= 1.0f) {
Shinya Kitaoka 120a6e
        spec_r = bubbleColor[255].x * aa;
Shinya Kitaoka 120a6e
        spec_g = bubbleColor[255].y * aa;
Shinya Kitaoka 120a6e
        spec_b = bubbleColor[255].z * aa;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        /*- 線形補間する -*/
Shinya Kitaoka 120a6e
        int index   = (int)(brightness * 255.0f);
Shinya Kitaoka 120a6e
        float ratio = brightness * 255.0f - (float)index;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        spec_r = bubbleColor[index].x * (1.0f - ratio) +
Shinya Kitaoka 120a6e
                 bubbleColor[index + 1].x * ratio;
Shinya Kitaoka 120a6e
        spec_g = bubbleColor[index].y * (1.0f - ratio) +
Shinya Kitaoka 120a6e
                 bubbleColor[index + 1].y * ratio;
Shinya Kitaoka 120a6e
        spec_b = bubbleColor[index].z * (1.0f - ratio) +
Shinya Kitaoka 120a6e
                 bubbleColor[index + 1].z * ratio;
Shinya Kitaoka 120a6e
        spec_r *= aa;
Shinya Kitaoka 120a6e
        spec_g *= aa;
Shinya Kitaoka 120a6e
        spec_b *= aa;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*- 元のピクセルに書き戻す -*/
Shinya Kitaoka 120a6e
      float val;
Shinya Kitaoka 120a6e
      /*- チャンネル範囲にクランプ -*/
Shinya Kitaoka 120a6e
      val    = spec_r * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = spec_g * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = spec_b * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_SpectrumFx::convertRasterWithLight(const RASTER ras, TDimensionI dim,
Shinya Kitaoka 120a6e
                                            float3 *bubbleColor,
Shinya Kitaoka 120a6e
                                            const RASTER lightRas,
Shinya Kitaoka 120a6e
                                            float lightThres,
Shinya Kitaoka 120a6e
                                            float lightIntensity) {
Shinya Kitaoka 120a6e
  float rr, gg, bb, aa;
Shinya Kitaoka 120a6e
  float spec_r, spec_g, spec_b;
Shinya Kitaoka 120a6e
  float brightness;
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *light_pix = lightRas->pixels(j);
Shinya Kitaoka 120a6e
    PIXEL *pix       = ras->pixels(j);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; i++) {
Shinya Kitaoka 120a6e
      aa = (float)light_pix->m / PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      if (aa == 0.0f) /*- アルファが0なら透明にする -*/
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        *pix = PIXEL::Transparent;
Shinya Kitaoka 120a6e
        light_pix++;
Shinya Kitaoka 120a6e
        pix++;
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*- depremutiplyはしないでおく -*/
Shinya Kitaoka 120a6e
      rr         = (float)pix->r / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      gg         = (float)pix->g / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      bb         = (float)pix->b / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      brightness = 0.298912f * rr + 0.586611f * gg + 0.114478f * bb;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- 反転 -*/
Shinya Kitaoka 120a6e
      brightness = 1.0f - brightness;
Shinya Kitaoka 120a6e
      /*- 輝度MAXの場合 -*/
Shinya Kitaoka 120a6e
      if (brightness >= 1.0f) {
Shinya Kitaoka 120a6e
        spec_r = bubbleColor[255].x;
Shinya Kitaoka 120a6e
        spec_g = bubbleColor[255].y;
Shinya Kitaoka 120a6e
        spec_b = bubbleColor[255].z;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        /*- 線形補間する -*/
Shinya Kitaoka 120a6e
        int index   = (int)(brightness * 255.0f);
Shinya Kitaoka 120a6e
        float ratio = brightness * 255.0f - (float)index;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        spec_r = bubbleColor[index].x * (1.0f - ratio) +
Shinya Kitaoka 120a6e
                 bubbleColor[index + 1].x * ratio;
Shinya Kitaoka 120a6e
        spec_g = bubbleColor[index].y * (1.0f - ratio) +
Shinya Kitaoka 120a6e
                 bubbleColor[index + 1].y * ratio;
Shinya Kitaoka 120a6e
        spec_b = bubbleColor[index].z * (1.0f - ratio) +
Shinya Kitaoka 120a6e
                 bubbleColor[index + 1].z * ratio;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- ここで、Light画像とのスクリーン合成を行う -*/
Shinya Kitaoka 120a6e
      float HDR_Factor;
Shinya Kitaoka 120a6e
      if (aa <= lightThres || lightThres == 1.0f)
Shinya Kitaoka 120a6e
        HDR_Factor = 0.0;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        HDR_Factor = lightIntensity * (aa - lightThres) / (1.0 - lightThres);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      float light_r = (float)light_pix->r / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      float light_g = (float)light_pix->g / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      float light_b = (float)light_pix->b / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      /*- スクリーン合成結果と虹色をHDR_Factorで混ぜる -*/
Shinya Kitaoka 120a6e
      spec_r = (1.0f - HDR_Factor) * spec_r +
Shinya Kitaoka 120a6e
               HDR_Factor * (spec_r + light_r - spec_r * light_r);
Shinya Kitaoka 120a6e
      spec_g = (1.0f - HDR_Factor) * spec_g +
Shinya Kitaoka 120a6e
               HDR_Factor * (spec_g + light_g - spec_g * light_g);
Shinya Kitaoka 120a6e
      spec_b = (1.0f - HDR_Factor) * spec_b +
Shinya Kitaoka 120a6e
               HDR_Factor * (spec_b + light_b - spec_b * light_b);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      spec_r *= aa;
Shinya Kitaoka 120a6e
      spec_g *= aa;
Shinya Kitaoka 120a6e
      spec_b *= aa;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*- 元のピクセルに書き戻す -*/
Shinya Kitaoka 120a6e
      float val;
Shinya Kitaoka 120a6e
      /*- チャンネル範囲にクランプ -*/
Shinya Kitaoka 120a6e
      val    = spec_r * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = spec_g * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = spec_b * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      pix->m = light_pix->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
      light_pix++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------
Toshihiro Shimizu 890ddd
 素材タイルを0〜1に正規化して格納
Toshihiro Shimizu 890ddd
------------------------------------*/
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Shinya Kitaoka 120a6e
void Iwa_SpectrumFx::setSourceRasters(const RASTER ras,
Shinya Kitaoka 120a6e
                                      float4 *in_out_tile_host,
Shinya Kitaoka 120a6e
                                      const RASTER light_ras,
Shinya Kitaoka 120a6e
                                      float4 *light_host, TDimensionI dim,
Shinya Kitaoka 120a6e
                                      bool useLight) {
Shinya Kitaoka 120a6e
  float4 *chann_p      = in_out_tile_host;
Shinya Kitaoka 120a6e
  float4 *lightChann_p = light_host;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix      = ras->pixels(j);
Shinya Kitaoka 120a6e
    PIXEL *lightPix = (useLight) ? light_ras->pixels(j) : 0;
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; i++) {
Shinya Kitaoka 120a6e
      (*chann_p).x = (float)pix->r / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).y = (float)pix->g / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).z = (float)pix->b / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      (*chann_p).w = (float)pix->m / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
      chann_p++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (useLight) {
Shinya Kitaoka 120a6e
        (*lightChann_p).x = (float)lightPix->r / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
        (*lightChann_p).y = (float)lightPix->g / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
        (*lightChann_p).z = (float)lightPix->b / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
        (*lightChann_p).w = (float)lightPix->m / (float)PIXEL::maxChannelValue;
Shinya Kitaoka 120a6e
        lightPix++;
Shinya Kitaoka 120a6e
        lightChann_p++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------
Toshihiro Shimizu 890ddd
 出力結果をChannel値に変換してタイルに格納
Toshihiro Shimizu 890ddd
------------------------------------*/
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void Iwa_SpectrumFx::outputRasters(const RASTER outRas,
Shinya Kitaoka 120a6e
                                   float4 *in_out_tile_host, TDimensionI dim) {
Shinya Kitaoka 120a6e
  float4 *chann_p = in_out_tile_host;
Shinya Kitaoka 120a6e
  for (int j = 0; j < dim.ly; j++) {
Shinya Kitaoka 120a6e
    PIXEL *pix = outRas->pixels(j);
Shinya Kitaoka 120a6e
    for (int i = 0; i < dim.lx; i++) {
Shinya Kitaoka 120a6e
      float val;
Shinya Kitaoka 120a6e
      val    = (*chann_p).x * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chann_p).y * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chann_p).z * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      val    = (*chann_p).w * (float)PIXEL::maxChannelValue + 0.5f;
Shinya Kitaoka 120a6e
      pix->m = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
Shinya Kitaoka 120a6e
                                             ? (float)PIXEL::maxChannelValue
Shinya Kitaoka 120a6e
                                             : val);
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
      chann_p++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool Iwa_SpectrumFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                               const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (!m_input.isConnected()) {
Shinya Kitaoka 120a6e
    bBox = TRectD();
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return m_input->doGetBBox(frame, bBox, info);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool Iwa_SpectrumFx::canHandle(const TRenderSettings &info, double frame) {
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(Iwa_SpectrumFx, "iwa_SpectrumFx")