|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "traster.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpixelutils.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//***********************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace stuff
|
|
Toshihiro Shimizu |
890ddd |
//***********************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
struct RaylitFuncTraits {
|
|
Shinya Kitaoka |
120a6e |
typedef void (*function_type)(T *, T *, int, int, int, int, const TRect &,
|
|
Shinya Kitaoka |
120a6e |
const TRect &, const TRop::RaylitParams &);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void performStandardRaylit(T *bufIn, T *bufOut, int dxIn, int dyIn, int dxOut,
|
|
Shinya Kitaoka |
120a6e |
int dyOut, const TRect &srcRect,
|
|
Shinya Kitaoka |
120a6e |
const TRect &dstRect,
|
|
Shinya Kitaoka |
120a6e |
const TRop::RaylitParams ¶ms) {
|
|
Shinya Kitaoka |
120a6e |
/* NOTATION: Diagram assuming octant 1
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/ |
|
|
Shinya Kitaoka |
120a6e |
/ |
|
|
Shinya Kitaoka |
120a6e |
/ - ray_final_y | octLy
|
|
Shinya Kitaoka |
120a6e |
/ 1 |
|
|
Shinya Kitaoka |
120a6e |
+---- |
|
|
Shinya Kitaoka |
120a6e |
_____ octLx
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
So, octLx and octLy are the octant's lx and ly; ray_final_y is the final height
|
|
Shinya Kitaoka |
120a6e |
of the ray we're tracing
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Build colors-related variables
|
|
Shinya Kitaoka |
120a6e |
int max = T::maxChannelValue;
|
|
shun-iwasawa |
443318 |
/*-- Color of transparent part --*/
|
|
Shinya Kitaoka |
120a6e |
int transp_val = (params.m_invert) ? max : 0, opaque_val = max - transp_val;
|
|
Shinya Kitaoka |
120a6e |
int value, val_r, val_g, val_b, val_m;
|
|
Shinya Kitaoka |
120a6e |
double lightness, r_fac, g_fac, b_fac, m_fac;
|
|
shun-iwasawa |
443318 |
/*-- Coefficients to absorb 8bit/16bit difference --*/
|
|
Shinya Kitaoka |
120a6e |
double factor = max / 255.0;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
255f14 |
// NOTE: These variable initializations are, well,
|
|
shun-iwasawa |
255f14 |
// heuristic at least. They were probably tested
|
|
shun-iwasawa |
255f14 |
// to be good, but didn't quite make any REAL sense.
|
|
Shinya Kitaoka |
120a6e |
// They could be done MUCH better, but changing them
|
|
shun-iwasawa |
255f14 |
// would alter the way raylit has been applied until now.
|
|
shun-iwasawa |
255f14 |
// Should be changed at some point, though...
|
|
shun-iwasawa |
255f14 |
|
|
shun-iwasawa |
255f14 |
double scale = params.m_scale;
|
|
shun-iwasawa |
255f14 |
double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;
|
|
shun-iwasawa |
255f14 |
double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
|
|
shun-iwasawa |
255f14 |
double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
|
|
shun-iwasawa |
255f14 |
double radius = params.m_radius;
|
|
shun-iwasawa |
255f14 |
|
|
shun-iwasawa |
443318 |
/*-- The rate at which light diminishes when there is no light source at the
|
|
shun-iwasawa |
443318 |
* next pixel when advancing one step. --*/
|
|
shun-iwasawa |
255f14 |
double neg_delta_p = smoothness * intensity;
|
|
shun-iwasawa |
443318 |
/*-- The rate at which light intensifies when there is a light source at the
|
|
shun-iwasawa |
443318 |
* next pixel when advancing one step. --*/
|
|
Shinya Kitaoka |
120a6e |
double quot_delta_p = intensity / max; //
|
|
shun-iwasawa |
255f14 |
|
|
Shinya Kitaoka |
120a6e |
/*--
|
|
shun-iwasawa |
443318 |
* m_color is the Color value of RaylitFx. r_fac, g_fac, b_fac are the
|
|
shun-iwasawa |
443318 |
* premultiplied values of each channel
|
|
Shinya Kitaoka |
120a6e |
* --*/
|
|
Shinya Kitaoka |
120a6e |
m_fac = (params.m_color.m / 255.0);
|
|
Shinya Kitaoka |
120a6e |
r_fac = m_fac * (params.m_color.r / 255.0);
|
|
Shinya Kitaoka |
120a6e |
g_fac = m_fac * (params.m_color.g / 255.0);
|
|
Shinya Kitaoka |
120a6e |
b_fac = m_fac * (params.m_color.b / 255.0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Geometry-related variables
|
|
Shinya Kitaoka |
120a6e |
int x, y, ray_final_y;
|
|
Shinya Kitaoka |
120a6e |
int octLx = dstRect.x1 - dstRect.x0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double rayPosIncrementX = 1.0 / scale;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square
|
|
Shinya Kitaoka |
120a6e |
// distances from p, so square
|
|
Shinya Kitaoka |
120a6e |
// it once now
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Perform raylit
|
|
Shinya Kitaoka |
120a6e |
T *pixIn, *pixOut;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
|
|
Shinya Kitaoka |
120a6e |
// Initialize increment variables
|
|
Shinya Kitaoka |
120a6e |
lightness = 0.0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Use an integer counter to know when y must increase. Will add ray_final_y
|
|
Shinya Kitaoka |
120a6e |
// as long as
|
|
Shinya Kitaoka |
120a6e |
// a multiple of octLx-1 is reached, then increase
|
|
Shinya Kitaoka |
120a6e |
int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Trace a single ray of light
|
|
Shinya Kitaoka |
120a6e |
TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
|
|
Shinya Kitaoka |
120a6e |
(x < dstRect.x1) && (y < dstRect.y1); ++x) {
|
|
Shinya Kitaoka |
120a6e |
bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
|
|
Shinya Kitaoka |
120a6e |
(y >= srcRect.y0) && (y < srcRect.y1);
|
|
Shinya Kitaoka |
120a6e |
if (insideSrc) {
|
|
Shinya Kitaoka |
120a6e |
// Add a light component depending on source's matte
|
|
Shinya Kitaoka |
120a6e |
if (pixIn->m == opaque_val)
|
|
Shinya Kitaoka |
120a6e |
lightness = std::max(
|
|
Shinya Kitaoka |
120a6e |
0.0, lightness - neg_delta_p); // No light source - ray fading
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
if (pixIn->m == transp_val)
|
|
Shinya Kitaoka |
120a6e |
lightness += intensity; // Full light source - ray enforcing
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
lightness = std::max(
|
|
Shinya Kitaoka |
120a6e |
0.0, lightness + // Half light source
|
|
Shinya Kitaoka |
120a6e |
(params.m_invert ? pixIn->m : (max - pixIn->m)) *
|
|
Shinya Kitaoka |
120a6e |
quot_delta_p); // matte-linear enforcing
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (params.m_includeInput) {
|
|
Shinya Kitaoka |
120a6e |
val_r = pixIn->r;
|
|
Shinya Kitaoka |
120a6e |
val_g = pixIn->g;
|
|
Shinya Kitaoka |
120a6e |
val_b = pixIn->b;
|
|
Shinya Kitaoka |
120a6e |
val_m = pixIn->m;
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
val_r = val_g = val_b = val_m = 0;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (!params.m_invert)
|
|
Shinya Kitaoka |
120a6e |
lightness += intensity;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
lightness = std::max(0.0, lightness - neg_delta_p);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
val_r = val_g = val_b = val_m = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool insideDst = (x >= 0) && (y >= 0);
|
|
Shinya Kitaoka |
120a6e |
if (insideDst) {
|
|
Shinya Kitaoka |
120a6e |
// Write the corresponding destination pixel
|
|
shun-iwasawa |
255f14 |
if (lightness > 0.0) {
|
|
shun-iwasawa |
255f14 |
if (radius == 0.0) {
|
|
shun-iwasawa |
255f14 |
value = (int)(factor * lightness /
|
|
shun-iwasawa |
255f14 |
(rayPos.x *
|
|
shun-iwasawa |
255f14 |
pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z),
|
|
shun-iwasawa |
255f14 |
decay)) +
|
|
shun-iwasawa |
255f14 |
0.5); // * ^-d... 0.5 rounds
|
|
shun-iwasawa |
255f14 |
} else {
|
|
shun-iwasawa |
255f14 |
double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
|
|
shun-iwasawa |
255f14 |
value = (int)(factor * lightness /
|
|
shun-iwasawa |
255f14 |
(rayPos.x * ratio *
|
|
shun-iwasawa |
255f14 |
pow((double)(sq(rayPos.x * ratio) +
|
|
shun-iwasawa |
255f14 |
sq(rayPos.y * ratio) + sq_z),
|
|
shun-iwasawa |
481b59 |
decay)) +
|
|
shun-iwasawa |
255f14 |
0.5); // * ^-d... 0.5 rounds
|
|
shun-iwasawa |
255f14 |
}
|
|
shun-iwasawa |
255f14 |
} else
|
|
Shinya Kitaoka |
120a6e |
value = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// NOTE: pow() could be slow. If that is the case, it could be cached
|
|
Shinya Kitaoka |
120a6e |
// for the whole octant along the longest ray at integer positions,
|
|
Shinya Kitaoka |
120a6e |
// and then linearly interpolated between those... Have to profile this
|
|
Shinya Kitaoka |
120a6e |
// before resorting to that...
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
val_r += value * r_fac;
|
|
Shinya Kitaoka |
120a6e |
val_g += value * g_fac;
|
|
Shinya Kitaoka |
120a6e |
val_b += value * b_fac;
|
|
Shinya Kitaoka |
120a6e |
val_m += value * m_fac;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
pixOut->r = (val_r > max) ? max : val_r;
|
|
Shinya Kitaoka |
120a6e |
pixOut->g = (val_g > max) ? max : val_g;
|
|
Shinya Kitaoka |
120a6e |
pixOut->b = (val_b > max) ? max : val_b;
|
|
Shinya Kitaoka |
120a6e |
pixOut->m = (val_m > max) ? max : val_m;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Increment variables along the x-axis
|
|
Shinya Kitaoka |
120a6e |
pixIn += dxIn, pixOut += dxOut;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Increment variables along the y-axis
|
|
Shinya Kitaoka |
120a6e |
if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
|
|
Shinya Kitaoka |
120a6e |
++y, pixIn += dyIn, pixOut += dyOut;
|
|
Shinya Kitaoka |
120a6e |
yIncrementCounter -= yIncrementThreshold;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
// specialization for floating point pixel
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void performStandardRaylit<tpixelf>(TPixelF *bufIn, TPixelF *bufOut, int dxIn,</tpixelf>
|
|
shun-iwasawa |
481b59 |
int dyIn, int dxOut, int dyOut,
|
|
shun-iwasawa |
481b59 |
const TRect &srcRect, const TRect &dstRect,
|
|
shun-iwasawa |
481b59 |
const TRop::RaylitParams ¶ms) {
|
|
shun-iwasawa |
481b59 |
/* NOTATION: Diagram assuming octant 1
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/ |
|
|
shun-iwasawa |
481b59 |
/ |
|
|
shun-iwasawa |
481b59 |
/ - ray_final_y | octLy
|
|
shun-iwasawa |
481b59 |
/ 1 |
|
|
shun-iwasawa |
481b59 |
+---- |
|
|
shun-iwasawa |
481b59 |
_____ octLx
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
So, octLx and octLy are the octant's lx and ly; ray_final_y is the final height
|
|
shun-iwasawa |
481b59 |
of the ray we're tracing
|
|
shun-iwasawa |
481b59 |
*/
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Build colors-related variables
|
|
shun-iwasawa |
481b59 |
float max = TPixelF::maxChannelValue;
|
|
shun-iwasawa |
443318 |
/*-- Color of transparent part --*/
|
|
shun-iwasawa |
481b59 |
float transp_val = (params.m_invert) ? max : 0.f,
|
|
shun-iwasawa |
481b59 |
opaque_val = max - transp_val;
|
|
shun-iwasawa |
481b59 |
float value, val_r, val_g, val_b, val_m;
|
|
shun-iwasawa |
481b59 |
double lightness, r_fac, g_fac, b_fac, m_fac;
|
|
shun-iwasawa |
443318 |
/*-- Coefficients to absorb 8bit/16bit difference --*/
|
|
shun-iwasawa |
481b59 |
double factor = max / 255.0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// NOTE: These variable initializations are, well,
|
|
shun-iwasawa |
481b59 |
// heuristic at least. They were probably tested
|
|
shun-iwasawa |
481b59 |
// to be good, but didn't quite make any REAL sense.
|
|
shun-iwasawa |
481b59 |
// They could be done MUCH better, but changing them
|
|
shun-iwasawa |
481b59 |
// would alter the way raylit has been applied until now.
|
|
shun-iwasawa |
481b59 |
// Should be changed at some point, though...
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double scale = params.m_scale;
|
|
shun-iwasawa |
481b59 |
double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;
|
|
shun-iwasawa |
481b59 |
double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
|
|
shun-iwasawa |
481b59 |
double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
|
|
shun-iwasawa |
481b59 |
double radius = params.m_radius;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
443318 |
/*-- The rate at which light diminishes when there is no light source at the
|
|
shun-iwasawa |
443318 |
* next pixel when advancing one step. --*/
|
|
shun-iwasawa |
481b59 |
double neg_delta_p = smoothness * intensity;
|
|
shun-iwasawa |
443318 |
/*-- The rate at which light intensifies when there is a light source at the
|
|
shun-iwasawa |
443318 |
* next pixel when advancing one step. --*/
|
|
shun-iwasawa |
481b59 |
double quot_delta_p = intensity / max; //
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
/*--
|
|
shun-iwasawa |
443318 |
* m_color is the Color value of RaylitFx. r_fac, g_fac, b_fac are the
|
|
shun-iwasawa |
443318 |
* premultiplied values of each channel
|
|
shun-iwasawa |
481b59 |
* --*/
|
|
shun-iwasawa |
481b59 |
TPixelF colorF = toPixelF(params.m_color);
|
|
shun-iwasawa |
481b59 |
m_fac = colorF.m;
|
|
shun-iwasawa |
481b59 |
r_fac = m_fac * colorF.r;
|
|
shun-iwasawa |
481b59 |
g_fac = m_fac * colorF.g;
|
|
shun-iwasawa |
481b59 |
b_fac = m_fac * colorF.b;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Geometry-related variables
|
|
shun-iwasawa |
481b59 |
int x, y, ray_final_y;
|
|
shun-iwasawa |
481b59 |
int octLx = dstRect.x1 - dstRect.x0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double rayPosIncrementX = 1.0 / scale;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square
|
|
shun-iwasawa |
481b59 |
// distances from p, so square
|
|
shun-iwasawa |
481b59 |
// it once now
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Perform raylit
|
|
shun-iwasawa |
481b59 |
TPixelF *pixIn, *pixOut;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
|
|
shun-iwasawa |
481b59 |
// Initialize increment variables
|
|
shun-iwasawa |
481b59 |
lightness = 0.0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Use an integer counter to know when y must increase. Will add ray_final_y
|
|
shun-iwasawa |
481b59 |
// as long as
|
|
shun-iwasawa |
481b59 |
// a multiple of octLx-1 is reached, then increase
|
|
shun-iwasawa |
481b59 |
int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Trace a single ray of light
|
|
shun-iwasawa |
481b59 |
TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
|
|
shun-iwasawa |
481b59 |
(x < dstRect.x1) && (y < dstRect.y1); ++x) {
|
|
shun-iwasawa |
481b59 |
bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
|
|
shun-iwasawa |
481b59 |
(y >= srcRect.y0) && (y < srcRect.y1);
|
|
shun-iwasawa |
481b59 |
if (insideSrc) {
|
|
shun-iwasawa |
481b59 |
// Add a light component depending on source's matte
|
|
shun-iwasawa |
481b59 |
if (areAlmostEqual((double)pixIn->m, (double)opaque_val))
|
|
shun-iwasawa |
481b59 |
lightness = std::max(
|
|
shun-iwasawa |
481b59 |
0.0, lightness - neg_delta_p); // No light source - ray fading
|
|
shun-iwasawa |
481b59 |
else {
|
|
shun-iwasawa |
481b59 |
if (areAlmostEqual((double)pixIn->m, (double)transp_val))
|
|
shun-iwasawa |
481b59 |
lightness += intensity; // Full light source - ray enforcing
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
lightness = std::max(
|
|
shun-iwasawa |
481b59 |
0.0, lightness + // Half light source
|
|
shun-iwasawa |
481b59 |
(params.m_invert ? pixIn->m : (max - pixIn->m)) *
|
|
shun-iwasawa |
481b59 |
quot_delta_p); // matte-linear enforcing
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
if (params.m_includeInput) {
|
|
shun-iwasawa |
481b59 |
val_r = pixIn->r;
|
|
shun-iwasawa |
481b59 |
val_g = pixIn->g;
|
|
shun-iwasawa |
481b59 |
val_b = pixIn->b;
|
|
shun-iwasawa |
481b59 |
val_m = pixIn->m;
|
|
shun-iwasawa |
481b59 |
} else
|
|
shun-iwasawa |
481b59 |
val_r = val_g = val_b = val_m = 0.f;
|
|
shun-iwasawa |
481b59 |
} else {
|
|
shun-iwasawa |
481b59 |
if (!params.m_invert)
|
|
shun-iwasawa |
481b59 |
lightness += intensity;
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
lightness = std::max(0.0, lightness - neg_delta_p);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
val_r = val_g = val_b = val_m = 0.f;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
bool insideDst = (x >= 0) && (y >= 0);
|
|
shun-iwasawa |
481b59 |
if (insideDst) {
|
|
shun-iwasawa |
481b59 |
// Write the corresponding destination pixel
|
|
shun-iwasawa |
481b59 |
if (lightness > 0.0) {
|
|
shun-iwasawa |
481b59 |
if (radius == 0.0) {
|
|
shun-iwasawa |
481b59 |
value =
|
|
shun-iwasawa |
481b59 |
factor * lightness /
|
|
shun-iwasawa |
481b59 |
(rayPos.x * pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z),
|
|
shun-iwasawa |
481b59 |
decay)); // * ^-d...
|
|
shun-iwasawa |
481b59 |
} else {
|
|
shun-iwasawa |
481b59 |
double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
|
|
shun-iwasawa |
481b59 |
value = factor * lightness /
|
|
shun-iwasawa |
481b59 |
(rayPos.x * ratio *
|
|
shun-iwasawa |
481b59 |
pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) +
|
|
shun-iwasawa |
481b59 |
sq_z),
|
|
shun-iwasawa |
481b59 |
decay)); // * ^-d...
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
} else
|
|
shun-iwasawa |
481b59 |
value = 0.f;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// NOTE: pow() could be slow. If that is the case, it could be cached
|
|
shun-iwasawa |
481b59 |
// for the whole octant along the longest ray at integer positions,
|
|
shun-iwasawa |
481b59 |
// and then linearly interpolated between those... Have to profile this
|
|
shun-iwasawa |
481b59 |
// before resorting to that...
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
val_r += value * r_fac;
|
|
shun-iwasawa |
481b59 |
val_g += value * g_fac;
|
|
shun-iwasawa |
481b59 |
val_b += value * b_fac;
|
|
shun-iwasawa |
481b59 |
val_m += value * m_fac;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
pixOut->r = val_r;
|
|
shun-iwasawa |
481b59 |
pixOut->g = val_g;
|
|
shun-iwasawa |
481b59 |
pixOut->b = val_b;
|
|
shun-iwasawa |
481b59 |
pixOut->m = (val_m > max) ? max : val_m;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Increment variables along the x-axis
|
|
shun-iwasawa |
481b59 |
pixIn += dxIn, pixOut += dxOut;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Increment variables along the y-axis
|
|
shun-iwasawa |
481b59 |
if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
|
|
shun-iwasawa |
481b59 |
++y, pixIn += dyIn, pixOut += dyOut;
|
|
shun-iwasawa |
481b59 |
yIncrementCounter -= yIncrementThreshold;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void performColorRaylit(T *bufIn, T *bufOut, int dxIn, int dyIn, int dxOut,
|
|
Shinya Kitaoka |
120a6e |
int dyOut, const TRect &srcRect, const TRect &dstRect,
|
|
Shinya Kitaoka |
120a6e |
const TRop::RaylitParams ¶ms) {
|
|
Shinya Kitaoka |
120a6e |
// Build colors-related variables
|
|
Shinya Kitaoka |
120a6e |
int max = T::maxChannelValue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int val_r, val_g, val_b, val_m;
|
|
Shinya Kitaoka |
120a6e |
double lightness_r, lightness_g, lightness_b;
|
|
Shinya Kitaoka |
120a6e |
double factor = max / 255.0;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
255f14 |
// NOTE: These variable initializations are, well,
|
|
shun-iwasawa |
255f14 |
// heuristic at least. They were probably tested
|
|
shun-iwasawa |
255f14 |
// to be good, but didn't quite make any REAL sense.
|
|
Shinya Kitaoka |
120a6e |
// They could be done MUCH better, but changing them
|
|
shun-iwasawa |
255f14 |
// would alter the way raylit has been applied until now.
|
|
shun-iwasawa |
255f14 |
// Should be changed at some point, though...
|
|
shun-iwasawa |
255f14 |
|
|
shun-iwasawa |
255f14 |
double scale = params.m_scale;
|
|
shun-iwasawa |
255f14 |
double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;
|
|
shun-iwasawa |
255f14 |
double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
|
|
shun-iwasawa |
255f14 |
double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
|
|
shun-iwasawa |
255f14 |
double radius = params.m_radius;
|
|
shun-iwasawa |
255f14 |
|
|
Shinya Kitaoka |
120a6e |
double neg_delta_p =
|
|
Shinya Kitaoka |
120a6e |
smoothness *
|
|
Shinya Kitaoka |
120a6e |
intensity; // would alter the way raylit has been applied until now.
|
|
Shinya Kitaoka |
120a6e |
double quot_delta_p = intensity / max; //
|
|
Shinya Kitaoka |
120a6e |
// Should be changed at some point, though...
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Geometry-related variables
|
|
Shinya Kitaoka |
120a6e |
int x, y, ray_final_y;
|
|
Shinya Kitaoka |
120a6e |
int octLx = dstRect.x1 - dstRect.x0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double rayPosIncrementX = 1.0 / scale;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double fac, sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square
|
|
Shinya Kitaoka |
120a6e |
// distances from p, so
|
|
Shinya Kitaoka |
120a6e |
// square it once now
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Perform raylit
|
|
Shinya Kitaoka |
120a6e |
T *pixIn, *pixOut;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
|
|
Shinya Kitaoka |
120a6e |
// Initialize increment variables
|
|
Shinya Kitaoka |
120a6e |
lightness_r = lightness_g = lightness_b = 0.0;
|
|
Shinya Kitaoka |
120a6e |
int l, l_max;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Use an integer counter to know when y must increase. Will add ray_final_y
|
|
Shinya Kitaoka |
120a6e |
// as long as
|
|
Shinya Kitaoka |
120a6e |
// a multiple of octLx-1 is reached, then increase
|
|
Shinya Kitaoka |
120a6e |
int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Trace a single ray of light
|
|
Shinya Kitaoka |
120a6e |
TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
|
|
Shinya Kitaoka |
120a6e |
(x < dstRect.x1) && (y < dstRect.y1); ++x) {
|
|
Shinya Kitaoka |
120a6e |
bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
|
|
Shinya Kitaoka |
120a6e |
(y >= srcRect.y0) && (y < srcRect.y1);
|
|
Shinya Kitaoka |
120a6e |
if (insideSrc) {
|
|
Shinya Kitaoka |
120a6e |
val_r = pixIn->r;
|
|
Shinya Kitaoka |
120a6e |
val_g = pixIn->g;
|
|
Shinya Kitaoka |
120a6e |
val_b = pixIn->b;
|
|
Shinya Kitaoka |
120a6e |
val_m = pixIn->m;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
lightness_r = std::max(0.0, val_r ? lightness_r + val_r * quot_delta_p
|
|
Shinya Kitaoka |
120a6e |
: lightness_r - neg_delta_p);
|
|
Shinya Kitaoka |
120a6e |
lightness_g = std::max(0.0, val_g ? lightness_g + val_g * quot_delta_p
|
|
Shinya Kitaoka |
120a6e |
: lightness_g - neg_delta_p);
|
|
Shinya Kitaoka |
120a6e |
lightness_b = std::max(0.0, val_b ? lightness_b + val_b * quot_delta_p
|
|
Shinya Kitaoka |
120a6e |
: lightness_b - neg_delta_p);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!params.m_includeInput) val_r = val_g = val_b = val_m = 0;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
lightness_r = std::max(0.0, lightness_r - neg_delta_p);
|
|
Shinya Kitaoka |
120a6e |
lightness_g = std::max(0.0, lightness_g - neg_delta_p);
|
|
Shinya Kitaoka |
120a6e |
lightness_b = std::max(0.0, lightness_b - neg_delta_p);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
val_r = val_g = val_b = val_m = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool insideDst = (x >= 0) && (y >= 0);
|
|
Shinya Kitaoka |
120a6e |
if (insideDst) {
|
|
Shinya Kitaoka |
120a6e |
// Write the corresponding destination pixel
|
|
shun-iwasawa |
255f14 |
if (radius == 0.0) {
|
|
shun-iwasawa |
255f14 |
fac = factor /
|
|
shun-iwasawa |
255f14 |
(rayPos.x *
|
|
shun-iwasawa |
255f14 |
pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay));
|
|
shun-iwasawa |
255f14 |
} else {
|
|
shun-iwasawa |
255f14 |
double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
|
|
shun-iwasawa |
255f14 |
fac =
|
|
shun-iwasawa |
255f14 |
factor /
|
|
shun-iwasawa |
255f14 |
(rayPos.x * ratio *
|
|
shun-iwasawa |
255f14 |
pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) + sq_z),
|
|
shun-iwasawa |
255f14 |
decay));
|
|
shun-iwasawa |
255f14 |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// NOTE: pow() could be slow. If that is the case, it could be cached
|
|
Shinya Kitaoka |
120a6e |
// for the whole octant along the longest ray at integer positions,
|
|
Shinya Kitaoka |
120a6e |
// and then linearly interpolated between those... Have to profile this
|
|
Shinya Kitaoka |
120a6e |
// before resorting to that...
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
val_r += l = (int)(fac * lightness_r + 0.5);
|
|
Shinya Kitaoka |
120a6e |
l_max = l;
|
|
Shinya Kitaoka |
120a6e |
val_g += l = (int)(fac * lightness_g + 0.5);
|
|
Shinya Kitaoka |
120a6e |
l_max = std::max(l, l_max);
|
|
Shinya Kitaoka |
120a6e |
val_b += l = (int)(fac * lightness_b + 0.5);
|
|
Shinya Kitaoka |
120a6e |
l_max = std::max(l, l_max);
|
|
Shinya Kitaoka |
120a6e |
val_m += l_max;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
pixOut->r = (val_r > max) ? max : val_r;
|
|
Shinya Kitaoka |
120a6e |
pixOut->g = (val_g > max) ? max : val_g;
|
|
Shinya Kitaoka |
120a6e |
pixOut->b = (val_b > max) ? max : val_b;
|
|
Shinya Kitaoka |
120a6e |
pixOut->m = (val_m > max) ? max : val_m;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Increment variables along the x-axis
|
|
Shinya Kitaoka |
120a6e |
pixIn += dxIn, pixOut += dxOut;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Increment variables along the y-axis
|
|
Shinya Kitaoka |
120a6e |
if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
|
|
Shinya Kitaoka |
120a6e |
++y, pixIn += dyIn, pixOut += dyOut;
|
|
Shinya Kitaoka |
120a6e |
yIncrementCounter -= yIncrementThreshold;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
// specialization for floating point pixel
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void performColorRaylit<tpixelf>(TPixelF *bufIn, TPixelF *bufOut, int dxIn,</tpixelf>
|
|
shun-iwasawa |
481b59 |
int dyIn, int dxOut, int dyOut,
|
|
shun-iwasawa |
481b59 |
const TRect &srcRect, const TRect &dstRect,
|
|
shun-iwasawa |
481b59 |
const TRop::RaylitParams ¶ms) {
|
|
shun-iwasawa |
481b59 |
// Build colors-related variables
|
|
shun-iwasawa |
481b59 |
float max = TPixelF::maxChannelValue;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
float val_r, val_g, val_b, val_m;
|
|
shun-iwasawa |
481b59 |
double lightness_r, lightness_g, lightness_b;
|
|
shun-iwasawa |
481b59 |
double factor = max / 255.0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// NOTE: These variable initializations are, well,
|
|
shun-iwasawa |
481b59 |
// heuristic at least. They were probably tested
|
|
shun-iwasawa |
481b59 |
// to be good, but didn't quite make any REAL sense.
|
|
shun-iwasawa |
481b59 |
// They could be done MUCH better, but changing them
|
|
shun-iwasawa |
481b59 |
// would alter the way raylit has been applied until now.
|
|
shun-iwasawa |
481b59 |
// Should be changed at some point, though...
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double scale = params.m_scale;
|
|
shun-iwasawa |
481b59 |
double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;
|
|
shun-iwasawa |
481b59 |
double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
|
|
shun-iwasawa |
481b59 |
double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
|
|
shun-iwasawa |
481b59 |
double radius = params.m_radius;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double neg_delta_p =
|
|
shun-iwasawa |
481b59 |
smoothness *
|
|
shun-iwasawa |
481b59 |
intensity; // would alter the way raylit has been applied until now.
|
|
shun-iwasawa |
481b59 |
double quot_delta_p = intensity / max; //
|
|
shun-iwasawa |
481b59 |
// Should be changed at some point, though...
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Geometry-related variables
|
|
shun-iwasawa |
481b59 |
int x, y, ray_final_y;
|
|
shun-iwasawa |
481b59 |
int octLx = dstRect.x1 - dstRect.x0;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double rayPosIncrementX = 1.0 / scale;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double fac, sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square
|
|
shun-iwasawa |
481b59 |
// distances from p, so
|
|
shun-iwasawa |
481b59 |
// square it once now
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Perform raylit
|
|
shun-iwasawa |
481b59 |
TPixelF *pixIn, *pixOut;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
|
|
shun-iwasawa |
481b59 |
// Initialize increment variables
|
|
shun-iwasawa |
481b59 |
lightness_r = lightness_g = lightness_b = 0.0;
|
|
shun-iwasawa |
481b59 |
double l, l_max;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Use an integer counter to know when y must increase. Will add ray_final_y
|
|
shun-iwasawa |
481b59 |
// as long as
|
|
shun-iwasawa |
481b59 |
// a multiple of octLx-1 is reached, then increase
|
|
shun-iwasawa |
481b59 |
int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Trace a single ray of light
|
|
shun-iwasawa |
481b59 |
TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
|
|
shun-iwasawa |
481b59 |
(x < dstRect.x1) && (y < dstRect.y1); ++x) {
|
|
shun-iwasawa |
481b59 |
bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
|
|
shun-iwasawa |
481b59 |
(y >= srcRect.y0) && (y < srcRect.y1);
|
|
shun-iwasawa |
481b59 |
if (insideSrc) {
|
|
shun-iwasawa |
481b59 |
val_r = pixIn->r;
|
|
shun-iwasawa |
481b59 |
val_g = pixIn->g;
|
|
shun-iwasawa |
481b59 |
val_b = pixIn->b;
|
|
shun-iwasawa |
481b59 |
val_m = pixIn->m;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
lightness_r = std::max(0.0, val_r ? lightness_r + val_r * quot_delta_p
|
|
shun-iwasawa |
481b59 |
: lightness_r - neg_delta_p);
|
|
shun-iwasawa |
481b59 |
lightness_g = std::max(0.0, val_g ? lightness_g + val_g * quot_delta_p
|
|
shun-iwasawa |
481b59 |
: lightness_g - neg_delta_p);
|
|
shun-iwasawa |
481b59 |
lightness_b = std::max(0.0, val_b ? lightness_b + val_b * quot_delta_p
|
|
shun-iwasawa |
481b59 |
: lightness_b - neg_delta_p);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
if (!params.m_includeInput) val_r = val_g = val_b = val_m = 0.f;
|
|
shun-iwasawa |
481b59 |
} else {
|
|
shun-iwasawa |
481b59 |
lightness_r = std::max(0.0, lightness_r - neg_delta_p);
|
|
shun-iwasawa |
481b59 |
lightness_g = std::max(0.0, lightness_g - neg_delta_p);
|
|
shun-iwasawa |
481b59 |
lightness_b = std::max(0.0, lightness_b - neg_delta_p);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
val_r = val_g = val_b = val_m = 0.f;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
bool insideDst = (x >= 0) && (y >= 0);
|
|
shun-iwasawa |
481b59 |
if (insideDst) {
|
|
shun-iwasawa |
481b59 |
// Write the corresponding destination pixel
|
|
shun-iwasawa |
481b59 |
if (radius == 0.0) {
|
|
shun-iwasawa |
481b59 |
fac = factor /
|
|
shun-iwasawa |
481b59 |
(rayPos.x *
|
|
shun-iwasawa |
481b59 |
pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay));
|
|
shun-iwasawa |
481b59 |
} else {
|
|
shun-iwasawa |
481b59 |
double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
|
|
shun-iwasawa |
481b59 |
fac =
|
|
shun-iwasawa |
481b59 |
factor /
|
|
shun-iwasawa |
481b59 |
(rayPos.x * ratio *
|
|
shun-iwasawa |
481b59 |
pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) + sq_z),
|
|
shun-iwasawa |
481b59 |
decay));
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// NOTE: pow() could be slow. If that is the case, it could be cached
|
|
shun-iwasawa |
481b59 |
// for the whole octant along the longest ray at integer positions,
|
|
shun-iwasawa |
481b59 |
// and then linearly interpolated between those... Have to profile this
|
|
shun-iwasawa |
481b59 |
// before resorting to that...
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
val_r += l = fac * lightness_r;
|
|
shun-iwasawa |
481b59 |
l_max = l;
|
|
shun-iwasawa |
481b59 |
val_g += l = fac * lightness_g;
|
|
shun-iwasawa |
481b59 |
l_max = std::max(l, l_max);
|
|
shun-iwasawa |
481b59 |
val_b += l = fac * lightness_b;
|
|
shun-iwasawa |
481b59 |
l_max = std::max(l, l_max);
|
|
shun-iwasawa |
481b59 |
val_m += l_max;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
pixOut->r = val_r;
|
|
shun-iwasawa |
481b59 |
pixOut->g = val_g;
|
|
shun-iwasawa |
481b59 |
pixOut->b = val_b;
|
|
shun-iwasawa |
481b59 |
pixOut->m = (val_m > max) ? max : val_m;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Increment variables along the x-axis
|
|
shun-iwasawa |
481b59 |
pixIn += dxIn, pixOut += dxOut;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Increment variables along the y-axis
|
|
shun-iwasawa |
481b59 |
if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
|
|
shun-iwasawa |
481b59 |
++y, pixIn += dyIn, pixOut += dyOut;
|
|
shun-iwasawa |
481b59 |
yIncrementCounter -= yIncrementThreshold;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------------
|
|
shun-iwasawa |
443318 |
/*-- Calculate one of the 8 pizza-shaped regions --*/
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void computeOctant(const TRasterPT<t> &src, const TRasterPT<t> &dst, int octant,</t></t>
|
|
Shinya Kitaoka |
120a6e |
const TRop::RaylitParams ¶ms,
|
|
Shinya Kitaoka |
120a6e |
typename RaylitFuncTraits<t>::function_type raylitFunc) {</t>
|
|
Shinya Kitaoka |
120a6e |
// Build octant geometry variables
|
|
Shinya Kitaoka |
120a6e |
int x0, x1, lxIn, lxOut, dxIn, dxOut;
|
|
Shinya Kitaoka |
120a6e |
int y0, y1, lyIn, lyOut, dyIn, dyOut;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const T3DPoint &pIn = params.m_lightOriginSrc,
|
|
Shinya Kitaoka |
120a6e |
&pOut = params.m_lightOriginDst;
|
|
Shinya Kitaoka |
120a6e |
int srcWrap = src->getWrap(), dstWrap = dst->getWrap();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
T *bufIn = (T *)src->getRawData() + tfloor(pIn.y) * srcWrap + tfloor(pIn.x);
|
|
Shinya Kitaoka |
120a6e |
T *bufOut =
|
|
Shinya Kitaoka |
120a6e |
(T *)dst->getRawData() + tfloor(pOut.y) * dstWrap + tfloor(pOut.x);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRect srcRect(src->getBounds() +
|
|
Shinya Kitaoka |
120a6e |
TPoint(tround(pOut.x - pIn.x), tround(pOut.y - pIn.y)));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
lxIn = src->getLx(), lxOut = dst->getLx();
|
|
Shinya Kitaoka |
120a6e |
lyIn = src->getLy(), lyOut = dst->getLy();
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
443318 |
/*-- Movement value when moving forward by 1 pixel --*/
|
|
Shinya Kitaoka |
120a6e |
// Vertical octant pairs
|
|
Shinya Kitaoka |
120a6e |
if (octant == 1 || octant == 8)
|
|
Shinya Kitaoka |
120a6e |
dxIn = 1, dxOut = 1, x0 = tfloor(pOut.x), x1 = lxOut;
|
|
Shinya Kitaoka |
120a6e |
if (octant == 2 || octant == 7)
|
|
Shinya Kitaoka |
120a6e |
dyIn = 1, dyOut = 1, y0 = tfloor(pOut.x), y1 = lxOut;
|
|
Shinya Kitaoka |
120a6e |
if (octant == 3 || octant == 6)
|
|
Shinya Kitaoka |
120a6e |
dyIn = -1, dyOut = -1, y0 = lxOut - tfloor(pOut.x) - 1, y1 = lxOut,
|
|
otakuto |
ed7dcd |
std::swap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0,
|
|
Shinya Kitaoka |
120a6e |
srcRect.x1 = lxOut - srcRect.x1;
|
|
Shinya Kitaoka |
120a6e |
if (octant == 4 || octant == 5)
|
|
Shinya Kitaoka |
120a6e |
dxIn = -1, dxOut = -1, x0 = lxOut - tfloor(pOut.x) - 1, x1 = lxOut,
|
|
otakuto |
ed7dcd |
std::swap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0,
|
|
Shinya Kitaoka |
120a6e |
srcRect.x1 = lxOut - srcRect.x1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Horizontal octant pairs
|
|
Shinya Kitaoka |
120a6e |
if (octant == 2 || octant == 3)
|
|
Shinya Kitaoka |
120a6e |
dxIn = srcWrap, dxOut = dstWrap, x0 = tfloor(pOut.y), x1 = lyOut;
|
|
Shinya Kitaoka |
120a6e |
if (octant == 1 || octant == 4)
|
|
Shinya Kitaoka |
120a6e |
dyIn = srcWrap, dyOut = dstWrap, y0 = tfloor(pOut.y), y1 = lyOut;
|
|
Shinya Kitaoka |
120a6e |
if (octant == 5 || octant == 8)
|
|
Shinya Kitaoka |
120a6e |
dyIn = -srcWrap, dyOut = -dstWrap, y0 = lyOut - tfloor(pOut.y) - 1,
|
|
shun-iwasawa |
255f14 |
y1 = lyOut, std::swap(srcRect.y0, srcRect.y1),
|
|
shun-iwasawa |
255f14 |
srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1;
|
|
Shinya Kitaoka |
120a6e |
if (octant == 6 || octant == 7)
|
|
Shinya Kitaoka |
120a6e |
dxIn = -srcWrap, dxOut = -dstWrap, x0 = lyOut - tfloor(pOut.y) - 1,
|
|
shun-iwasawa |
255f14 |
x1 = lyOut, std::swap(srcRect.y0, srcRect.y1),
|
|
shun-iwasawa |
255f14 |
srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
443318 |
/*-- To calculate the pizza area in vertical orientation, rotate 90 degrees in
|
|
shun-iwasawa |
443318 |
* advance --*/
|
|
Shinya Kitaoka |
120a6e |
// Swap x and y axis where necessary
|
|
Shinya Kitaoka |
120a6e |
if (octant == 2 || octant == 3 || octant == 6 || octant == 7) {
|
|
otakuto |
ed7dcd |
std::swap(lxIn, lyIn), std::swap(lxOut, lyOut);
|
|
otakuto |
ed7dcd |
std::swap(srcRect.x0, srcRect.y0), std::swap(srcRect.x1, srcRect.y1);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int octLx = (x1 - x0), octLy = (y1 - y0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(octLx > 0 && octLy > 0);
|
|
Shinya Kitaoka |
120a6e |
if (octLx <= 0 && octLy <= 0) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
raylitFunc(bufIn, bufOut, dxIn, dyIn, dxOut, dyOut, srcRect,
|
|
Shinya Kitaoka |
120a6e |
TRect(x0, y0, x1, y1), params);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
OCTANTS:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\ 3 | 2 /
|
|
Toshihiro Shimizu |
890ddd |
\ | /
|
|
Toshihiro Shimizu |
890ddd |
\ | /
|
|
Toshihiro Shimizu |
890ddd |
4 \|/ 1
|
|
Toshihiro Shimizu |
890ddd |
----+----
|
|
Toshihiro Shimizu |
890ddd |
5 /|\ 8
|
|
Toshihiro Shimizu |
890ddd |
/ | \
|
|
Toshihiro Shimizu |
890ddd |
/ | \
|
|
Toshihiro Shimizu |
890ddd |
/ 6 | 7 \
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename t=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void doRaylit(const TRasterPT<t> &src, const TRasterPT<t> &dst,</t></t>
|
|
Shinya Kitaoka |
120a6e |
const TRop::RaylitParams ¶ms,
|
|
Shinya Kitaoka |
120a6e |
typename RaylitFuncTraits<t>::function_type raylitFunc) {</t>
|
|
Shinya Kitaoka |
120a6e |
int lxOut = dst->getLx(), lyOut = dst->getLy();
|
|
Shinya Kitaoka |
120a6e |
const T3DPoint &p = params.m_lightOriginDst;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
src->lock();
|
|
Shinya Kitaoka |
120a6e |
dst->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Depending on the position of p, only some of the quadrants need to be built
|
|
Shinya Kitaoka |
120a6e |
if (p.y < lyOut) {
|
|
Shinya Kitaoka |
120a6e |
if (p.x < lxOut) {
|
|
Shinya Kitaoka |
120a6e |
// Compute the raylit fx on each octant independently
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 1, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 2, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (p.x >= 0) {
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 3, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 4, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (p.y >= 0) {
|
|
Shinya Kitaoka |
120a6e |
if (p.x >= 0) {
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 5, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 6, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (p.x < lxOut) {
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 7, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
computeOctant(src, dst, 8, params, raylitFunc);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
dst->unlock();
|
|
Shinya Kitaoka |
120a6e |
src->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//***********************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// TRop::raylit implementation
|
|
Toshihiro Shimizu |
890ddd |
//***********************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::raylit(const TRasterP &dstRas, const TRasterP &srcRas,
|
|
Shinya Kitaoka |
120a6e |
const RaylitParams ¶ms) {
|
|
Shinya Kitaoka |
120a6e |
if ((TRaster32P)dstRas && (TRaster32P)srcRas)
|
|
Shinya Kitaoka |
120a6e |
doRaylit<tpixel32>(srcRas, dstRas, params,</tpixel32>
|
|
Shinya Kitaoka |
120a6e |
&performStandardRaylit<tpixel32>);</tpixel32>
|
|
Shinya Kitaoka |
120a6e |
else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
|
|
Shinya Kitaoka |
120a6e |
doRaylit<tpixel64>(srcRas, dstRas, params,</tpixel64>
|
|
Shinya Kitaoka |
120a6e |
&performStandardRaylit<tpixel64>);</tpixel64>
|
|
shun-iwasawa |
481b59 |
else if ((TRasterFP)dstRas && (TRasterFP)srcRas)
|
|
shun-iwasawa |
481b59 |
doRaylit<tpixelf>(srcRas, dstRas, params, &performStandardRaylit<tpixelf>);</tpixelf></tpixelf>
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
throw TException("TRop::raylit unsupported pixel type");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::glassRaylit(const TRasterP &dstRas, const TRasterP &srcRas,
|
|
Shinya Kitaoka |
120a6e |
const RaylitParams ¶ms) {
|
|
Shinya Kitaoka |
120a6e |
if ((TRaster32P)dstRas && (TRaster32P)srcRas)
|
|
Shinya Kitaoka |
120a6e |
doRaylit<tpixel32>(srcRas, dstRas, params, &performColorRaylit<tpixel32>);</tpixel32></tpixel32>
|
|
Shinya Kitaoka |
120a6e |
else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
|
|
Shinya Kitaoka |
120a6e |
doRaylit<tpixel64>(srcRas, dstRas, params, &performColorRaylit<tpixel64>);</tpixel64></tpixel64>
|
|
shun-iwasawa |
481b59 |
else if ((TRasterFP)dstRas && (TRasterFP)srcRas)
|
|
shun-iwasawa |
481b59 |
doRaylit<tpixelf>(srcRas, dstRas, params, &performColorRaylit<tpixelf>);</tpixelf></tpixelf>
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
throw TException("TRop::raylit unsupported pixel type");
|
|
Toshihiro Shimizu |
890ddd |
}
|