particlesfx : use 16bpc control image for gradient

This commit is contained in:
shun-iwasawa 2021-04-20 16:39:28 +09:00 committed by manongjohn
parent 5d866328ea
commit 3b3c1b2fa1
4 changed files with 136 additions and 94 deletions

View file

@ -150,12 +150,14 @@ Particle::Particle(int g_lifetime, int seed, std::map<int, TTile *> porttiles,
/*- Speed Angleの制御。RangeモードとGradientモードがある -*/ /*- Speed Angleの制御。RangeモードとGradientモードがある -*/
if (values.speeda_ctrl_val && if (values.speeda_ctrl_val &&
(porttiles.find(values.speeda_ctrl_val) != porttiles.end())) { (porttiles.find(values.speeda_ctrl_val) != porttiles.end() ||
porttiles.find(values.speeda_ctrl_val + Ctrl_64_Offset) !=
porttiles.end())) {
if (values.speeda_use_gradient_val) { if (values.speeda_use_gradient_val) {
/*- 参照画像のGradientを得る関数を利用して角度を得る -*/ /*- 参照画像のGradientを得る関数を利用して角度を得る -*/
float dir_x, dir_y; float dir_x, dir_y;
get_image_gravity(porttiles[values.speeda_ctrl_val], values, dir_x, get_image_gravity(porttiles[values.speeda_ctrl_val + Ctrl_64_Offset],
dir_y); values, dir_x, dir_y);
if (dir_x == 0.0f && dir_y == 0.0f) if (dir_x == 0.0f && dir_y == 0.0f)
random_s_a_range = values.speed_val.first; random_s_a_range = values.speed_val.first;
else else
@ -558,67 +560,41 @@ void Particle::get_image_reference(TTile *ctrl, const particles_values &values,
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
void Particle::get_image_gravity(TTile *ctrl1, const particles_values &values, void Particle::get_image_gravity(TTile *ctrl1, const particles_values &values,
float &gx, float &gy) { float &gx, float &gy) {
TRaster32P raster32 = ctrl1->getRaster(); TRaster64P raster64 = ctrl1->getRaster();
TPointD tmp(x, y); TPointD tmp(x, y);
tmp -= ctrl1->m_pos; tmp -= ctrl1->m_pos;
int radius = 4; int radius = 2;
gx = 0; gx = 0;
gy = 0; gy = 0;
//#define OLDSTUFF raster64->lock();
#ifdef OLDSTUFF if (raster64 && tmp.x >= radius && tmp.x < raster64->getLx() - radius &&
int i; tmp.y >= radius && tmp.y < raster64->getLy() - radius) {
#endif TPixel64 *pix = &(raster64->pixels(troundp(tmp.y))[(int)tmp.x]);
raster32->lock();
#ifdef OLDSTUFF
if (!values.gravity_radius_val) {
radius = 4;
if (raster32 && tmp.x >= radius && tmp.x < raster32->getLx() - radius &&
tmp.y >= radius && tmp.y < raster32->getLy() - radius) {
TPixel32 *pix = &(raster32->pixels(troundp(tmp.y))[(int)tmp.x]);
double norm = 1 / ((double)TPixelGR8::maxChannelValue);
for (i = 1; i < radius; i++) {
gx += TPixelGR8::from(*(pix + i)).value;
gx -= TPixelGR8::from(*(pix - i)).value;
gy += TPixelGR8::from(*(pix + raster32->getWrap() * i)).value;
gy -= TPixelGR8::from(*(pix - raster32->getWrap() * i)).value;
}
gx = gx * norm;
gy = gy * norm;
}
} else {
#endif
radius = 2;
if (raster32 && tmp.x >= radius && tmp.x < raster32->getLx() - radius &&
tmp.y >= radius && tmp.y < raster32->getLy() - radius) {
TPixel32 *pix = &(raster32->pixels(troundp(tmp.y))[(int)tmp.x]);
gx += 2 * TPixelGR8::from(*(pix + 1)).value; gx += 2 * TPixelGR16::from(*(pix + 1)).value;
gx += TPixelGR8::from(*(pix + 1 + raster32->getWrap() * 1)).value; gx += TPixelGR16::from(*(pix + 1 + raster64->getWrap() * 1)).value;
gx += TPixelGR8::from(*(pix + 1 - raster32->getWrap() * 1)).value; gx += TPixelGR16::from(*(pix + 1 - raster64->getWrap() * 1)).value;
gx -= 2 * TPixelGR8::from(*(pix - 1)).value; gx -= 2 * TPixelGR16::from(*(pix - 1)).value;
gx -= TPixelGR8::from(*(pix - 1 + raster32->getWrap() * 1)).value; gx -= TPixelGR16::from(*(pix - 1 + raster64->getWrap() * 1)).value;
gx -= TPixelGR8::from(*(pix - 1 - raster32->getWrap() * 1)).value; gx -= TPixelGR16::from(*(pix - 1 - raster64->getWrap() * 1)).value;
gy += 2 * TPixelGR8::from(*(pix + raster32->getWrap() * 1)).value; gy += 2 * TPixelGR16::from(*(pix + raster64->getWrap() * 1)).value;
gy += TPixelGR8::from(*(pix + raster32->getWrap() * 1 + 1)).value; gy += TPixelGR16::from(*(pix + raster64->getWrap() * 1 + 1)).value;
gy += TPixelGR8::from(*(pix + raster32->getWrap() * 1 - 1)).value; gy += TPixelGR16::from(*(pix + raster64->getWrap() * 1 - 1)).value;
gy -= 2 * TPixelGR8::from(*(pix - raster32->getWrap() * 1)).value; gy -= 2 * TPixelGR16::from(*(pix - raster64->getWrap() * 1)).value;
gy -= TPixelGR8::from(*(pix - raster32->getWrap() * 1 + 1)).value; gy -= TPixelGR16::from(*(pix - raster64->getWrap() * 1 + 1)).value;
gy -= TPixelGR8::from(*(pix - raster32->getWrap() * 1 - 1)).value; gy -= TPixelGR16::from(*(pix - raster64->getWrap() * 1 - 1)).value;
double norm = sqrt(gx * gx + gy * gy); double norm = std::sqrt(gx * gx + gy * gy);
if (norm) { if (norm) {
double inorm = 0.1 / norm; double inorm = 0.1 / norm;
gx = gx * inorm; gx = gx * inorm;
gy = gy * inorm; gy = gy * inorm;
} }
} }
#ifdef OLDSTUFF raster64->unlock();
}
#endif
raster32->unlock();
} }
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
@ -701,9 +677,10 @@ void Particle::move(std::map<int, TTile *> porttiles,
// time=genlifetime-lifetime-1; // time=genlifetime-lifetime-1;
// if(time<0) time=0; // if(time<0) time=0;
if (values.gravity_ctrl_val && if (values.gravity_ctrl_val &&
(porttiles.find(values.gravity_ctrl_val) != porttiles.end())) { (porttiles.find(values.gravity_ctrl_val + Ctrl_64_Offset) !=
get_image_gravity(porttiles[values.gravity_ctrl_val], values, xgravity, porttiles.end())) {
ygravity); get_image_gravity(porttiles[values.gravity_ctrl_val + Ctrl_64_Offset],
values, xgravity, ygravity);
xgravity *= values.gravity_val; xgravity *= values.gravity_val;
ygravity *= values.gravity_val; ygravity *= values.gravity_val;
} }

View file

@ -7,6 +7,8 @@
#include "tspectrum.h" #include "tspectrum.h"
#include "trandom.h" #include "trandom.h"
const int Ctrl_64_Offset = 1000;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
struct particles_values { struct particles_values {

View file

@ -160,15 +160,31 @@ void Particles_Engine::fill_range_struct(struct particles_values &values,
} }
bool Particles_Engine::port_is_used(int i, struct particles_values &values) { bool Particles_Engine::port_is_used(int i, struct particles_values &values) {
return port_is_used_for_value(i, values) ||
port_is_used_for_gradient(i, values);
}
// Returns true if the pixel value of control image is used.
// Such image will be computed in 8bpc.
bool Particles_Engine::port_is_used_for_value(int i,
struct particles_values &values) {
return values.fincol_ctrl_val == i || values.foutcol_ctrl_val == i || return values.fincol_ctrl_val == i || values.foutcol_ctrl_val == i ||
values.friction_ctrl_val == i || values.gencol_ctrl_val == i || values.friction_ctrl_val == i || values.gencol_ctrl_val == i ||
values.gravity_ctrl_val == i || values.opacity_ctrl_val == i || values.opacity_ctrl_val == i || values.rot_ctrl_val == i ||
values.rot_ctrl_val == i || values.scale_ctrl_val == i || values.scale_ctrl_val == i || values.scalestep_ctrl_val == i ||
values.scalestep_ctrl_val == i || values.source_ctrl_val == i || values.source_ctrl_val == i || values.speed_ctrl_val == i ||
values.speed_ctrl_val == i || values.speeda_ctrl_val == i || (values.speeda_ctrl_val == i && !values.speeda_use_gradient_val) ||
values.lifetime_ctrl_val == i || values.randomx_ctrl_val == i || values.lifetime_ctrl_val == i || values.randomx_ctrl_val == i ||
values.randomy_ctrl_val == i; values.randomy_ctrl_val == i;
} }
// Returns true if the gradient of control image is used.
// Such image will be computed in 16bpc to get smooth result.
bool Particles_Engine::port_is_used_for_gradient(
int i, struct particles_values &values) {
return values.gravity_ctrl_val == i ||
(values.speeda_ctrl_val == i && values.speeda_use_gradient_val);
}
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
/*-- Startフレームからカレントフレームまで順番に回す関数 --*/ /*-- Startフレームからカレントフレームまで順番に回す関数 --*/
void Particles_Engine::roll_particles( void Particles_Engine::roll_particles(
@ -492,6 +508,9 @@ void Particles_Engine::render_particles(
TRenderSettings riAux(ri); TRenderSettings riAux(ri);
riAux.m_affine = TAffine(); riAux.m_affine = TAffine();
riAux.m_bpp = 32; riAux.m_bpp = 32;
// control image using its gradient is computed in 64bpp
TRenderSettings riAux64(riAux);
riAux64.m_bpp = 64;
int r_frame; // Useful in case of negative roll frames int r_frame; // Useful in case of negative roll frames
if (frame < 0) if (frame < 0)
@ -538,6 +557,47 @@ void Particles_Engine::render_particles(
// dryComputed - so, declare the same here. // dryComputed - so, declare the same here.
(*it->second)->dryCompute(bbox, r_frame, riAux); (*it->second)->dryCompute(bbox, r_frame, riAux);
} else { } else {
// control image is used its gradient
if (port_is_used_for_gradient(it->first, values)) {
tmp = new TTile;
if (isPrecomputingEnabled)
(*it->second)
->allocateAndCompute(*tmp, bbox.getP00(),
convert(bbox).getSize(), 0, r_frame,
riAux64);
else {
std::string alias =
"CTRL64: " + (*(it->second))->getAlias(r_frame, riAux64);
TRasterImageP rimg = TImageCache::instance()->get(alias, false);
if (rimg) {
tmp->m_pos = bbox.getP00();
tmp->setRaster(rimg->getRaster());
} else {
(*it->second)
->allocateAndCompute(*tmp, bbox.getP00(),
convert(bbox).getSize(), 0, r_frame,
riAux64);
addRenderCache(alias, TRasterImageP(tmp->getRaster()));
}
}
porttiles[it->first + Ctrl_64_Offset] = tmp;
// in case the control image is also used for non-gradient
if (port_is_used_for_value(it->first, values)) {
TRaster32P tileRas(tmp->getRaster()->getSize());
TRop::convert(tileRas, tmp->getRaster());
tmp = new TTile;
tmp->m_pos = bbox.getP00();
tmp->setRaster(tileRas);
porttiles[it->first] = tmp;
}
}
// control images used only for non-gradient
else {
tmp = new TTile; tmp = new TTile;
if (isPrecomputingEnabled) if (isPrecomputingEnabled)
@ -568,6 +628,7 @@ void Particles_Engine::render_particles(
} }
} }
} }
}
if (frame > pcFrame) { if (frame > pcFrame) {
// Invoke the actual rolling procedure // Invoke the actual rolling procedure

View file

@ -52,6 +52,8 @@ public:
std::map<std::pair<int, int>, double> &partScales); std::map<std::pair<int, int>, double> &partScales);
bool port_is_used(int i, struct particles_values &values); bool port_is_used(int i, struct particles_values &values);
bool port_is_used_for_value(int i, struct particles_values &values);
bool port_is_used_for_gradient(int i, struct particles_values &values);
/*- /*-
do_source_gradationがONのとき do_source_gradationがONのとき