|
Toshihiro Shimizu |
890ddd |
/*------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
Iwa_MotionBlurCompFx
|
|
shun-iwasawa |
4f5900 |
Motion blur fx considering the exposure of light and trajectory of the object.
|
|
shun-iwasawa |
4f5900 |
Available to composite exposure value with background.
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "iwa_motionblurfx.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tfxattributes.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tstageobject.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
4f5900 |
/* Normalize the source image to 0 - 1 and read it into the host memory.
|
|
shun-iwasawa |
4f5900 |
* Check if the source image is premultiped or not here, if it is not specified
|
|
shun-iwasawa |
4f5900 |
* in the combo box. */
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixel="" raster,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
bool Iwa_MotionBlurCompFx::setSourceRaster(const RASTER srcRas, float4 *dstMem,
|
|
Shinya Kitaoka |
120a6e |
TDimensionI dim,
|
|
Shinya Kitaoka |
120a6e |
PremultiTypes type) {
|
|
Shinya Kitaoka |
120a6e |
bool isPremultiplied = (type == SOURCE_IS_NOT_PREMUTIPLIED) ? false : true;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
float4 *chann_p = dstMem;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
float threshold = 100.0 / (float)TPixel64::maxChannelValue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int max = 0;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < dim.ly; j++) {
|
|
Shinya Kitaoka |
120a6e |
PIXEL *pix = srcRas->pixels(j);
|
|
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 |
|
|
Campbell Barton |
d3ecc4 |
/* If there are pixels whose RGB values are larger than the alpha
|
|
shun-iwasawa |
4f5900 |
* channel, determine the source is not premutiplied */
|
|
shun-iwasawa |
481b59 |
// CAUTION: this condition won't work properly ith HDR image pixels!
|
|
Shinya Kitaoka |
120a6e |
if (type == AUTO && isPremultiplied &&
|
|
Shinya Kitaoka |
120a6e |
(((*chann_p).x > (*chann_p).w && (*chann_p).x > threshold) ||
|
|
Shinya Kitaoka |
120a6e |
((*chann_p).y > (*chann_p).w && (*chann_p).y > threshold) ||
|
|
Shinya Kitaoka |
120a6e |
((*chann_p).z > (*chann_p).w && (*chann_p).z > threshold)))
|
|
Shinya Kitaoka |
120a6e |
isPremultiplied = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
pix++;
|
|
Shinya Kitaoka |
120a6e |
chann_p++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isPremultiplied) {
|
|
Shinya Kitaoka |
120a6e |
chann_p = dstMem;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < dim.lx * dim.ly; i++, chann_p++) {
|
|
Shinya Kitaoka |
120a6e |
if ((*chann_p).x > (*chann_p).w) (*chann_p).x = (*chann_p).w;
|
|
Shinya Kitaoka |
120a6e |
if ((*chann_p).y > (*chann_p).w) (*chann_p).y = (*chann_p).w;
|
|
Shinya Kitaoka |
120a6e |
if ((*chann_p).z > (*chann_p).w) (*chann_p).z = (*chann_p).w;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return isPremultiplied;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
Campbell Barton |
d3ecc4 |
Convert output result to Channel value and store it in the tile
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixel="" raster,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::setOutputRaster(float4 *srcMem, const RASTER dstRas,
|
|
Shinya Kitaoka |
120a6e |
TDimensionI dim, int2 margin) {
|
|
Shinya Kitaoka |
120a6e |
int out_j = 0;
|
|
Shinya Kitaoka |
120a6e |
for (int j = margin.y; j < dstRas->getLy() + margin.y; j++, out_j++) {
|
|
Shinya Kitaoka |
120a6e |
PIXEL *pix = dstRas->pixels(out_j);
|
|
Shinya Kitaoka |
120a6e |
float4 *chan_p = srcMem;
|
|
Shinya Kitaoka |
120a6e |
chan_p += j * dim.lx + margin.x;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < dstRas->getLx(); i++) {
|
|
Shinya Kitaoka |
120a6e |
float val;
|
|
Shinya Kitaoka |
120a6e |
val = (*chan_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 = (*chan_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 = (*chan_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 = (*chan_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 |
chan_p++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
template <>
|
|
shun-iwasawa |
481b59 |
void Iwa_MotionBlurCompFx::setOutputRaster<trasterfp, tpixelf="">(</trasterfp,>
|
|
shun-iwasawa |
481b59 |
float4 *srcMem, const TRasterFP dstRas, TDimensionI dim, int2 margin) {
|
|
shun-iwasawa |
481b59 |
int out_j = 0;
|
|
shun-iwasawa |
481b59 |
for (int j = margin.y; j < dstRas->getLy() + margin.y; j++, out_j++) {
|
|
shun-iwasawa |
481b59 |
TPixelF *pix = dstRas->pixels(out_j);
|
|
shun-iwasawa |
481b59 |
float4 *chan_p = srcMem;
|
|
shun-iwasawa |
481b59 |
chan_p += j * dim.lx + margin.x;
|
|
shun-iwasawa |
481b59 |
for (int i = 0; i < dstRas->getLx(); i++) {
|
|
shun-iwasawa |
481b59 |
pix->r = (*chan_p).x;
|
|
shun-iwasawa |
481b59 |
pix->g = (*chan_p).y;
|
|
shun-iwasawa |
481b59 |
pix->b = (*chan_p).z;
|
|
shun-iwasawa |
481b59 |
pix->m = (*chan_p).w;
|
|
shun-iwasawa |
481b59 |
pix++;
|
|
shun-iwasawa |
481b59 |
chan_p++;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
Campbell Barton |
d3ecc4 |
Create and normalize filters
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::makeMotionBlurFilter_CPU(
|
|
Shinya Kitaoka |
120a6e |
float *filter_p, TDimensionI &filterDim, int marginLeft, int marginBottom,
|
|
Shinya Kitaoka |
120a6e |
float4 *pointsTable, int pointAmount, float startValue, float startCurve,
|
|
Shinya Kitaoka |
120a6e |
float endValue, float endCurve) {
|
|
shun-iwasawa |
4f5900 |
/* Variable for adding filter value*/
|
|
Shinya Kitaoka |
120a6e |
float fil_val_sum = 0.0f;
|
|
shun-iwasawa |
4f5900 |
/* The current filter position to be looped in the 'for' statement */
|
|
Shinya Kitaoka |
120a6e |
float *current_fil_p = filter_p;
|
|
shun-iwasawa |
4f5900 |
/* For each coordinate in the filter */
|
|
Shinya Kitaoka |
120a6e |
for (int fily = 0; fily < filterDim.ly; fily++) {
|
|
Shinya Kitaoka |
120a6e |
for (int filx = 0; filx < filterDim.lx; filx++, current_fil_p++) {
|
|
Campbell Barton |
d3ecc4 |
/* Get filter coordinates */
|
|
Shinya Kitaoka |
120a6e |
float2 pos = {static_cast<float>(filx - marginLeft),</float>
|
|
Shinya Kitaoka |
120a6e |
static_cast<float>(fily - marginBottom)};</float>
|
|
shun-iwasawa |
4f5900 |
/* Value to be updated */
|
|
Shinya Kitaoka |
120a6e |
float nearestDist2 = 100.0f;
|
|
Shinya Kitaoka |
120a6e |
int nearestIndex = -1;
|
|
Shinya Kitaoka |
120a6e |
float nearestFramePosRatio = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Find the nearest point for each pair of sample points */
|
|
Shinya Kitaoka |
120a6e |
for (int v = 0; v < pointAmount - 1; v++) {
|
|
Shinya Kitaoka |
120a6e |
float4 p0 = pointsTable[v];
|
|
Shinya Kitaoka |
120a6e |
float4 p1 = pointsTable[v + 1];
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* If it is not within the range, continue */
|
|
Shinya Kitaoka |
120a6e |
if (pos.x < std::min(p0.x, p1.x) - 1.0f ||
|
|
Shinya Kitaoka |
120a6e |
pos.x > std::max(p0.x, p1.x) + 1.0f ||
|
|
Shinya Kitaoka |
120a6e |
pos.y < std::min(p0.y, p1.y) - 1.0f ||
|
|
Shinya Kitaoka |
120a6e |
pos.y > std::max(p0.y, p1.y) + 1.0f)
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Since it is within the range, obtain the distance between the line
|
|
Campbell Barton |
d3ecc4 |
* segment and the point. */
|
|
shun-iwasawa |
4f5900 |
/* Calculate the inner product of 'p0'->sampling point and 'p0'->'p1' */
|
|
Shinya Kitaoka |
120a6e |
float2 vec_p0_sample = {static_cast<float>(pos.x - p0.x),</float>
|
|
Shinya Kitaoka |
120a6e |
static_cast<float>(pos.y - p0.y)};</float>
|
|
shun-iwasawa |
481b59 |
float2 vec_p0_p1 = {static_cast<float>(p1.x - p0.x),</float>
|
|
shun-iwasawa |
481b59 |
static_cast<float>(p1.y - p0.y)};</float>
|
|
Shinya Kitaoka |
120a6e |
float dot =
|
|
Shinya Kitaoka |
120a6e |
vec_p0_sample.x * vec_p0_p1.x + vec_p0_sample.y * vec_p0_p1.y;
|
|
shun-iwasawa |
4f5900 |
/* Calculate the square of distance */
|
|
Shinya Kitaoka |
120a6e |
float dist2;
|
|
Shinya Kitaoka |
120a6e |
float framePosRatio;
|
|
shun-iwasawa |
4f5900 |
/* If it is before 'p0' */
|
|
Shinya Kitaoka |
120a6e |
if (dot <= 0.0f) {
|
|
Shinya Kitaoka |
120a6e |
dist2 = vec_p0_sample.x * vec_p0_sample.x +
|
|
Shinya Kitaoka |
120a6e |
vec_p0_sample.y * vec_p0_sample.y;
|
|
Shinya Kitaoka |
120a6e |
framePosRatio = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Campbell Barton |
d3ecc4 |
/* Calculate the square of the length of the trajectory vector */
|
|
Shinya Kitaoka |
120a6e |
float length2 = p0.z * p0.z;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* If it is between 'p0' and 'p1'
|
|
shun-iwasawa |
4f5900 |
* If the trajectory at p is a point,
|
|
shun-iwasawa |
4f5900 |
* 'length2' becomes 0, so it will never fall into this condition.
|
|
Campbell Barton |
d3ecc4 |
* So, there should not be worry of becoming ZeroDivide. */
|
|
Shinya Kitaoka |
120a6e |
if (dot < length2) {
|
|
Shinya Kitaoka |
120a6e |
float p0_sample_dist2 = vec_p0_sample.x * vec_p0_sample.x +
|
|
Shinya Kitaoka |
120a6e |
vec_p0_sample.y * vec_p0_sample.y;
|
|
Shinya Kitaoka |
120a6e |
dist2 = p0_sample_dist2 - dot * dot / length2;
|
|
Shinya Kitaoka |
120a6e |
framePosRatio = dot / length2;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
4f5900 |
/* If it is before 'p1' */
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
float2 vec_p1_sample = {pos.x - p1.x, pos.y - p1.y};
|
|
Shinya Kitaoka |
120a6e |
dist2 = vec_p1_sample.x * vec_p1_sample.x +
|
|
Shinya Kitaoka |
120a6e |
vec_p1_sample.y * vec_p1_sample.y;
|
|
Shinya Kitaoka |
120a6e |
framePosRatio = 1.0f;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Campbell Barton |
d3ecc4 |
/* If the distance is farther than (√ 2 + 1) / 2, continue
|
|
shun-iwasawa |
4f5900 |
* Because it is a comparison with dist2, the value is squared */
|
|
Shinya Kitaoka |
120a6e |
if (dist2 > 1.4571f) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Update if distance is closer */
|
|
Shinya Kitaoka |
120a6e |
if (dist2 < nearestDist2) {
|
|
Shinya Kitaoka |
120a6e |
nearestDist2 = dist2;
|
|
Shinya Kitaoka |
120a6e |
nearestIndex = v;
|
|
Shinya Kitaoka |
120a6e |
nearestFramePosRatio = framePosRatio;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* If neighborhood vector of the current pixel can not be found,
|
|
shun-iwasawa |
4f5900 |
* set the filter value to 0 and return */
|
|
Shinya Kitaoka |
120a6e |
if (nearestIndex == -1) {
|
|
Shinya Kitaoka |
120a6e |
*current_fil_p = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Count how many subpixels (16 * 16) of the current pixel
|
|
shun-iwasawa |
4f5900 |
* are in the range 0.5 from the neighborhood vector.
|
|
Campbell Barton |
d3ecc4 |
*/
|
|
Shinya Kitaoka |
120a6e |
int count = 0;
|
|
Shinya Kitaoka |
120a6e |
float4 np0 = pointsTable[nearestIndex];
|
|
Shinya Kitaoka |
120a6e |
float4 np1 = pointsTable[nearestIndex + 1];
|
|
Shinya Kitaoka |
120a6e |
for (int yy = 0; yy < 16; yy++) {
|
|
shun-iwasawa |
4f5900 |
/* Y coordinate of the subpixel */
|
|
Shinya Kitaoka |
120a6e |
float subPosY = pos.y + ((float)yy - 7.5f) / 16.0f;
|
|
Shinya Kitaoka |
120a6e |
for (int xx = 0; xx < 16; xx++) {
|
|
shun-iwasawa |
4f5900 |
/* X coordinate of the subpixel */
|
|
Shinya Kitaoka |
120a6e |
float subPosX = pos.x + ((float)xx - 7.5f) / 16.0f;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
float2 vec_np0_sub = {subPosX - np0.x, subPosY - np0.y};
|
|
Shinya Kitaoka |
120a6e |
float2 vec_np0_np1 = {np1.x - np0.x, np1.y - np0.y};
|
|
Shinya Kitaoka |
120a6e |
float dot =
|
|
Shinya Kitaoka |
120a6e |
vec_np0_sub.x * vec_np0_np1.x + vec_np0_sub.y * vec_np0_np1.y;
|
|
shun-iwasawa |
4f5900 |
/* Calculate the square of the distance */
|
|
Shinya Kitaoka |
120a6e |
float dist2;
|
|
shun-iwasawa |
4f5900 |
/* If it is before 'p0' */
|
|
Shinya Kitaoka |
120a6e |
if (dot <= 0.0f)
|
|
Shinya Kitaoka |
120a6e |
dist2 =
|
|
Shinya Kitaoka |
120a6e |
vec_np0_sub.x * vec_np0_sub.x + vec_np0_sub.y * vec_np0_sub.y;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Campbell Barton |
d3ecc4 |
/* Compute the square of the length of the trajectory vector */
|
|
Shinya Kitaoka |
120a6e |
float length2 = np0.z * np0.z;
|
|
shun-iwasawa |
4f5900 |
/* If it is between 'p0' and 'p1' */
|
|
Shinya Kitaoka |
120a6e |
if (dot < length2) {
|
|
Shinya Kitaoka |
120a6e |
float np0_sub_dist2 =
|
|
Shinya Kitaoka |
120a6e |
vec_np0_sub.x * vec_np0_sub.x + vec_np0_sub.y * vec_np0_sub.y;
|
|
Shinya Kitaoka |
120a6e |
dist2 = np0_sub_dist2 - dot * dot / length2;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Campbell Barton |
d3ecc4 |
/* if it is before 'p1' */
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
float2 vec_np1_sub = {subPosX - np1.x, subPosY - np1.y};
|
|
Shinya Kitaoka |
120a6e |
dist2 =
|
|
Shinya Kitaoka |
120a6e |
vec_np1_sub.x * vec_np1_sub.x + vec_np1_sub.y * vec_np1_sub.y;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
4f5900 |
/* Increment count if squared distance is less than 0.25 */
|
|
Shinya Kitaoka |
120a6e |
if (dist2 <= 0.25f) count++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
4f5900 |
/* 'safeguard' - If the count is 0, set the field value to 0 and return.
|
|
shun-iwasawa |
4f5900 |
*/
|
|
Shinya Kitaoka |
120a6e |
if (count == 0) {
|
|
Shinya Kitaoka |
120a6e |
*current_fil_p = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Count is 256 at a maximum */
|
|
Shinya Kitaoka |
120a6e |
float countRatio = (float)count / 256.0f;
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* The brightness of the filter value is inversely proportional
|
|
Campbell Barton |
d3ecc4 |
* to the area of the line of width 1 made by the vector.
|
|
Campbell Barton |
d3ecc4 |
*
|
|
Campbell Barton |
d3ecc4 |
* Since there are semicircular caps with radius 0.5
|
|
shun-iwasawa |
4f5900 |
* before and after the vector, it will never be 0-divide
|
|
shun-iwasawa |
4f5900 |
* even if the length of vector is 0.
|
|
Campbell Barton |
d3ecc4 |
*/
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Area of the neighborhood vector when width = 1 */
|
|
Shinya Kitaoka |
120a6e |
float vecMenseki = 0.25f * 3.14159265f + np0.z;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//-----------------
|
|
Campbell Barton |
d3ecc4 |
/* Next, get the value of the gamma strength */
|
|
Campbell Barton |
d3ecc4 |
/* Offset value of the frame of the neighbor point */
|
|
Shinya Kitaoka |
120a6e |
float curveValue;
|
|
Shinya Kitaoka |
120a6e |
float frameOffset =
|
|
Shinya Kitaoka |
120a6e |
np0.w * (1.0f - nearestFramePosRatio) + np1.w * nearestFramePosRatio;
|
|
Campbell Barton |
d3ecc4 |
/* If the frame is exactly at the frame origin,
|
|
shun-iwasawa |
4f5900 |
* or there is no attenuation value, set curveValue to 1 */
|
|
Shinya Kitaoka |
120a6e |
if (frameOffset == 0.0f || (frameOffset < 0.0f && startValue == 1.0f) ||
|
|
Shinya Kitaoka |
120a6e |
(frameOffset > 0.0f && endValue == 1.0f))
|
|
Shinya Kitaoka |
120a6e |
curveValue = 1.0f;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Campbell Barton |
d3ecc4 |
/* Change according to positive / negative of offset */
|
|
Shinya Kitaoka |
120a6e |
float value, curve, ratio;
|
|
Campbell Barton |
d3ecc4 |
if (frameOffset < 0.0f) /* Start side */
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
value = startValue;
|
|
Shinya Kitaoka |
120a6e |
curve = startCurve;
|
|
Shinya Kitaoka |
120a6e |
ratio = 1.0f - (frameOffset / pointsTable[0].w);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
value = endValue;
|
|
Shinya Kitaoka |
120a6e |
curve = endCurve;
|
|
Shinya Kitaoka |
120a6e |
ratio = 1.0f - (frameOffset / pointsTable[pointAmount - 1].w);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
curveValue = value + (1.0f - value) * powf(ratio, 1.0f / curve);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
//-----------------
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Store field value */
|
|
Shinya Kitaoka |
120a6e |
*current_fil_p = curveValue * countRatio / vecMenseki;
|
|
Shinya Kitaoka |
120a6e |
fil_val_sum += *current_fil_p;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Normalization */
|
|
Shinya Kitaoka |
120a6e |
current_fil_p = filter_p;
|
|
Shinya Kitaoka |
120a6e |
for (int f = 0; f < filterDim.lx * filterDim.ly; f++, current_fil_p++) {
|
|
Shinya Kitaoka |
120a6e |
*current_fil_p /= fil_val_sum;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
Campbell Barton |
d3ecc4 |
Create afterimage filter and normalize
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::makeZanzoFilter_CPU(
|
|
Shinya Kitaoka |
120a6e |
float *filter_p, TDimensionI &filterDim, int marginLeft, int marginBottom,
|
|
Shinya Kitaoka |
120a6e |
float4 *pointsTable, int pointAmount, float startValue, float startCurve,
|
|
Shinya Kitaoka |
120a6e |
float endValue, float endCurve) {
|
|
Campbell Barton |
d3ecc4 |
/* Variable for adding filter value */
|
|
Shinya Kitaoka |
120a6e |
float fil_val_sum = 0.0f;
|
|
shun-iwasawa |
4f5900 |
/* The current filter position to be looped in the 'for' statement */
|
|
Shinya Kitaoka |
120a6e |
float *current_fil_p = filter_p;
|
|
shun-iwasawa |
4f5900 |
/* For each coordinate in the filter */
|
|
Shinya Kitaoka |
120a6e |
for (int fily = 0; fily < filterDim.ly; fily++) {
|
|
Shinya Kitaoka |
120a6e |
for (int filx = 0; filx < filterDim.lx; filx++, current_fil_p++) {
|
|
Campbell Barton |
d3ecc4 |
/* Get filter coordinates */
|
|
Shinya Kitaoka |
120a6e |
float2 pos = {(float)(filx - marginLeft), (float)(fily - marginBottom)};
|
|
shun-iwasawa |
4f5900 |
/* Variable to be accumulated */
|
|
Shinya Kitaoka |
120a6e |
float filter_sum = 0.0f;
|
|
shun-iwasawa |
4f5900 |
/* Measure the distance for each sample point and accumulate the density
|
|
shun-iwasawa |
4f5900 |
*/
|
|
Shinya Kitaoka |
120a6e |
for (int v = 0; v < pointAmount; v++) {
|
|
Shinya Kitaoka |
120a6e |
float4 p0 = pointsTable[v];
|
|
Campbell Barton |
d3ecc4 |
/* If it is not within the distance 1 around the coordinates of 'p0',
|
|
Campbell Barton |
d3ecc4 |
* continue */
|
|
Shinya Kitaoka |
120a6e |
if (pos.x < p0.x - 1.0f || pos.x > p0.x + 1.0f || pos.y < p0.y - 1.0f ||
|
|
Shinya Kitaoka |
120a6e |
pos.y > p0.y + 1.0f)
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Linear interpolation with 4 neighboring pixels */
|
|
Rozhuk Ivan |
823a31 |
float xRatio = 1.0f - std::abs(pos.x - p0.x);
|
|
Rozhuk Ivan |
823a31 |
float yRatio = 1.0f - std::abs(pos.y - p0.y);
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Next, get the value of the gamma strength */
|
|
Campbell Barton |
d3ecc4 |
/* Offset value of the frame of the neighbor point */
|
|
Shinya Kitaoka |
120a6e |
float curveValue;
|
|
Shinya Kitaoka |
120a6e |
float frameOffset = p0.w;
|
|
Campbell Barton |
d3ecc4 |
/* If the frame is exactly at the frame origin,
|
|
shun-iwasawa |
481b59 |
* or there is no attenuation value, set curveValue to 1 */
|
|
Shinya Kitaoka |
120a6e |
if (frameOffset == 0.0f || (frameOffset < 0.0f && startValue == 1.0f) ||
|
|
Shinya Kitaoka |
120a6e |
(frameOffset > 0.0f && endValue == 1.0f))
|
|
Shinya Kitaoka |
120a6e |
curveValue = 1.0f;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Campbell Barton |
d3ecc4 |
/* Change according to positive / negative of offset */
|
|
Shinya Kitaoka |
120a6e |
float value, curve, ratio;
|
|
Campbell Barton |
d3ecc4 |
if (frameOffset < 0.0f) /* Start side */
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
value = startValue;
|
|
Shinya Kitaoka |
120a6e |
curve = startCurve;
|
|
Shinya Kitaoka |
120a6e |
ratio = 1.0f - (frameOffset / pointsTable[0].w);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
value = endValue;
|
|
Shinya Kitaoka |
120a6e |
curve = endCurve;
|
|
Shinya Kitaoka |
120a6e |
ratio = 1.0f - (frameOffset / pointsTable[pointAmount - 1].w);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
curveValue = value + (1.0f - value) * powf(ratio, 1.0f / curve);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
//-----------------
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Filter value integration */
|
|
Shinya Kitaoka |
120a6e |
filter_sum += xRatio * yRatio * curveValue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Store value */
|
|
Shinya Kitaoka |
120a6e |
*current_fil_p = filter_sum;
|
|
Shinya Kitaoka |
120a6e |
fil_val_sum += *current_fil_p;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Normalization */
|
|
Shinya Kitaoka |
120a6e |
current_fil_p = filter_p;
|
|
Shinya Kitaoka |
120a6e |
for (int f = 0; f < filterDim.lx * filterDim.ly; f++, current_fil_p++) {
|
|
Shinya Kitaoka |
120a6e |
*current_fil_p /= fil_val_sum;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
shun-iwasawa |
4f5900 |
Unpremultiply -> convert to exposure value -> premultiply
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::convertRGBtoExposure_CPU(
|
|
shun-iwasawa |
481b59 |
float4 *in_tile_p, TDimensionI &dim, const ExposureConverter &conv,
|
|
Shinya Kitaoka |
120a6e |
bool sourceIsPremultiplied) {
|
|
Shinya Kitaoka |
120a6e |
float4 *cur_tile_p = in_tile_p;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < dim.lx * dim.ly; i++, cur_tile_p++) {
|
|
shun-iwasawa |
4f5900 |
/* if alpha is 0, return */
|
|
Shinya Kitaoka |
120a6e |
if (cur_tile_p->w == 0.0f) {
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->x = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->y = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->z = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Unpremultiply on sources that are premultiplied, such as regular Level.
|
|
shun-iwasawa |
4f5900 |
* It is not done for 'digital overlay' (image with alpha mask added by
|
|
shun-iwasawa |
4f5900 |
* using Photoshop, as known as 'DigiBook' in Japanese animation industry)
|
|
shun-iwasawa |
4f5900 |
* etc. */
|
|
Shinya Kitaoka |
120a6e |
if (sourceIsPremultiplied) {
|
|
shun-iwasawa |
4f5900 |
/* unpremultiply */
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->x /= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->y /= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->z /= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* convert RGB to Exposure */
|
|
shun-iwasawa |
481b59 |
cur_tile_p->x = conv.valueToExposure(cur_tile_p->x);
|
|
shun-iwasawa |
481b59 |
cur_tile_p->y = conv.valueToExposure(cur_tile_p->y);
|
|
shun-iwasawa |
481b59 |
cur_tile_p->z = conv.valueToExposure(cur_tile_p->z);
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Then multiply with the alpha channel */
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->x *= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->y *= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->z *= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
Campbell Barton |
d3ecc4 |
Filter and blur exposure values
|
|
shun-iwasawa |
4f5900 |
Loop for the range of 'outDim'.
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::applyBlurFilter_CPU(
|
|
Shinya Kitaoka |
120a6e |
float4 *in_tile_p, float4 *out_tile_p, TDimensionI &enlargedDim,
|
|
Shinya Kitaoka |
120a6e |
float *filter_p, TDimensionI &filterDim, int marginLeft, int marginBottom,
|
|
Shinya Kitaoka |
120a6e |
int marginRight, int marginTop, TDimensionI &outDim) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < outDim.lx * outDim.ly; i++) {
|
|
Campbell Barton |
d3ecc4 |
/* in_tile_dev and out_tile_dev contain data with dimensions lx * ly.
|
|
shun-iwasawa |
4f5900 |
* So, convert i to coordinates for output. */
|
|
Shinya Kitaoka |
120a6e |
int2 outPos = {i % outDim.lx + marginRight, i / outDim.lx + marginTop};
|
|
Shinya Kitaoka |
120a6e |
int outIndex = outPos.y * enlargedDim.lx + outPos.x;
|
|
Campbell Barton |
d3ecc4 |
/* put the result in out_tile_dev [outIndex] */
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Prepare a container to accumulate values - */
|
|
Shinya Kitaoka |
120a6e |
float4 value = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Loop by filter size.
|
|
shun-iwasawa |
4f5900 |
* Note that the filter is used to 'collect' pixels at sample points
|
|
shun-iwasawa |
4f5900 |
* so flip the filter vertically and horizontally and sample it */
|
|
Shinya Kitaoka |
120a6e |
int filterIndex = 0;
|
|
Shinya Kitaoka |
120a6e |
for (int fily = -marginBottom; fily < filterDim.ly - marginBottom; fily++) {
|
|
shun-iwasawa |
4f5900 |
/* Sample coordinates and index of the end of this scan line */
|
|
Shinya Kitaoka |
120a6e |
int2 samplePos = {outPos.x + marginLeft, outPos.y - fily};
|
|
Shinya Kitaoka |
120a6e |
int sampleIndex = samplePos.y * enlargedDim.lx + samplePos.x;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int filx = -marginLeft; filx < filterDim.lx - marginLeft;
|
|
Shinya Kitaoka |
120a6e |
filx++, filterIndex++, sampleIndex--) {
|
|
shun-iwasawa |
4f5900 |
/* If the filter value is 0 or the sample pixel is transparent, continue
|
|
Campbell Barton |
d3ecc4 |
*/
|
|
Shinya Kitaoka |
120a6e |
if (filter_p[filterIndex] == 0.0f || in_tile_p[sampleIndex].w == 0.0f)
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Campbell Barton |
d3ecc4 |
/* multiply the sample point value by the filter value and integrate */
|
|
Shinya Kitaoka |
120a6e |
value.x += in_tile_p[sampleIndex].x * filter_p[filterIndex];
|
|
Shinya Kitaoka |
120a6e |
value.y += in_tile_p[sampleIndex].y * filter_p[filterIndex];
|
|
Shinya Kitaoka |
120a6e |
value.z += in_tile_p[sampleIndex].z * filter_p[filterIndex];
|
|
Shinya Kitaoka |
120a6e |
value.w += in_tile_p[sampleIndex].w * filter_p[filterIndex];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
out_tile_p[outIndex].x = value.x;
|
|
Shinya Kitaoka |
120a6e |
out_tile_p[outIndex].y = value.y;
|
|
Shinya Kitaoka |
120a6e |
out_tile_p[outIndex].z = value.z;
|
|
Shinya Kitaoka |
120a6e |
out_tile_p[outIndex].w = value.w;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
shun-iwasawa |
4f5900 |
Unpremultiply the exposure value
|
|
shun-iwasawa |
4f5900 |
-> convert back to RGB value (0 to 1)
|
|
shun-iwasawa |
4f5900 |
-> premultiply
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
void Iwa_MotionBlurCompFx::convertExposureToRGB_CPU(
|
|
shun-iwasawa |
481b59 |
float4 *out_tile_p, TDimensionI &dim, const ExposureConverter &conv) {
|
|
Shinya Kitaoka |
120a6e |
float4 *cur_tile_p = out_tile_p;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < dim.lx * dim.ly; i++, cur_tile_p++) {
|
|
Campbell Barton |
d3ecc4 |
/* if alpha is 0 return */
|
|
Shinya Kitaoka |
120a6e |
if (cur_tile_p->w == 0.0f) {
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->x = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->y = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->z = 0.0f;
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
// unpremultiply
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->x /= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->y /= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->z /= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Convert Exposure to RGB value */
|
|
shun-iwasawa |
481b59 |
cur_tile_p->x = conv.exposureToValue(cur_tile_p->x);
|
|
shun-iwasawa |
481b59 |
cur_tile_p->y = conv.exposureToValue(cur_tile_p->y);
|
|
shun-iwasawa |
481b59 |
cur_tile_p->z = conv.exposureToValue(cur_tile_p->z);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// multiply
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->x *= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->y *= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
cur_tile_p->z *= cur_tile_p->w;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
shun-iwasawa |
4f5900 |
If there is a background, and the foreground does not move, simply over
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::composeWithNoMotion(
|
|
Shinya Kitaoka |
120a6e |
TTile &tile, double frame, const TRenderSettings &settings) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_background.isConnected());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_background->compute(tile, frame, settings);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TTile fore_tile;
|
|
Shinya Kitaoka |
120a6e |
m_input->allocateAndCompute(fore_tile, tile.m_pos,
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster()->getSize(), tile.getRaster(),
|
|
Shinya Kitaoka |
120a6e |
frame, settings);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterP up(fore_tile.getRaster()), down(tile.getRaster());
|
|
Shinya Kitaoka |
120a6e |
TRop::over(down, up);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
shun-iwasawa |
4f5900 |
Convert background to exposure value and over it
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::composeBackgroundExposure_CPU(
|
|
Shinya Kitaoka |
120a6e |
float4 *out_tile_p, TDimensionI &enlargedDimIn, int marginRight,
|
|
shun-iwasawa |
481b59 |
int marginTop, TTile &back_tile, TDimensionI &dimOut,
|
|
shun-iwasawa |
481b59 |
const ExposureConverter &conv) {
|
|
Campbell Barton |
d3ecc4 |
/* Memory allocation of host */
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P background_host_ras(sizeof(float4) * dimOut.lx, dimOut.ly);
|
|
Shinya Kitaoka |
120a6e |
background_host_ras->lock();
|
|
Shinya Kitaoka |
120a6e |
float4 *background_host = (float4 *)background_host_ras->getRawData();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool bgIsPremultiplied;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* normalize the background image to 0 - 1 and read it into the host memory
|
|
Campbell Barton |
d3ecc4 |
*/
|
|
Shinya Kitaoka |
120a6e |
TRaster32P backRas32 = (TRaster32P)back_tile.getRaster();
|
|
Shinya Kitaoka |
120a6e |
TRaster64P backRas64 = (TRaster64P)back_tile.getRaster();
|
|
shun-iwasawa |
481b59 |
TRasterFP backRasF = (TRasterFP)back_tile.getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (backRas32)
|
|
Shinya Kitaoka |
120a6e |
bgIsPremultiplied = setSourceRaster<traster32p, tpixel32="">(</traster32p,>
|
|
Shinya Kitaoka |
120a6e |
backRas32, background_host, dimOut);
|
|
Shinya Kitaoka |
120a6e |
else if (backRas64)
|
|
Shinya Kitaoka |
120a6e |
bgIsPremultiplied = setSourceRaster<traster64p, tpixel64="">(</traster64p,>
|
|
Shinya Kitaoka |
120a6e |
backRas64, background_host, dimOut);
|
|
shun-iwasawa |
481b59 |
else if (backRasF)
|
|
shun-iwasawa |
481b59 |
bgIsPremultiplied =
|
|
shun-iwasawa |
481b59 |
setSourceRaster<trasterfp, tpixelf="">(backRasF, background_host, dimOut);</trasterfp,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
float4 *bg_p = background_host;
|
|
Shinya Kitaoka |
120a6e |
float4 *out_p;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < dimOut.ly; j++) {
|
|
Shinya Kitaoka |
120a6e |
out_p = out_tile_p + ((marginTop + j) * enlargedDimIn.lx + marginRight);
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < dimOut.lx; i++, bg_p++, out_p++) {
|
|
Campbell Barton |
d3ecc4 |
/* if upper layer is completely opaque continue */
|
|
Shinya Kitaoka |
120a6e |
if ((*out_p).w >= 1.0f) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* even if the lower layer is completely transparent continue */
|
|
Shinya Kitaoka |
120a6e |
if ((*bg_p).w < 0.0001f) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
float3 bgExposure = {(*bg_p).x, (*bg_p).y, (*bg_p).z};
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Unpremultiply on sources that are premultiplied, such as regular Level.
|
|
shun-iwasawa |
4f5900 |
* It is not done for 'digital overlay' (image with alpha mask added by
|
|
shun-iwasawa |
4f5900 |
* using Photoshop, as known as 'DigiBook' in Japanese animation industry)
|
|
shun-iwasawa |
4f5900 |
* etc.
|
|
shun-iwasawa |
481b59 |
*/
|
|
Shinya Kitaoka |
120a6e |
if (bgIsPremultiplied) {
|
|
shun-iwasawa |
4f5900 |
// Unpremultiply
|
|
Shinya Kitaoka |
120a6e |
bgExposure.x /= (*bg_p).w;
|
|
Shinya Kitaoka |
120a6e |
bgExposure.y /= (*bg_p).w;
|
|
Shinya Kitaoka |
120a6e |
bgExposure.z /= (*bg_p).w;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
/* Set RGB value to Exposure*/
|
|
shun-iwasawa |
481b59 |
bgExposure.x = conv.valueToExposure(bgExposure.x);
|
|
shun-iwasawa |
481b59 |
bgExposure.y = conv.valueToExposure(bgExposure.y);
|
|
shun-iwasawa |
481b59 |
bgExposure.z = conv.valueToExposure(bgExposure.z);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// multiply
|
|
Shinya Kitaoka |
120a6e |
bgExposure.x *= (*bg_p).w;
|
|
Shinya Kitaoka |
120a6e |
bgExposure.y *= (*bg_p).w;
|
|
Shinya Kitaoka |
120a6e |
bgExposure.z *= (*bg_p).w;
|
|
Shinya Kitaoka |
120a6e |
|
|
luz paz |
5d417b |
/* Over composite with front layers */
|
|
Shinya Kitaoka |
120a6e |
(*out_p).x = (*out_p).x + bgExposure.x * (1.0f - (*out_p).w);
|
|
Shinya Kitaoka |
120a6e |
(*out_p).y = (*out_p).y + bgExposure.y * (1.0f - (*out_p).w);
|
|
Shinya Kitaoka |
120a6e |
(*out_p).z = (*out_p).z + bgExposure.z * (1.0f - (*out_p).w);
|
|
shun-iwasawa |
4f5900 |
/* Alpha value also over-composited */
|
|
Shinya Kitaoka |
120a6e |
(*out_p).w = (*out_p).w + (*bg_p).w * (1.0f - (*out_p).w);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
background_host_ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Iwa_MotionBlurCompFx::Iwa_MotionBlurCompFx()
|
|
Shinya Kitaoka |
120a6e |
: m_hardness(0.3)
|
|
shun-iwasawa |
481b59 |
, m_gamma(2.2)
|
|
shun-iwasawa |
481b59 |
, m_gammaAdjust(0.)
|
|
Campbell Barton |
d3ecc4 |
/* Parameters for blurring left and right */
|
|
Shinya Kitaoka |
120a6e |
, m_startValue(1.0)
|
|
Shinya Kitaoka |
120a6e |
, m_startCurve(1.0)
|
|
Shinya Kitaoka |
120a6e |
, m_endValue(1.0)
|
|
Shinya Kitaoka |
120a6e |
, m_endCurve(1.0)
|
|
Shinya Kitaoka |
120a6e |
, m_zanzoMode(false)
|
|
Shinya Kitaoka |
120a6e |
, m_premultiType(new TIntEnumParam(AUTO, "Auto")) {
|
|
Campbell Barton |
d3ecc4 |
/* Bind common parameters */
|
|
Shinya Kitaoka |
120a6e |
addInputPort("Source", m_input);
|
|
Shinya Kitaoka |
120a6e |
addInputPort("Back", m_background);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "hardness", m_hardness);
|
|
shun-iwasawa |
481b59 |
bindParam(this, "gamma", m_gamma);
|
|
shun-iwasawa |
481b59 |
bindParam(this, "gammaAdjust", m_gammaAdjust);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "shutterStart", m_shutterStart);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "shutterEnd", m_shutterEnd);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "traceResolution", m_traceResolution);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "motionObjectType", m_motionObjectType);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "motionObjectIndex", m_motionObjectIndex);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "startValue", m_startValue);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "startCurve", m_startCurve);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "endValue", m_endValue);
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "endCurve", m_endCurve);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "zanzoMode", m_zanzoMode);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bindParam(this, "premultiType", m_premultiType);
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Common parameter range setting */
|
|
Shinya Kitaoka |
120a6e |
m_hardness->setValueRange(0.05, 10.0);
|
|
shun-iwasawa |
481b59 |
m_gamma->setValueRange(1.0, 10.0);
|
|
shun-iwasawa |
481b59 |
m_gammaAdjust->setValueRange(-5., 5.);
|
|
Shinya Kitaoka |
120a6e |
m_startValue->setValueRange(0.0, 1.0);
|
|
Shinya Kitaoka |
120a6e |
m_startCurve->setValueRange(0.1, 10.0);
|
|
Shinya Kitaoka |
120a6e |
m_endValue->setValueRange(0.0, 1.0);
|
|
Shinya Kitaoka |
120a6e |
m_endCurve->setValueRange(0.1, 10.0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_premultiType->addItem(SOURCE_IS_PREMULTIPLIED, "Source is premultiplied");
|
|
Shinya Kitaoka |
120a6e |
m_premultiType->addItem(SOURCE_IS_NOT_PREMUTIPLIED,
|
|
Shinya Kitaoka |
120a6e |
"Source is NOT premultiplied");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
getAttributes()->setIsSpeedAware(true);
|
|
shun-iwasawa |
481b59 |
enableComputeInFloat(true);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
// Version 1: Exposure is computed by using Hardness
|
|
shun-iwasawa |
481b59 |
// E = std::pow(10.0, (value - 0.5) / hardness)
|
|
shun-iwasawa |
481b59 |
// Version 2: Exposure is computed by using Gamma, for easier combination with
|
|
shun-iwasawa |
481b59 |
// the linear color space
|
|
shun-iwasawa |
481b59 |
// E = std::pow(value, gamma)
|
|
shun-iwasawa |
481b59 |
// Version 3: Gamma is computed by rs.m_colorSpaceGamma + gammaAdjust
|
|
shun-iwasawa |
481b59 |
// this must be called after binding the parameters (see onFxVersionSet())
|
|
shun-iwasawa |
481b59 |
setFxVersion(3);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
//--------------------------------------------
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
void Iwa_MotionBlurCompFx::onFxVersionSet() {
|
|
shun-iwasawa |
481b59 |
if (getFxVersion() == 1) { // use hardness
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("hardness")->setIsHidden(false);
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("gamma")->setIsHidden(true);
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("gammaAdjust")->setIsHidden(true);
|
|
shun-iwasawa |
481b59 |
return;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("hardness")->setIsHidden(true);
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
bool useGamma = getFxVersion() == 2;
|
|
shun-iwasawa |
481b59 |
if (useGamma) {
|
|
shun-iwasawa |
481b59 |
// Automatically update version
|
|
shun-iwasawa |
481b59 |
if (m_gamma->getKeyframeCount() == 0 &&
|
|
shun-iwasawa |
481b59 |
areAlmostEqual(m_gamma->getDefaultValue(), 2.2)) {
|
|
shun-iwasawa |
481b59 |
useGamma = false;
|
|
shun-iwasawa |
481b59 |
setFxVersion(3);
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("gamma")->setIsHidden(!useGamma);
|
|
shun-iwasawa |
481b59 |
getParams()->getParamVar("gammaAdjust")->setIsHidden(useGamma);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::doCompute(TTile &tile, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &settings) {
|
|
Campbell Barton |
d3ecc4 |
/* Do not process if not connected */
|
|
Shinya Kitaoka |
120a6e |
if (!m_input.isConnected() && !m_background.isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster()->clear();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Campbell Barton |
d3ecc4 |
/* For BG only connection */
|
|
Shinya Kitaoka |
120a6e |
if (!m_input.isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
m_background->compute(tile, frame, settings);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Get parameters */
|
|
Shinya Kitaoka |
120a6e |
QList<tpointd> points = getAttributes()->getMotionPoints();</tpointd>
|
|
shun-iwasawa |
481b59 |
double gamma;
|
|
shun-iwasawa |
481b59 |
// The hardness value had been used inversely with the bokeh fxs.
|
|
shun-iwasawa |
481b59 |
// Now the convertion functions are shared with the bokeh fxs,
|
|
shun-iwasawa |
481b59 |
// so we need to change the hardness to reciprocal in order to obtain
|
|
shun-iwasawa |
481b59 |
// the same result as previous versions.
|
|
shun-iwasawa |
481b59 |
if (getFxVersion() == 1)
|
|
shun-iwasawa |
481b59 |
gamma = 1. / m_hardness->getValue(frame);
|
|
shun-iwasawa |
481b59 |
else { // gamma
|
|
shun-iwasawa |
481b59 |
if (getFxVersion() == 2)
|
|
shun-iwasawa |
481b59 |
gamma = m_gamma->getValue(frame);
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
gamma = std::max(
|
|
shun-iwasawa |
481b59 |
1., settings.m_colorSpaceGamma + m_gammaAdjust->getValue(frame));
|
|
shun-iwasawa |
481b59 |
if (tile.getRaster()->isLinear()) gamma /= settings.m_colorSpaceGamma;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
double shutterStart = m_shutterStart->getValue(frame);
|
|
shun-iwasawa |
481b59 |
double shutterEnd = m_shutterEnd->getValue(frame);
|
|
shun-iwasawa |
481b59 |
int traceResolution = m_traceResolution->getValue();
|
|
shun-iwasawa |
481b59 |
float startValue = (float)m_startValue->getValue(frame);
|
|
shun-iwasawa |
481b59 |
float startCurve = (float)m_startCurve->getValue(frame);
|
|
shun-iwasawa |
481b59 |
float endValue = (float)m_endValue->getValue(frame);
|
|
shun-iwasawa |
481b59 |
float endCurve = (float)m_endCurve->getValue(frame);
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Do not process if there are no more than two trajectory data */
|
|
Shinya Kitaoka |
120a6e |
if (points.size() < 2) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_background.isConnected()) m_input->compute(tile, frame, settings);
|
|
Campbell Barton |
d3ecc4 |
/* If there is a background and the foreground does not move, simply over */
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
composeWithNoMotion(tile, frame, settings);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
4f5900 |
/* Get display area */
|
|
Shinya Kitaoka |
120a6e |
TRectD bBox =
|
|
Campbell Barton |
d3ecc4 |
TRectD(tile.m_pos /* Render position on Pixel unit */
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Campbell Barton |
d3ecc4 |
TDimensionD(/* Size of Render image (Pixel unit) */
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster()->getLx(), tile.getRaster()->getLy()));
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Get upper, lower, left and right margin */
|
|
Shinya Kitaoka |
120a6e |
double minX = 0.0;
|
|
Shinya Kitaoka |
120a6e |
double maxX = 0.0;
|
|
Shinya Kitaoka |
120a6e |
double minY = 0.0;
|
|
Shinya Kitaoka |
120a6e |
double maxY = 0.0;
|
|
Shinya Kitaoka |
120a6e |
for (int p = 0; p < points.size(); p++) {
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).x > maxX) maxX = points.at(p).x;
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).x < minX) minX = points.at(p).x;
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).y > maxY) maxY = points.at(p).y;
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).y < minY) minY = points.at(p).y;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Rozhuk Ivan |
823a31 |
int marginLeft = (int)ceil(std::abs(minX));
|
|
Rozhuk Ivan |
823a31 |
int marginRight = (int)ceil(std::abs(maxX));
|
|
Rozhuk Ivan |
823a31 |
int marginTop = (int)ceil(std::abs(maxY));
|
|
Rozhuk Ivan |
823a31 |
int marginBottom = (int)ceil(std::abs(minY));
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Return the input tile as-is if there is not movement
|
|
shun-iwasawa |
481b59 |
* (= filter margins are all 0). */
|
|
Shinya Kitaoka |
120a6e |
if (marginLeft == 0 && marginRight == 0 && marginTop == 0 &&
|
|
Shinya Kitaoka |
120a6e |
marginBottom == 0) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_background.isConnected()) m_input->compute(tile, frame, settings);
|
|
shun-iwasawa |
4f5900 |
/* If there is a background, and the foreground does not move, simply over
|
|
shun-iwasawa |
4f5900 |
*/
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
composeWithNoMotion(tile, frame, settings);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* resize the bbox with the upper/lower/left/right inverted margins.
|
|
Campbell Barton |
d3ecc4 |
*/
|
|
Shinya Kitaoka |
120a6e |
TRectD enlargedBBox(bBox.x0 - (double)marginRight,
|
|
Shinya Kitaoka |
120a6e |
bBox.y0 - (double)marginTop, bBox.x1 + (double)marginLeft,
|
|
Shinya Kitaoka |
120a6e |
bBox.y1 + (double)marginBottom);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// std::cout<<"Margin Left:"<
|
|
Shinya Kitaoka |
120a6e |
// " Bottom:"<
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
TDimensionI enlargedDimIn(/* Rounded to the nearest Pixel */
|
|
Shinya Kitaoka |
120a6e |
(int)(enlargedBBox.getLx() + 0.5),
|
|
Shinya Kitaoka |
120a6e |
(int)(enlargedBBox.getLy() + 0.5));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TTile enlarge_tile;
|
|
Shinya Kitaoka |
120a6e |
m_input->allocateAndCompute(enlarge_tile, enlargedBBox.getP00(),
|
|
Shinya Kitaoka |
120a6e |
enlargedDimIn, tile.getRaster(), frame, settings);
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* If background is required */
|
|
Shinya Kitaoka |
120a6e |
TTile back_Tile;
|
|
Shinya Kitaoka |
120a6e |
if (m_background.isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
m_background->allocateAndCompute(back_Tile, tile.m_pos,
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster()->getSize(),
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster(), frame, settings);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//-------------------------------------------------------
|
|
Campbell Barton |
d3ecc4 |
/* Compute range */
|
|
Shinya Kitaoka |
120a6e |
TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy());
|
|
Shinya Kitaoka |
120a6e |
TDimensionI filterDim(marginLeft + marginRight + 1,
|
|
Shinya Kitaoka |
120a6e |
marginTop + marginBottom + 1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Release of pointsTable is done within each doCompute */
|
|
Shinya Kitaoka |
120a6e |
int pointAmount = points.size();
|
|
Shinya Kitaoka |
120a6e |
float4 *pointsTable = new float4[pointAmount];
|
|
Shinya Kitaoka |
120a6e |
float dt = (float)(shutterStart + shutterEnd) / (float)traceResolution;
|
|
Shinya Kitaoka |
120a6e |
for (int p = 0; p < pointAmount; p++) {
|
|
Shinya Kitaoka |
120a6e |
pointsTable[p].x = (float)points.at(p).x;
|
|
Shinya Kitaoka |
120a6e |
pointsTable[p].y = (float)points.at(p).y;
|
|
shun-iwasawa |
4f5900 |
/* z stores the distance of p -> p + 1 vector */
|
|
Shinya Kitaoka |
120a6e |
if (p < pointAmount - 1) {
|
|
shun-iwasawa |
481b59 |
float2 vec = {(float)(points.at(p + 1).x - points.at(p).x),
|
|
shun-iwasawa |
481b59 |
(float)(points.at(p + 1).y - points.at(p).y)};
|
|
Shinya Kitaoka |
120a6e |
pointsTable[p].z = sqrtf(vec.x * vec.x + vec.y * vec.y);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
4f5900 |
/* w stores shutter time offset */
|
|
Shinya Kitaoka |
120a6e |
pointsTable[p].w = -(float)shutterStart + (float)p * dt;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
481b59 |
doCompute_CPU(tile, frame, settings, pointsTable, pointAmount, gamma,
|
|
Shinya Kitaoka |
120a6e |
shutterStart, shutterEnd, traceResolution, startValue,
|
|
Shinya Kitaoka |
120a6e |
startCurve, endValue, endCurve, marginLeft, marginRight,
|
|
Shinya Kitaoka |
120a6e |
marginTop, marginBottom, enlargedDimIn, enlarge_tile, dimOut,
|
|
Shinya Kitaoka |
120a6e |
filterDim, back_Tile);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void Iwa_MotionBlurCompFx::doCompute_CPU(
|
|
Shinya Kitaoka |
120a6e |
TTile &tile, double frame, const TRenderSettings &settings,
|
|
shun-iwasawa |
481b59 |
float4 *pointsTable, int pointAmount, double gamma, double shutterStart,
|
|
Shinya Kitaoka |
120a6e |
double shutterEnd, int traceResolution, float startValue, float startCurve,
|
|
Shinya Kitaoka |
120a6e |
float endValue, float endCurve, int marginLeft, int marginRight,
|
|
Shinya Kitaoka |
120a6e |
int marginTop, int marginBottom, TDimensionI &enlargedDimIn,
|
|
Shinya Kitaoka |
120a6e |
TTile &enlarge_tile, TDimensionI &dimOut, TDimensionI &filterDim,
|
|
Shinya Kitaoka |
120a6e |
TTile &back_tile) {
|
|
Campbell Barton |
d3ecc4 |
/* Processing memory */
|
|
Campbell Barton |
d3ecc4 |
float4 *in_tile_p; /* With margin */
|
|
Campbell Barton |
d3ecc4 |
float4 *out_tile_p; /* With margin */
|
|
Campbell Barton |
d3ecc4 |
/* Filter */
|
|
Shinya Kitaoka |
120a6e |
float *filter_p;
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Memory allocation */
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P in_tile_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly);
|
|
Shinya Kitaoka |
120a6e |
in_tile_ras->lock();
|
|
Shinya Kitaoka |
120a6e |
in_tile_p = (float4 *)in_tile_ras->getRawData();
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P out_tile_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly);
|
|
Shinya Kitaoka |
120a6e |
out_tile_ras->lock();
|
|
Shinya Kitaoka |
120a6e |
out_tile_p = (float4 *)out_tile_ras->getRawData();
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P filter_ras(sizeof(float) * filterDim.lx, filterDim.ly);
|
|
Shinya Kitaoka |
120a6e |
filter_ras->lock();
|
|
Shinya Kitaoka |
120a6e |
filter_p = (float *)filter_ras->getRawData();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool sourceIsPremultiplied;
|
|
shun-iwasawa |
4f5900 |
/* normalize the source image to 0 - 1 and read it into memory */
|
|
Shinya Kitaoka |
120a6e |
TRaster32P ras32 = (TRaster32P)enlarge_tile.getRaster();
|
|
Shinya Kitaoka |
120a6e |
TRaster64P ras64 = (TRaster64P)enlarge_tile.getRaster();
|
|
shun-iwasawa |
481b59 |
TRasterFP rasF = (TRasterFP)enlarge_tile.getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (ras32)
|
|
Shinya Kitaoka |
120a6e |
sourceIsPremultiplied = setSourceRaster<traster32p, tpixel32="">(</traster32p,>
|
|
Shinya Kitaoka |
120a6e |
ras32, in_tile_p, enlargedDimIn,
|
|
Shinya Kitaoka |
120a6e |
(PremultiTypes)m_premultiType->getValue());
|
|
Shinya Kitaoka |
120a6e |
else if (ras64)
|
|
Shinya Kitaoka |
120a6e |
sourceIsPremultiplied = setSourceRaster<traster64p, tpixel64="">(</traster64p,>
|
|
Shinya Kitaoka |
120a6e |
ras64, in_tile_p, enlargedDimIn,
|
|
Shinya Kitaoka |
120a6e |
(PremultiTypes)m_premultiType->getValue());
|
|
shun-iwasawa |
481b59 |
else if (rasF)
|
|
shun-iwasawa |
481b59 |
sourceIsPremultiplied = setSourceRaster<trasterfp, tpixelf="">(</trasterfp,>
|
|
shun-iwasawa |
481b59 |
rasF, in_tile_p, enlargedDimIn,
|
|
shun-iwasawa |
481b59 |
(PremultiTypes)m_premultiType->getValue());
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* When afterimage mode is off */
|
|
Shinya Kitaoka |
120a6e |
if (!m_zanzoMode->getValue()) {
|
|
Campbell Barton |
d3ecc4 |
/* Create and normalize filters */
|
|
Shinya Kitaoka |
120a6e |
makeMotionBlurFilter_CPU(filter_p, filterDim, marginLeft, marginBottom,
|
|
Shinya Kitaoka |
120a6e |
pointsTable, pointAmount, startValue, startCurve,
|
|
Shinya Kitaoka |
120a6e |
endValue, endCurve);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
4f5900 |
/* When afterimage mode is ON */
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
shun-iwasawa |
4f5900 |
/* Create / normalize the afterimage filter */
|
|
Shinya Kitaoka |
120a6e |
makeZanzoFilter_CPU(filter_p, filterDim, marginLeft, marginBottom,
|
|
Shinya Kitaoka |
120a6e |
pointsTable, pointAmount, startValue, startCurve,
|
|
Shinya Kitaoka |
120a6e |
endValue, endCurve);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
delete[] pointsTable;
|
|
Shinya Kitaoka |
120a6e |
|
|
shun-iwasawa |
4f5900 |
/* Unpremultiply RGB value (0 to 1)
|
|
Campbell Barton |
d3ecc4 |
* -> convert it to exposure value
|
|
Campbell Barton |
d3ecc4 |
* -> premultiply again
|
|
Campbell Barton |
d3ecc4 |
*/
|
|
shun-iwasawa |
481b59 |
if (getFxVersion() == 1)
|
|
shun-iwasawa |
481b59 |
convertRGBtoExposure_CPU(
|
|
shun-iwasawa |
481b59 |
in_tile_p, enlargedDimIn,
|
|
shun-iwasawa |
481b59 |
HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
|
|
shun-iwasawa |
481b59 |
enlarge_tile.getRaster()->isLinear()),
|
|
shun-iwasawa |
481b59 |
sourceIsPremultiplied);
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
convertRGBtoExposure_CPU(in_tile_p, enlargedDimIn,
|
|
shun-iwasawa |
481b59 |
GammaBasedConverter(gamma), sourceIsPremultiplied);
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Filter and blur exposure value */
|
|
Shinya Kitaoka |
120a6e |
applyBlurFilter_CPU(in_tile_p, out_tile_p, enlargedDimIn, filter_p, filterDim,
|
|
Shinya Kitaoka |
120a6e |
marginLeft, marginBottom, marginRight, marginTop, dimOut);
|
|
Campbell Barton |
d3ecc4 |
/* Memory release */
|
|
Shinya Kitaoka |
120a6e |
in_tile_ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
filter_ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* If there is a background, do Exposure multiplication */
|
|
Shinya Kitaoka |
120a6e |
if (m_background.isConnected()) {
|
|
shun-iwasawa |
481b59 |
if (getFxVersion() == 1)
|
|
shun-iwasawa |
481b59 |
composeBackgroundExposure_CPU(
|
|
shun-iwasawa |
481b59 |
out_tile_p, enlargedDimIn, marginRight, marginTop, back_tile, dimOut,
|
|
shun-iwasawa |
481b59 |
HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
|
|
shun-iwasawa |
481b59 |
tile.getRaster()->isLinear()));
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
composeBackgroundExposure_CPU(out_tile_p, enlargedDimIn, marginRight,
|
|
shun-iwasawa |
481b59 |
marginTop, back_tile, dimOut,
|
|
shun-iwasawa |
481b59 |
GammaBasedConverter(gamma));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
4f5900 |
/* Unpremultiply the exposure value
|
|
shun-iwasawa |
4f5900 |
* -> convert back to RGB value (0 to 1)
|
|
shun-iwasawa |
4f5900 |
* -> premultiply */
|
|
shun-iwasawa |
481b59 |
if (getFxVersion() == 1)
|
|
shun-iwasawa |
481b59 |
convertExposureToRGB_CPU(
|
|
shun-iwasawa |
481b59 |
out_tile_p, enlargedDimIn,
|
|
shun-iwasawa |
481b59 |
HardnessBasedConverter(gamma, settings.m_colorSpaceGamma,
|
|
shun-iwasawa |
481b59 |
tile.getRaster()->isLinear()));
|
|
shun-iwasawa |
481b59 |
else
|
|
shun-iwasawa |
481b59 |
convertExposureToRGB_CPU(out_tile_p, enlargedDimIn,
|
|
shun-iwasawa |
481b59 |
GammaBasedConverter(gamma));
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Clear raster */
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster()->clear();
|
|
Shinya Kitaoka |
120a6e |
TRaster32P outRas32 = (TRaster32P)tile.getRaster();
|
|
Shinya Kitaoka |
120a6e |
TRaster64P outRas64 = (TRaster64P)tile.getRaster();
|
|
shun-iwasawa |
481b59 |
TRasterFP outRasF = (TRasterFP)tile.getRaster();
|
|
Shinya Kitaoka |
120a6e |
int2 margin = {marginRight, marginTop};
|
|
Shinya Kitaoka |
120a6e |
if (outRas32)
|
|
Shinya Kitaoka |
120a6e |
setOutputRaster<traster32p, tpixel32="">(out_tile_p, outRas32, enlargedDimIn,</traster32p,>
|
|
Shinya Kitaoka |
120a6e |
margin);
|
|
Shinya Kitaoka |
120a6e |
else if (outRas64)
|
|
Shinya Kitaoka |
120a6e |
setOutputRaster<traster64p, tpixel64="">(out_tile_p, outRas64, enlargedDimIn,</traster64p,>
|
|
Shinya Kitaoka |
120a6e |
margin);
|
|
shun-iwasawa |
481b59 |
else if (outRasF)
|
|
shun-iwasawa |
481b59 |
setOutputRaster<trasterfp, tpixelf="">(out_tile_p, outRasF, enlargedDimIn,</trasterfp,>
|
|
shun-iwasawa |
481b59 |
margin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
/* Memory release */
|
|
Shinya Kitaoka |
120a6e |
out_tile_ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool Iwa_MotionBlurCompFx::doGetBBox(double frame, TRectD &bBox,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
if (!m_input.isConnected() && !m_background.isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
bBox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
luz paz |
6454c4 |
/* Rough implementation - return infinite size if the background is connected
|
|
shun-iwasawa |
4f5900 |
*/
|
|
Shinya Kitaoka |
120a6e |
if (m_background.isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
bool _ret = m_background->doGetBBox(frame, bBox, info);
|
|
Shinya Kitaoka |
120a6e |
bBox = TConsts::infiniteRectD;
|
|
Shinya Kitaoka |
120a6e |
return _ret;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool ret = m_input->doGetBBox(frame, bBox, info);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (bBox == TConsts::infiniteRectD) return true;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
QList<tpointd> points = getAttributes()->getMotionPoints();</tpointd>
|
|
shun-iwasawa |
4f5900 |
/* Compute the margin from the bounding box of the moved trajectory */
|
|
shun-iwasawa |
4f5900 |
/* Obtain the maximum absolute value of the coordinates of each trajectory
|
|
shun-iwasawa |
4f5900 |
* point */
|
|
shun-iwasawa |
4f5900 |
/* Get upper, lower, left and right margins */
|
|
Shinya Kitaoka |
120a6e |
double minX = 0.0;
|
|
Shinya Kitaoka |
120a6e |
double maxX = 0.0;
|
|
Shinya Kitaoka |
120a6e |
double minY = 0.0;
|
|
Shinya Kitaoka |
120a6e |
double maxY = 0.0;
|
|
Shinya Kitaoka |
120a6e |
for (int p = 0; p < points.size(); p++) {
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).x > maxX) maxX = points.at(p).x;
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).x < minX) minX = points.at(p).x;
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).y > maxY) maxY = points.at(p).y;
|
|
Shinya Kitaoka |
120a6e |
if (points.at(p).y < minY) minY = points.at(p).y;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Rozhuk Ivan |
823a31 |
int marginLeft = (int)ceil(std::abs(minX));
|
|
Rozhuk Ivan |
823a31 |
int marginRight = (int)ceil(std::abs(maxX));
|
|
Rozhuk Ivan |
823a31 |
int marginTop = (int)ceil(std::abs(maxY));
|
|
Rozhuk Ivan |
823a31 |
int marginBottom = (int)ceil(std::abs(minY));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD enlargedBBox(
|
|
Shinya Kitaoka |
120a6e |
bBox.x0 - (double)marginLeft, bBox.y0 - (double)marginBottom,
|
|
Shinya Kitaoka |
120a6e |
bBox.x1 + (double)marginRight, bBox.y1 + (double)marginTop);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bBox = enlargedBBox;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return ret;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool Iwa_MotionBlurCompFx::canHandle(const TRenderSettings &info,
|
|
Shinya Kitaoka |
120a6e |
double frame) {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*------------------------------------------------------------
|
|
Campbell Barton |
d3ecc4 |
Since there is a possibility that the reference object is moving,
|
|
shun-iwasawa |
4f5900 |
Change the alias every frame
|
|
Toshihiro Shimizu |
890ddd |
------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string Iwa_MotionBlurCompFx::getAlias(double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) const {
|
|
Shinya Kitaoka |
120a6e |
std::string alias = getFxType();
|
|
Shinya Kitaoka |
120a6e |
alias += "[";
|
|
Shinya Kitaoka |
120a6e |
|
|
Campbell Barton |
d3ecc4 |
// alias of the effects related to the input ports separated by commas
|
|
Campbell Barton |
d3ecc4 |
// a port that is not connected to an alias blank (empty string)
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < getInputPortCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TFxPort *port = getInputPort(i);
|
|
Shinya Kitaoka |
120a6e |
if (port->isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
TRasterFxP ifx = port->getFx();
|
|
Shinya Kitaoka |
120a6e |
assert(ifx);
|
|
Shinya Kitaoka |
120a6e |
alias += ifx->getAlias(frame, info);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
alias += ",";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::string paramalias("");
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < getParams()->getParamCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TParam *param = getParams()->getParam(i);
|
|
Shinya Kitaoka |
120a6e |
paramalias += param->getName() + "=" + param->getValueAlias(frame, 3);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
unsigned long id = getIdentifier();
|
|
Shinya Kitaoka |
120a6e |
return alias + std::to_string(frame) + "," + std::to_string(id) + paramalias +
|
|
Shinya Kitaoka |
120a6e |
"]";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
481b59 |
//------------------------------------------------------------
|
|
shun-iwasawa |
481b59 |
|
|
shun-iwasawa |
481b59 |
bool Iwa_MotionBlurCompFx::toBeComputedInLinearColorSpace(
|
|
shun-iwasawa |
481b59 |
bool settingsIsLinear, bool tileIsLinear) const {
|
|
shun-iwasawa |
481b59 |
return settingsIsLinear;
|
|
shun-iwasawa |
481b59 |
}
|
|
shun-iwasawa |
481b59 |
|
|
Toshihiro Shimizu |
890ddd |
FX_PLUGIN_IDENTIFIER(Iwa_MotionBlurCompFx, "iwa_MotionBlurCompFx")
|