void RenderTask::onFrameFailed(TException &e) { // TRasterP evenRas(m_evenTile.getRaster()); TRenderPort::RenderData rd(m_frames, m_info, m_tileA.getRaster(), m_tileB.getRaster(), m_renderId, m_taskId); m_rendererImp->notifyRasterFailure(rd, e); }
void RenderTask::releaseTiles() { m_rendererImp->m_rasterPool.releaseRaster(m_tileA.getRaster()); m_tileA.setRaster(TRasterP()); if (m_fieldRender || m_stereoscopic) { m_rendererImp->m_rasterPool.releaseRaster(m_tileB.getRaster()); m_tileB.setRaster(TRasterP()); } }
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) { if (!m_input.isConnected()) return; m_input->compute(tile, frame, ri); double v = 1 - m_value->getValue(frame) / 100; TRop::rgbmScale(tile.getRaster(), tile.getRaster(), 1, 1, 1, v); }
void ColumnColorFilterFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { if (!m_port.isConnected()) return; if (!TRaster32P(tile.getRaster()) && !TRaster64P(tile.getRaster())) throw TException("AffineFx unsupported pixel type"); TRasterFxP src = m_port.getFx(); src->compute(tile, frame, ri); TRop::applyColorScale(tile.getRaster(), m_colorFilter); }
/*------------------------------------------------------------ 背景があり、前景が動かない場合、単純にOverする ------------------------------------------------------------*/ void Iwa_MotionBlurCompFx::composeWithNoMotion( TTile &tile, double frame, const TRenderSettings &settings) { assert(m_background.isConnected()); m_background->compute(tile, frame, settings); TTile fore_tile; m_input->allocateAndCompute(fore_tile, tile.m_pos, tile.getRaster()->getSize(), tile.getRaster(), frame, settings); TRasterP up(fore_tile.getRaster()), down(tile.getRaster()); TRop::over(down, up); }
bool TCacheResource::downloadAll(TTile &tile) { if (!checkTile(tile)) return false; return downloadAll(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); }
bool TCacheResource::upload(const TTile &tile) { if (!checkTile(tile)) return false; return upload(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); }
QRegion TCacheResource::download(TTile &tile) { if (!checkTile(tile)) return QRegion(); return download(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); }
void SwatchViewer::ContentRender::run() { if (suspendedRendering) return; unsigned long renderId = TRenderer::buildRenderId(); TPassiveCacheManager::instance()->setContextName(renderId, "S"); m_viewer->m_renderer.install(renderId); m_viewer->m_renderer.declareRenderStart(renderId); m_viewer->m_renderer.declareFrameStart(m_frame); TRenderSettings info; info.m_isSwatch = true; info.m_affine = m_aff; TTile tile; m_fx->allocateAndCompute(tile, -0.5 * TPointD(m_size.lx, m_size.ly), m_size, 0, (double)m_frame, info); m_raster = tile.getRaster(); m_viewer->m_renderer.declareFrameEnd(m_frame); m_viewer->m_renderer.declareRenderEnd(renderId); m_viewer->m_renderer.uninstall(); }
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) { if (!m_port.isConnected()) { tile.getRaster()->clear(); return; } // Exchange frame with the stored one TRasterFxP(m_port.getFx())->compute(tile, m_frame, ri); }
void RenderTask::onFrameCompleted() { TRasterP rasA(m_tileA.getRaster()); TRasterP rasB(m_tileB.getRaster()); if (m_fieldRender) { assert(rasB); double t = m_frames[0]; int f = (m_info.m_fieldPrevalence == TRenderSettings::EvenField) ? 0 : 1; interlace(rasA, rasB, f); rasB = TRasterP(); } TRenderPort::RenderData rd(m_frames, m_info, rasA, rasB, m_renderId, m_taskId); m_rendererImp->notifyRasterCompleted(rd); }
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override { if (!m_input.isConnected()) return; m_input->compute(tile, frame, ri); TRop::invert(tile.getRaster(), m_redChan->getValue(), m_greenChan->getValue(), m_blueChan->getValue(), m_alphaChan->getValue()); }
void TGeometryFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { TRasterFxPort *input = dynamic_cast<TRasterFxPort *>(getInputPort(0)); assert(input); if (!input->isConnected()) return; if (!getActiveTimeRegion().contains(frame)) { TRasterFxP(input->getFx())->compute(tile, frame, ri); return; } if (!TRaster32P(tile.getRaster()) && !TRaster64P(tile.getRaster())) throw TException("AffineFx unsupported pixel type"); TAffine aff1 = getPlacement(frame); TRenderSettings ri2(ri); ri2.m_affine = ri2.m_affine * aff1; TRasterFxP src = getInputPort("source")->getFx(); src->compute(tile, frame, ri2); return; }
void doCompute(TTile &tile, double frame, const TRenderSettings &info) override { bool isWarped = m_warped.isConnected(); if (!isWarped) return; if (fabs(m_intensity->getValue(frame)) < 0.01) { m_warped->compute(tile, frame, info); return; } int shrink = (info.m_shrinkX + info.m_shrinkY) / 2; double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); params.m_shrink = shrink; double period = m_period->getValue(frame) / info.m_shrinkX; double count = m_count->getValue(frame); double cycle = m_cycle->getValue(frame) / info.m_shrinkX; double scaleX = m_scaleX->getValue(frame) / 100.0; double scaleY = m_scaleY->getValue(frame) / 100.0; double angle = -m_angle->getValue(frame); TPointD center = m_center->getValue(frame) * (1.0 / info.m_shrinkX); // The warper is calculated on a standard reference, with fixed dpi. This // makes sure // that the lattice created for the warp does not depend on camera // transforms and resolution. TRenderSettings warperInfo(info); double warperScaleFactor = 1.0 / params.m_warperScale; warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine; // Retrieve tile's geometry TRectD tileRect; { TRasterP tileRas = tile.getRaster(); tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy())); } // Build the compute rect TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params); if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return; if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0) return; TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect); double warperEnlargement = getWarperEnlargement(params); warperComputeRect = warperComputeRect.enlarge(warperEnlargement); warperComputeRect.x0 = tfloor(warperComputeRect.x0); warperComputeRect.y0 = tfloor(warperComputeRect.y0); warperComputeRect.x1 = tceil(warperComputeRect.x1); warperComputeRect.y1 = tceil(warperComputeRect.y1); // Compute the warped tile TTile tileIn; m_warped->allocateAndCompute( tileIn, warpedComputeRect.getP00(), TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()), tile.getRaster(), frame, info); TRasterP rasIn = tileIn.getRaster(); // Compute the warper tile TSpectrum::ColorKey colors[] = {TSpectrum::ColorKey(0, TPixel32::White), TSpectrum::ColorKey(0.5, TPixel32::Black), TSpectrum::ColorKey(1, TPixel32::White)}; TSpectrumParamP ripplecolors = TSpectrumParamP(tArrayCount(colors), colors); // Build the multiradial warperInfo.m_affine = warperInfo.m_affine * TTranslation(center) * TRotation(angle) * TScale(scaleX, scaleY); TAffine aff = warperInfo.m_affine.inv(); TPointD posTrasf = aff * (warperComputeRect.getP00()); TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy()); multiRadial(rasWarper, posTrasf, ripplecolors, period, count, cycle, aff, frame); // TImageWriter::save(TFilePath("C:\\ripple.tif"), rasWarper); // Warp TPointD db; TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db)); TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI); TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00()); TPointD warperPos( (TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00()); warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params); }
void Iwa_MotionBlurCompFx::doCompute_CPU( TTile &tile, double frame, const TRenderSettings &settings, float4 *pointsTable, int pointAmount, double hardness, double shutterStart, double shutterEnd, int traceResolution, float startValue, float startCurve, float endValue, float endCurve, int marginLeft, int marginRight, int marginTop, int marginBottom, TDimensionI &enlargedDimIn, TTile &enlarge_tile, TDimensionI &dimOut, TDimensionI &filterDim, TTile &back_tile) { /*- 処理を行うメモリ -*/ float4 *in_tile_p; /*- マージンあり -*/ float4 *out_tile_p; /*- マージンあり -*/ /*- フィルタ -*/ float *filter_p; /*- メモリ確保 -*/ TRasterGR8P in_tile_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly); in_tile_ras->lock(); in_tile_p = (float4 *)in_tile_ras->getRawData(); TRasterGR8P out_tile_ras(sizeof(float4) * enlargedDimIn.lx, enlargedDimIn.ly); out_tile_ras->lock(); out_tile_p = (float4 *)out_tile_ras->getRawData(); TRasterGR8P filter_ras(sizeof(float) * filterDim.lx, filterDim.ly); filter_ras->lock(); filter_p = (float *)filter_ras->getRawData(); bool sourceIsPremultiplied; /*- ソース画像を0〜1に正規化してメモリに読み込む -*/ TRaster32P ras32 = (TRaster32P)enlarge_tile.getRaster(); TRaster64P ras64 = (TRaster64P)enlarge_tile.getRaster(); if (ras32) sourceIsPremultiplied = setSourceRaster<TRaster32P, TPixel32>( ras32, in_tile_p, enlargedDimIn, (PremultiTypes)m_premultiType->getValue()); else if (ras64) sourceIsPremultiplied = setSourceRaster<TRaster64P, TPixel64>( ras64, in_tile_p, enlargedDimIn, (PremultiTypes)m_premultiType->getValue()); /*- 残像モードがオフのとき -*/ if (!m_zanzoMode->getValue()) { /*- フィルタをつくり、正規化する -*/ makeMotionBlurFilter_CPU(filter_p, filterDim, marginLeft, marginBottom, pointsTable, pointAmount, startValue, startCurve, endValue, endCurve); } /*- 残像モードがオンのとき -*/ else { /*- 残像フィルタをつくる/正規化する -*/ makeZanzoFilter_CPU(filter_p, filterDim, marginLeft, marginBottom, pointsTable, pointAmount, startValue, startCurve, endValue, endCurve); } delete[] pointsTable; /*- RGB値(0〜1)をdepremultiply→露光値に変換→再びpremultiply -*/ convertRGBtoExposure_CPU(in_tile_p, enlargedDimIn, hardness, sourceIsPremultiplied); /*- 露光値をフィルタリングしてぼかす -*/ applyBlurFilter_CPU(in_tile_p, out_tile_p, enlargedDimIn, filter_p, filterDim, marginLeft, marginBottom, marginRight, marginTop, dimOut); /*- メモリ解放 -*/ in_tile_ras->unlock(); filter_ras->unlock(); /*- 背景がある場合、Exposureの乗算を行う -*/ if (m_background.isConnected()) { composeBackgroundExposure_CPU(out_tile_p, enlargedDimIn, marginRight, marginTop, back_tile, dimOut, (float)hardness); } /*- 露光値をdepremultipy→RGB値(0〜1)に戻す→premultiply -*/ convertExposureToRGB_CPU(out_tile_p, enlargedDimIn, hardness); /*- ラスタのクリア -*/ tile.getRaster()->clear(); TRaster32P outRas32 = (TRaster32P)tile.getRaster(); TRaster64P outRas64 = (TRaster64P)tile.getRaster(); int2 margin = {marginRight, marginTop}; if (outRas32) setOutputRaster<TRaster32P, TPixel32>(out_tile_p, outRas32, enlargedDimIn, margin); else if (outRas64) setOutputRaster<TRaster64P, TPixel64>(out_tile_p, outRas64, enlargedDimIn, margin); /*- メモリ解放 -*/ out_tile_ras->unlock(); }
bool TCacheResource::canUpload(const TTile &tile) const { int tileType; return checkTile(tile) && checkRasterType(tile.getRaster(), tileType); }
/*- render_particles から呼ばれる。粒子の数だけ繰り返し -*/ void Particles_Engine::do_render( TFlash *flash, Particle *part, TTile *tile, std::vector<TRasterFxPort *> part_ports, std::map<int, TTile *> porttiles, const TRenderSettings &ri, TDimension &p_size, TPointD &p_offset, int lastframe, std::vector<TLevelP> partLevel, struct particles_values &values, double opacity_range, int dist_frame, std::map<std::pair<int, int>, double> &partScales) { // Retrieve the particle frame - that is, the *column frame* from which we are // picking // the particle to be rendered. int ndx = part->frame % lastframe; TRasterP tileRas(tile->getRaster()); std::string levelid; double aim_angle = 0; if (values.pathaim_val) { double arctan = atan2(part->vy, part->vx); aim_angle = arctan * M_180_PI; } // Calculate the rotational and scale components we have to apply on the // particle TRotation rotM(part->angle + aim_angle); TScale scaleM(part->scale); TAffine M(rotM * scaleM); // Particles deal with dpi affines on their own TAffine scaleAff(m_parent->handledAffine(ri, m_frame)); double partScale = scaleAff.a11 * partScales[std::pair<int, int>(part->level, ndx)]; TDimensionD partResolution(0, 0); TRenderSettings riNew(ri); // Retrieve the bounding box in the standard reference TRectD bbox(-5.0, -5.0, 5.0, 5.0), standardRefBBox; if (part->level < (int)part_ports.size() && // Not the default levelless cases part_ports[part->level]->isConnected()) { TRenderSettings riIdentity(ri); riIdentity.m_affine = TAffine(); (*part_ports[part->level])->getBBox(ndx, bbox, riIdentity); // A particle's bbox MUST be finite. Gradients and such which have an // infinite bbox // are just NOT rendered. // NOTE: No fx returns half-planes or similar (ie if any coordinate is // either // (std::numeric_limits<double>::max)() or its opposite, then the rect IS // THE infiniteRectD) if (bbox == TConsts::infiniteRectD) return; } // Now, these are the particle rendering specifications bbox = bbox.enlarge(3); standardRefBBox = bbox; riNew.m_affine = TScale(partScale); bbox = riNew.m_affine * bbox; /*- 縮小済みのParticleのサイズ -*/ partResolution = TDimensionD(tceil(bbox.getLx()), tceil(bbox.getLy())); if (flash) { if (!partLevel[part->level]->frame(ndx)) { if (part_ports[0]->isConnected()) { TTile auxTile; TRaster32P tmp; tmp = TRaster32P(p_size); (*part_ports[0]) ->allocateAndCompute(auxTile, p_offset, p_size, tmp, ndx, ri); partLevel[part->level]->setFrame(ndx, TRasterImageP(auxTile.getRaster())); } } flash->pushMatrix(); const TAffine aff; flash->multMatrix(scaleM * aff.place(0, 0, part->x, part->y)); // if(curr_opacity!=1.0 || part->gencol.fadecol || part->fincol.fadecol || // part->foutcol.fadecol) { TColorFader cf(TPixel32::Red, .5); flash->draw(partLevel[part->level]->frame(ndx), &cf); } // flash->draw(partLevel->frame(ndx), 0); flash->popMatrix(); } else { TRasterP ras; std::string alias; TRasterImageP rimg; if (rimg = partLevel[part->level]->frame(ndx)) { ras = rimg->getRaster(); } else { alias = "PART: " + (*part_ports[part->level])->getAlias(ndx, riNew); if (rimg = TImageCache::instance()->get(alias, false)) { ras = rimg->getRaster(); // Check that the raster resolution is sufficient for our purposes if (ras->getLx() < partResolution.lx || ras->getLy() < partResolution.ly) ras = 0; else partResolution = TDimensionD(ras->getLx(), ras->getLy()); } } // We are interested in making the relation between scale and (integer) // resolution // bijective - since we shall cache by using resolution as a partial // identification parameter. // Therefore, we find the current bbox Lx and take a unique scale out of it. partScale = partResolution.lx / standardRefBBox.getLx(); riNew.m_affine = TScale(partScale); bbox = riNew.m_affine * standardRefBBox; // If no image was retrieved from the cache (or it was not scaled enough), // calculate it if (!ras) { TTile auxTile; (*part_ports[part->level]) ->allocateAndCompute(auxTile, bbox.getP00(), TDimension(partResolution.lx, partResolution.ly), tile->getRaster(), ndx, riNew); ras = auxTile.getRaster(); // For now, we'll just use 32 bit particles TRaster32P rcachepart; rcachepart = ras; if (!rcachepart) { rcachepart = TRaster32P(ras->getSize()); TRop::convert(rcachepart, ras); } ras = rcachepart; // Finally, cache the particle addRenderCache(alias, TRasterImageP(ras)); } if (!ras) return; // At this point, it should never happen anyway... // Deal with particle colors/opacity TRaster32P rfinalpart; double curr_opacity = part->set_Opacity(porttiles, values, opacity_range, dist_frame); if (curr_opacity != 1.0 || part->gencol.fadecol || part->fincol.fadecol || part->foutcol.fadecol) { /*- 毎フレーム現在位置のピクセル色を参照 -*/ if (values.pick_color_for_every_frame_val && values.gencol_ctrl_val && (porttiles.find(values.gencol_ctrl_val) != porttiles.end())) part->get_image_reference(porttiles[values.gencol_ctrl_val], values, part->gencol.col); rfinalpart = ras->clone(); part->modify_colors_and_opacity(values, curr_opacity, dist_frame, rfinalpart); } else rfinalpart = ras; // Now, let's build the particle transform before it is overed on the output // tile // First, complete the transform by adding the rotational and scale // components from // Particles parameters M = ri.m_affine * M * TScale(1.0 / partScale); // Then, retrieve the particle position in current reference. TPointD pos(part->x, part->y); pos = ri.m_affine * pos; // Finally, add the translational component to the particle // NOTE: p_offset is added to account for the particle relative position // inside its level's bbox M = TTranslation(pos - tile->m_pos) * M * TTranslation(bbox.getP00()); if (TRaster32P myras32 = tile->getRaster()) TRop::over(tileRas, rfinalpart, M); else if (TRaster64P myras64 = tile->getRaster()) TRop::over(tileRas, rfinalpart, M); else throw TException("ParticlesFx: unsupported Pixel Type"); } }
void Iwa_TiledParticlesFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { std::vector<int> lastframe; std::vector<TLevelP> partLevel; TPointD p_offset; TDimension p_size(0, 0); /*- 参照画像ポートの取得 -*/ std::vector<TRasterFxPort *> part_ports; /*- テクスチャ素材画像のポート -*/ std::map<int, TRasterFxPort *> ctrl_ports; /*- コントロール画像のポート番号/ポート -*/ int portsCount = this->getInputPortCount(); for (int i = 0; i < portsCount; ++i) { std::string tmpName = this->getInputPortName(i); QString portName = QString::fromStdString(tmpName); if (portName.startsWith("T")) { TRasterFxPort *tmpPart = (TRasterFxPort *)this->getInputPort(tmpName); if (tmpPart->isConnected()) part_ports.push_back((TRasterFxPort *)this->getInputPort(tmpName)); } else { portName.replace(QString("Control"), QString("")); TRasterFxPort *tmpCtrl = (TRasterFxPort *)this->getInputPort(tmpName); if (tmpCtrl->isConnected()) ctrl_ports[portName.toInt()] = (TRasterFxPort *)this->getInputPort(tmpName); } } /*- テクスチャ素材のバウンディングボックスを足し合わせる ←この工程、いらないかも?-*/ if (!part_ports.empty()) { TRectD outTileBBox(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); TRectD bbox; for (unsigned int i = 0; i < (int)part_ports.size(); ++i) { const TFxTimeRegion &tr = (*part_ports[i])->getTimeRegion(); lastframe.push_back(tr.getLastFrame() + 1); partLevel.push_back(new TLevel()); partLevel[i]->setName((*part_ports[i])->getAlias(0, ri)); // The particles offset must be calculated without considering the affine's translational // component TRenderSettings riZero(ri); riZero.m_affine.a13 = riZero.m_affine.a23 = 0; // Calculate the bboxes union for (int t = 0; t <= tr.getLastFrame(); ++t) { TRectD inputBox; (*part_ports[i])->getBBox(t, inputBox, riZero); bbox += inputBox; } } if (bbox == TConsts::infiniteRectD) bbox *= outTileBBox; p_size.lx = (int)bbox.getLx() + 1; p_size.ly = (int)bbox.getLy() + 1; p_offset = TPointD(0.5 * (bbox.x0 + bbox.x1), 0.5 * (bbox.y0 + bbox.y1)); } else { partLevel.push_back(new TLevel()); partLevel[0]->setName("particles"); TDimension vecsize(10, 10); TOfflineGL *offlineGlContext = new TOfflineGL(vecsize); offlineGlContext->clear(TPixel32(0, 0, 0, 0)); TStroke *stroke; stroke = makeEllipticStroke(0.07, TPointD((vecsize.lx - 1) * .5, (vecsize.ly - 1) * .5), 2.0, 2.0); TVectorImageP vectmp = new TVectorImage(); TPalette *plt = new TPalette(); vectmp->setPalette(plt); vectmp->addStroke(stroke); TVectorRenderData rd(AffI, TRect(vecsize), plt, 0, true, true); offlineGlContext->makeCurrent(); offlineGlContext->draw(vectmp, rd); partLevel[0]->setFrame(0, TRasterImageP(offlineGlContext->getRaster()->clone())); p_size.lx = vecsize.lx + 1; p_size.ly = vecsize.ly + 1; lastframe.push_back(1); delete offlineGlContext; } Iwa_Particles_Engine myEngine(this, frame); // Retrieving the dpi multiplier from the accumulated affine (which is isotropic). That is, // the affine will be applied *before* this effect - and we'll multiply geometrical parameters // by this dpi mult. in order to compensate. float dpi = sqrt(fabs(ri.m_affine.det())) * 100; TTile tileIn; if (TRaster32P raster32 = tile.getRaster()) { TFlash *flash = 0; myEngine.render_particles(flash, &tile, part_ports, ri, p_size, p_offset, ctrl_ports, partLevel, 1, (int)frame, 1, 0, 0, 0, 0, lastframe, getIdentifier()); } else if (TRaster64P raster64 = tile.getRaster()) { TFlash *flash = 0; myEngine.render_particles(flash, &tile, part_ports, ri, p_size, p_offset, ctrl_ports, partLevel, 1, (int)frame, 1, 0, 0, 0, 0, lastframe, getIdentifier()); } else throw TException("ParticlesFx: unsupported Pixel Type"); }
void subCompute(TRasterFxPort &m_input, TTile &tile, double frame, const TRenderSettings &ri, TPointD p00, TPointD p01, TPointD p11, TPointD p10, int details, bool wireframe, TDimension m_offScreenSize, bool isCast) { TPixel32 bgColor; TRectD outBBox, inBBox; outBBox = inBBox = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); m_input->getBBox(frame, inBBox, ri); if (inBBox == TConsts::infiniteRectD) // e' uno zerario inBBox = outBBox; int inBBoxLx = (int)inBBox.getLx() / ri.m_shrinkX; int inBBoxLy = (int)inBBox.getLy() / ri.m_shrinkY; if (inBBox.isEmpty()) return; if (p00 == p01 && p00 == p10 && p00 == p11 && !isCast) // significa che non c'e' deformazione { m_input->compute(tile, frame, ri); return; } TRaster32P rasIn; TPointD rasInPos; if (!wireframe) { if (ri.m_bpp == 64 || ri.m_bpp == 48) { TRaster64P aux = TRaster64P(inBBoxLx, inBBoxLy); rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(aux, rasInPos); m_input->compute(tmp, frame, ri); rasIn = TRaster32P(inBBoxLx, inBBoxLy); TRop::convert(rasIn, aux); } else { rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(TRaster32P(inBBoxLx, inBBoxLy), rasInPos); m_input->allocateAndCompute(tmp, rasInPos, TDimension(inBBoxLx, inBBoxLy), TRaster32P(), frame, ri); rasIn = tmp.getRaster(); } } unsigned int texWidth = 2; unsigned int texHeight = 2; while (texWidth < (unsigned int)inBBoxLx) texWidth = texWidth << 1; while (texHeight < (unsigned int)inBBoxLy) texHeight = texHeight << 1; while (texWidth > 1024 || texHeight > 1024) // avevo usato la costante // GL_MAX_TEXTURE_SIZE invece di // 1024, ma non funzionava! { inBBoxLx = inBBoxLx >> 1; inBBoxLy = inBBoxLy >> 1; texWidth = texWidth >> 1; texHeight = texHeight >> 1; } if (rasIn->getLx() != inBBoxLx || rasIn->getLy() != inBBoxLy) { TRaster32P rasOut = TRaster32P(inBBoxLx, inBBoxLy); TRop::resample(rasOut, rasIn, TScale((double)rasOut->getLx() / rasIn->getLx(), (double)rasOut->getLy() / rasIn->getLy())); rasIn = rasOut; } int rasterWidth = tile.getRaster()->getLx() + 2; int rasterHeight = tile.getRaster()->getLy() + 2; assert(rasterWidth > 0); assert(rasterHeight > 0); TRectD clippingRect = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); #if CREATE_GL_CONTEXT_ONE_TIME int ret = wglMakeCurrent(m_offScreenGL.m_offDC, m_offScreenGL.m_hglRC); assert(ret == TRUE); #else TOfflineGL offScreenRendering(TDimension(rasterWidth, rasterHeight)); //#ifdef _WIN32 offScreenRendering.makeCurrent(); //#else //#if defined(LINUX) || defined(MACOSX) // offScreenRendering.m_offlineGL->makeCurrent(); //#endif #endif checkErrorsByGL // disabilito quello che non mi serve per le texture glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glDisable(GL_DITHER); glDisable(GL_DEPTH_TEST); glCullFace(GL_FRONT); glDisable(GL_STENCIL_TEST); glDisable(GL_LOGIC_OP); // creo la texture in base all'immagine originale glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); checkErrorsByGL #if !CREATE_GL_CONTEXT_ONE_TIME TRaster32P rasaux; if (!wireframe) { TRaster32P texture(texWidth, texHeight); texture->clear(); rasaux = texture; rasaux->lock(); texture->copy(rasIn); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->getRawData()); } #else unsigned int texWidth = 1024; unsigned int texHeight = 1024; rasaux = rasIn; rasaux->lock(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasIn->getLx(), rasIn->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, rasIn->getRawData()); #endif checkErrorsByGL glEnable(GL_TEXTURE_2D); // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-rasterWidth * 0.5, rasterWidth * 0.5, -rasterHeight * 0.5, rasterHeight * 0.5, -1, 1); glViewport(0, 0, rasterWidth, rasterHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // do OpenGL draw double lwTex = (double)(inBBoxLx - 1) / (double)(texWidth - 1); double lhTex = (double)(inBBoxLy - 1) / (double)(texHeight - 1); TPointD tex00 = TPointD(0.0, 0.0); TPointD tex10 = TPointD(lwTex, 0.0); TPointD tex11 = TPointD(lwTex, lhTex); TPointD tex01 = TPointD(0.0, lhTex); GLenum polygonStyle; if (wireframe) { polygonStyle = GL_LINE; glDisable(GL_TEXTURE_2D); } else polygonStyle = GL_FILL; checkErrorsByGL p00.x /= ri.m_shrinkX; p00.y /= ri.m_shrinkY; p10.x /= ri.m_shrinkX; p10.y /= ri.m_shrinkY; p11.x /= ri.m_shrinkX; p11.y /= ri.m_shrinkY; p01.x /= ri.m_shrinkX; p01.y /= ri.m_shrinkY; TPointD translate = TPointD(tile.m_pos.x + tile.getRaster()->getLx() * 0.5, tile.m_pos.y + tile.getRaster()->getLy() * 0.5); glTranslated(-translate.x, -translate.y, 0.0); // disegno il poligono double dist_p00_p01 = tdistance2(p00, p01); double dist_p10_p11 = tdistance2(p10, p11); double dist_p01_p11 = tdistance2(p01, p11); double dist_p00_p10 = tdistance2(p00, p10); bool vertical = (dist_p00_p01 == dist_p10_p11); bool horizontal = (dist_p00_p10 == dist_p01_p11); if (vertical && horizontal) details = 1; glPolygonMode(GL_FRONT_AND_BACK, polygonStyle); subdivision(p00, p10, p11, p01, tex00, tex10, tex11, tex01, clippingRect, details); if (!wireframe) { // abilito l'antialiasing delle linee glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // disegno il bordo del poligono glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glBegin(GL_QUADS); glTexCoord2d(tex00.x, tex00.y); tglVertex(p00); glTexCoord2d(tex10.x, tex10.y); tglVertex(p10); glTexCoord2d(tex11.x, tex11.y); tglVertex(p11); glTexCoord2d(tex01.x, tex01.y); tglVertex(p01); glEnd(); // disabilito l'antialiasing per le linee glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } // force to finish glFlush(); // rimetto il disegno dei poligoni a GL_FILL glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // metto il frame buffer nel raster del tile glPixelStorei(GL_UNPACK_ROW_LENGTH, rasterWidth); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); TRaster32P newRas(tile.getRaster()->getLx(), tile.getRaster()->getLy()); newRas->lock(); glReadPixels(1, 1, newRas->getLx(), newRas->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, (void *)newRas->getRawData()); newRas->unlock(); checkErrorsByGL rasaux->unlock(); tile.getRaster()->copy(newRas); }
void Particles_Engine::render_particles( TFlash *flash, TTile *tile, std::vector<TRasterFxPort *> part_ports, const TRenderSettings &ri, TDimension &p_size, TPointD &p_offset, std::map<int, TRasterFxPort *> ctrl_ports, std::vector<TLevelP> partLevel, float dpi, int curr_frame, int shrink, double startx, double starty, double endx, double endy, std::vector<int> last_frame, unsigned long fxId) { int frame, startframe, intpart = 0, level_n = 0; struct particles_values values; double dpicorr = dpi * 0.01, fractpart = 0, dpicorr_shrinked = 0, opacity_range = 0; bool random_level = false; level_n = part_ports.size(); bool isPrecomputingEnabled = false; { TRenderer renderer(TRenderer::instance()); isPrecomputingEnabled = (renderer && renderer.isPrecomputingEnabled()) ? true : false; } memset(&values, 0, sizeof(values)); /*- 現在のフレームでの各種パラメータを得る -*/ fill_value_struct(values, m_frame); /*- 不透明度の範囲(透明〜不透明を 0〜1 に正規化)-*/ opacity_range = (values.opacity_val.second - values.opacity_val.first) * 0.01; /*- 開始フレーム -*/ startframe = (int)values.startpos_val; if (values.unit_val == ParticlesFx::UNIT_SMALL_INCH) dpicorr_shrinked = dpicorr / shrink; else dpicorr_shrinked = dpi / shrink; std::map<std::pair<int, int>, double> partScales; curr_frame = curr_frame / values.step_val; ParticlesManager *pc = ParticlesManager::instance(); // Retrieve the last rolled frame ParticlesManager::FrameData *particlesData = pc->data(fxId); std::list<Particle> myParticles; TRandom myRandom; values.random_val = &myRandom; myRandom = m_parent->randseed_val->getValue(); int totalparticles = 0; int pcFrame = particlesData->m_frame; if (pcFrame > curr_frame) { // Clear stored particlesData particlesData->clear(); pcFrame = particlesData->m_frame; } else if (pcFrame >= startframe - 1) { myParticles = particlesData->m_particles; myRandom = particlesData->m_random; totalparticles = particlesData->m_totalParticles; } /*- スタートからカレントフレームまでループ -*/ for (frame = startframe - 1; frame <= curr_frame; ++frame) { int dist_frame = curr_frame - frame; /*- * ループ内の現在のフレームでのパラメータを取得。スタートが負ならフレーム=0のときの値を格納 * -*/ fill_value_struct(values, frame < 0 ? 0 : frame * values.step_val); /*- パラメータの正規化 -*/ normalize_values(values, ri); /*- maxnum_valは"birth_rate"のパラメータ -*/ intpart = (int)values.maxnum_val; /*- * /birth_rateが小数だったとき、各フレームの小数部分を足しこんだ結果の整数部分をintpartに渡す。 * -*/ fractpart = fractpart + values.maxnum_val - intpart; if ((int)fractpart) { values.maxnum_val += (int)fractpart; fractpart = fractpart - (int)fractpart; } std::map<int, TTile *> porttiles; // Perform the roll /*- RenderSettingsを複製して現在のフレームの計算用にする -*/ TRenderSettings riAux(ri); riAux.m_affine = TAffine(); riAux.m_bpp = 32; int r_frame; // Useful in case of negative roll frames if (frame < 0) r_frame = 0; else r_frame = frame; /*- 出力画像のバウンディングボックス -*/ TRectD outTileBBox(tile->m_pos, TDimensionD(tile->getRaster()->getLx(), tile->getRaster()->getLy())); /*- Controlに刺さっている各ポートについて -*/ for (std::map<int, TRasterFxPort *>::iterator it = ctrl_ports.begin(); it != ctrl_ports.end(); ++it) { TTile *tmp; /*- ポートが接続されていて、Fx内で実際に使用されていたら -*/ if ((it->second)->isConnected() && port_is_used(it->first, values)) { TRectD bbox; (*(it->second))->getBBox(r_frame, bbox, riAux); /*- 素材が存在する場合、portTilesにコントロール画像タイルを格納 -*/ if (!bbox.isEmpty()) { if (bbox == TConsts::infiniteRectD) // There could be an infinite // bbox - deal with it bbox = ri.m_affine.inv() * outTileBBox; if (frame <= pcFrame) { // This frame will not actually be rolled. However, it was // dryComputed - so, declare the same here. (*it->second)->dryCompute(bbox, r_frame, riAux); } else { tmp = new TTile; if (isPrecomputingEnabled) (*it->second) ->allocateAndCompute(*tmp, bbox.getP00(), convert(bbox).getSize(), 0, r_frame, riAux); else { std::string alias = "CTRL: " + (*(it->second))->getAlias(r_frame, riAux); 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, riAux); addRenderCache(alias, TRasterImageP(tmp->getRaster())); } } porttiles[it->first] = tmp; } } } } if (frame > pcFrame) { // Invoke the actual rolling procedure roll_particles(tile, porttiles, riAux, myParticles, values, 0, 0, frame, curr_frame, level_n, &random_level, 1, last_frame, totalparticles); // Store the rolled data in the particles manager if (!particlesData->m_calculated || particlesData->m_frame + particlesData->m_maxTrail < frame) { particlesData->m_frame = frame; particlesData->m_particles = myParticles; particlesData->m_random = myRandom; particlesData->buildMaxTrail(); particlesData->m_calculated = true; particlesData->m_totalParticles = totalparticles; } } // Render the particles if the distance from current frame is a trail // multiple if (frame >= startframe - 1 && !(dist_frame % (values.trailstep_val > 1.0 ? (int)values.trailstep_val : 1))) { // Store the maximum particle size before the do_render cycle std::list<Particle>::iterator pt; for (pt = myParticles.begin(); pt != myParticles.end(); ++pt) { Particle &part = *pt; int ndx = part.frame % last_frame[part.level]; std::pair<int, int> ndxPair(part.level, ndx); std::map<std::pair<int, int>, double>::iterator it = partScales.find(ndxPair); if (it != partScales.end()) it->second = std::max(part.scale, it->second); else partScales[ndxPair] = part.scale; } if (values.toplayer_val == ParticlesFx::TOP_SMALLER || values.toplayer_val == ParticlesFx::TOP_BIGGER) myParticles.sort(ComparebySize()); if (values.toplayer_val == ParticlesFx::TOP_SMALLER) { std::list<Particle>::iterator pt; for (pt = myParticles.begin(); pt != myParticles.end(); ++pt) { Particle &part = *pt; if (dist_frame <= part.trail && part.scale && part.lifetime > 0 && part.lifetime <= part.genlifetime) // This last... shouldn't always be? { do_render(flash, &part, tile, part_ports, porttiles, ri, p_size, p_offset, last_frame[part.level], partLevel, values, opacity_range, dist_frame, partScales); } } } else { std::list<Particle>::reverse_iterator pt; for (pt = myParticles.rbegin(); pt != myParticles.rend(); ++pt) { Particle &part = *pt; if (dist_frame <= part.trail && part.scale && part.lifetime > 0 && part.lifetime <= part.genlifetime) // Same here..? { do_render(flash, &part, tile, part_ports, porttiles, ri, p_size, p_offset, last_frame[part.level], partLevel, values, opacity_range, dist_frame, partScales); } } } } std::map<int, TTile *>::iterator it; for (it = porttiles.begin(); it != porttiles.end(); ++it) delete it->second; } }
void Iwa_MotionBlurCompFx::doCompute(TTile &tile, double frame, const TRenderSettings &settings) { /*- 接続していない場合は処理しない -*/ if (!m_input.isConnected() && !m_background.isConnected()) { tile.getRaster()->clear(); return; } /*- BGのみ接続の場合 -*/ if (!m_input.isConnected()) { m_background->compute(tile, frame, settings); return; } /*- 動作パラメータを得る -*/ QList<TPointD> points = getAttributes()->getMotionPoints(); double hardness = m_hardness->getValue(frame); double shutterStart = m_shutterStart->getValue(frame); double shutterEnd = m_shutterEnd->getValue(frame); int traceResolution = m_traceResolution->getValue(); float startValue = (float)m_startValue->getValue(frame); float startCurve = (float)m_startCurve->getValue(frame); float endValue = (float)m_endValue->getValue(frame); float endCurve = (float)m_endCurve->getValue(frame); /*- 軌跡データが2つ以上無い場合は、処理しない -*/ if (points.size() < 2) { if (!m_background.isConnected()) m_input->compute(tile, frame, settings); /*- 背景があり、前景が動かない場合、単純にOverする -*/ else composeWithNoMotion(tile, frame, settings); return; } /*- 表示の範囲を得る -*/ TRectD bBox = TRectD(tile.m_pos /*- Render画像上(Pixel単位)の位置 -*/ , TDimensionD(/*- Render画像上(Pixel単位)のサイズ -*/ tile.getRaster()->getLx(), tile.getRaster()->getLy())); /*- 上下左右のマージンを得る -*/ double minX = 0.0; double maxX = 0.0; double minY = 0.0; double maxY = 0.0; for (int p = 0; p < points.size(); p++) { if (points.at(p).x > maxX) maxX = points.at(p).x; if (points.at(p).x < minX) minX = points.at(p).x; if (points.at(p).y > maxY) maxY = points.at(p).y; if (points.at(p).y < minY) minY = points.at(p).y; } int marginLeft = (int)ceil(abs(minX)); int marginRight = (int)ceil(abs(maxX)); int marginTop = (int)ceil(abs(maxY)); int marginBottom = (int)ceil(abs(minY)); /*- 動かない(=フィルタマージンが全て0)場合、入力タイルをそのまま返す -*/ if (marginLeft == 0 && marginRight == 0 && marginTop == 0 && marginBottom == 0) { if (!m_background.isConnected()) m_input->compute(tile, frame, settings); /*- 背景があり、前景が動かない場合、単純にOverする -*/ else composeWithNoMotion(tile, frame, settings); return; } /*- マージンは、フィルタの上下左右を反転した寸法になる -*/ TRectD enlargedBBox(bBox.x0 - (double)marginRight, bBox.y0 - (double)marginTop, bBox.x1 + (double)marginLeft, bBox.y1 + (double)marginBottom); // std::cout<<"Margin Left:"<<marginLeft<<" Right:"<<marginRight<< // " Bottom:"<<marginBottom<<" Top:"<<marginTop<<std::endl; TDimensionI enlargedDimIn(/*- Pixel単位に四捨五入 -*/ (int)(enlargedBBox.getLx() + 0.5), (int)(enlargedBBox.getLy() + 0.5)); TTile enlarge_tile; m_input->allocateAndCompute(enlarge_tile, enlargedBBox.getP00(), enlargedDimIn, tile.getRaster(), frame, settings); /*- 背景が必要な場合 -*/ TTile back_Tile; if (m_background.isConnected()) { m_background->allocateAndCompute(back_Tile, tile.m_pos, tile.getRaster()->getSize(), tile.getRaster(), frame, settings); } //------------------------------------------------------- /*- 計算範囲 -*/ TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy()); TDimensionI filterDim(marginLeft + marginRight + 1, marginTop + marginBottom + 1); /*- pointsTableの解放は各doCompute内でやっている -*/ int pointAmount = points.size(); float4 *pointsTable = new float4[pointAmount]; float dt = (float)(shutterStart + shutterEnd) / (float)traceResolution; for (int p = 0; p < pointAmount; p++) { pointsTable[p].x = (float)points.at(p).x; pointsTable[p].y = (float)points.at(p).y; /*- zにはp→p+1のベクトルの距離を格納 -*/ if (p < pointAmount - 1) { float2 vec = {(float)(points.at(p + 1).x - points.at(p).x), (float)(points.at(p + 1).y - points.at(p).y)}; pointsTable[p].z = sqrtf(vec.x * vec.x + vec.y * vec.y); } /*- wにはシャッター時間のオフセットを格納 -*/ pointsTable[p].w = -(float)shutterStart + (float)p * dt; } doCompute_CPU(tile, frame, settings, pointsTable, pointAmount, hardness, shutterStart, shutterEnd, traceResolution, startValue, startCurve, endValue, endCurve, marginLeft, marginRight, marginTop, marginBottom, enlargedDimIn, enlarge_tile, dimOut, filterDim, back_Tile); }
void doCompute(TTile &tile, double frame, const TRenderSettings &info) { bool isWarped = m_warped.isConnected(); if (!isWarped) return; if (fabs(m_intensity->getValue(frame)) < 0.01) { m_warped->compute(tile, frame, info); return; } int shrink = (info.m_shrinkX + info.m_shrinkY) / 2; double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); params.m_shrink = shrink; double evolution = m_evol->getValue(frame); double size = 100.0 / info.m_shrinkX; TPointD pos(m_posx->getValue(frame), m_posy->getValue(frame)); //The warper is calculated on a standard reference, with fixed dpi. This makes sure //that the lattice created for the warp does not depend on camera transforms and resolution. TRenderSettings warperInfo(info); double warperScaleFactor = 1.0 / params.m_warperScale; warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine; //Retrieve tile's geometry TRectD tileRect; { TRasterP tileRas = tile.getRaster(); tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy())); } //Build the compute rect TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params); if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return; if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0) return; TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect); double warperEnlargement = getWarperEnlargement(params); warperComputeRect = warperComputeRect.enlarge(warperEnlargement); warperComputeRect.x0 = tfloor(warperComputeRect.x0); warperComputeRect.y0 = tfloor(warperComputeRect.y0); warperComputeRect.x1 = tceil(warperComputeRect.x1); warperComputeRect.y1 = tceil(warperComputeRect.y1); //Compute the warped tile TTile tileIn; m_warped->allocateAndCompute(tileIn, warpedComputeRect.getP00(), TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()), tile.getRaster(), frame, info); TRasterP rasIn = tileIn.getRaster(); //Compute the warper tile TSpectrum::ColorKey colors[] = { TSpectrum::ColorKey(0, TPixel32::White), TSpectrum::ColorKey(1, TPixel32::Black)}; TSpectrumParamP cloudscolors = TSpectrumParamP(tArrayCount(colors), colors); //Build the warper warperInfo.m_affine = warperInfo.m_affine; TAffine aff = warperInfo.m_affine.inv(); TTile warperTile; TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy()); warperTile.m_pos = warperComputeRect.getP00(); warperTile.setRaster(rasWarper); { TRenderSettings info2(warperInfo); //Now, separate the part of the affine the Fx can handle from the rest. TAffine fxHandledAffine = handledAffine(warperInfo, frame); info2.m_affine = fxHandledAffine; TAffine aff = warperInfo.m_affine * fxHandledAffine.inv(); aff.a13 /= warperInfo.m_shrinkX; aff.a23 /= warperInfo.m_shrinkY; TRectD rectIn = aff.inv() * warperComputeRect; //rectIn = rectIn.enlarge(getResampleFilterRadius(info)); //Needed to counter the resample filter TRect rectInI(tfloor(rectIn.x0), tfloor(rectIn.y0), tceil(rectIn.x1) - 1, tceil(rectIn.y1) - 1); // rasIn e' un raster dello stesso tipo di tile.getRaster() TTile auxtile(warperTile.getRaster()->create(rectInI.getLx(), rectInI.getLy()), convert(rectInI.getP00())); TPointD mypos(auxtile.m_pos - pos); double scale2 = sqrt(fabs(info2.m_affine.det())); doClouds(auxtile.getRaster(), cloudscolors, mypos, evolution, size, 0.0, 1.0, PNOISE_CLOUDS, scale2, frame); info2.m_affine = aff; TRasterFx::applyAffine(warperTile, auxtile, info2); } //Warp TPointD db; TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db)); TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI); TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00()); TPointD warperPos((TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00()); warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params); }
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override { Status status = getFxStatus(m_light, m_lighted); if (status & NoPortsConnected) // If no port, just do nothing :) return; // Calculate source if (status & Port1Connected) m_lighted->compute(tile, frame, ri); // Calculate light if (status & Port0Connected) { // Init light infos TDimension tileSize(tile.getRaster()->getSize()); TRectD tileRect(tile.m_pos, TDimensionD(tileSize.lx, tileSize.ly)); double scale = sqrt(fabs(ri.m_affine.det())); double blur = m_value->getValue(frame) * scale; // Build the light interesting rect TRectD lightRect, blurOutRect; m_light->getBBox(frame, lightRect, ri); buildLightRects(tileRect, lightRect, blurOutRect, blur); if ((lightRect.getLx() <= 0) || (lightRect.getLy() <= 0)) return; if ((blurOutRect.getLx() <= 0) || (blurOutRect.getLy() <= 0)) return; // Calculate the light tile TTile lightTile; TDimension lightSize(tround(lightRect.getLx()), tround(lightRect.getLy())); m_light->allocateAndCompute(lightTile, lightRect.getP00(), lightSize, tile.getRaster(), frame, ri); // Init glow parameters TPixel32 color = m_color->getValue(frame); double brightness = m_brightness->getValue(frame) / 100.0; double fade = m_fade->getValue(frame) / 100.0; // Now, apply the glow // First, deal with the fade { TRasterP light = lightTile.getRaster(); TRaster32P light32 = light; TRaster64P light64 = light; if (light32) ::fade(light32, fade, color); else if (light64) ::fade(light64, fade, toPixel64(color)); else assert(false); } // Then, build the blur TRasterP blurOut; if (blur > 0) { // Build a temporary output to the blur { TRasterP light(lightTile.getRaster()); blurOut = light->create(tround(blurOutRect.getLx()), tround(blurOutRect.getLy())); // Apply the blur. Please note that SSE2 should not be used for now - // I've seen it // doing strange things to the blur... TPointD displacement(lightRect.getP00() - blurOutRect.getP00()); TRop::blur(blurOut, light, blur, tround(displacement.x), tround(displacement.y), false); } } else blurOut = lightTile.getRaster(); // Apply the rgbm scale TRop::rgbmScale(blurOut, blurOut, 1, 1, 1, brightness); // Apply the add { TRectD interestingRect(tileRect * blurOutRect); TRect interestingTileRect(tround(interestingRect.x0 - tileRect.x0), tround(interestingRect.y0 - tileRect.y0), tround(interestingRect.x1 - tileRect.x0) - 1, tround(interestingRect.y1 - tileRect.y0) - 1); TRect interestingBlurRect( tround(interestingRect.x0 - blurOutRect.x0), tround(interestingRect.y0 - blurOutRect.y0), tround(interestingRect.x1 - blurOutRect.x0) - 1, tround(interestingRect.y1 - blurOutRect.y0) - 1); if ((interestingTileRect.getLx() <= 0) || (interestingTileRect.getLy() <= 0)) return; if ((interestingBlurRect.getLx() <= 0) || (interestingBlurRect.getLy() <= 0)) return; TRasterP tileInterestRas( tile.getRaster()->extract(interestingTileRect)); TRasterP blurInterestRas(blurOut->extract(interestingBlurRect)); TRop::add(blurInterestRas, tileInterestRas, tileInterestRas); } } }
void TExternalProgramFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { TRaster32P ras = tile.getRaster(); if (!ras) return; std::string args = m_args; std::string executablePath = ::to_string(m_executablePath); std::map<std::string, TFilePath> tmpFiles; // portname --> file TFilePath outputTmpFile; std::map<std::string, Port>::const_iterator portIt; for (portIt = m_ports.begin(); portIt != m_ports.end(); ++portIt) { TFilePath fp = TSystem::getUniqueFile("externfx"); fp = fp.withType(portIt->second.m_ext); tmpFiles[portIt->first] = fp; if (portIt->second.m_port == 0) // solo una porta e' di output outputTmpFile = fp; else { TRasterFxPort *tmp; tmp = portIt->second.m_port; if (tmp->isConnected()) { (*tmp)->compute(tile, frame, ri); TImageWriter::save(fp, ras); } } } // args e' della forma "$src $ctrl -o $out -v $value" // sostituisco le variabili int i = 0; for (;;) { i = args.find('$', i); if (i == (int)std::string::npos) break; int j = i + 1; int len = args.length(); while (j < len && isalnum(args[j])) j++; // un '$' non seguito da caratteri alfanumerici va ignorato if (j == i + 1) { // la sequenza '$$' diventa '$' if (j < len && args[j] == '$') args.replace(i, 2, "$"); i++; continue; } // ho trovato una variabile int m = j - i - 1; std::string name = args.substr(i + 1, m); // calcolo il valore. std::string value; std::map<std::string, TFilePath>::const_iterator it; it = tmpFiles.find(name); if (it != tmpFiles.end()) { // e' una porta. il valore e' il nome del // file temporaneo value = "\"" + ::to_string(it->second.getWideString()) + "\""; } else { // e' un parametro // se il nome non viene riconosciuto sostituisco la stringa nulla TDoubleParamP param = TParamP(getParams()->getParam(name)); if (param) value = std::to_string(param->getValue(frame)); } args.replace(i, m + 1, value); } args = " " + args; // aggiungo uno spazio per sicurezza // ofstream os("C:\\temp\\butta.txt"); // os << args << endl; // bisognerebbe calcolare le immagini dalla/e porta/e di input // scrivere il/i valore/i nei files temporanei/o // chiamare "m_executablePath args" // e leggere l'immagine scritta in outputTmpFile // poi cancellare tutto std::string expandedargs; char buffer[1024]; #ifdef _WIN32 ExpandEnvironmentStrings(args.c_str(), buffer, 1024); STARTUPINFO si; PROCESS_INFORMATION pinfo; GetStartupInfo(&si); BOOL ret = CreateProcess( (char *)executablePath.c_str(), // name of executable module buffer, // command line string NULL, // SD NULL, // SD TRUE, // handle inheritance option CREATE_NO_WINDOW, /*CREATE_NEW_CONSOLE*/ // creation flags NULL, // new environment block NULL, // current directory name &si, // startup information &pinfo // process information ); if (!ret) DWORD err = GetLastError(); // aspetta che il processo termini WaitForSingleObject(pinfo.hProcess, INFINITE); DWORD exitCode; ret = GetExitCodeProcess(pinfo.hProcess, // handle to the process &exitCode); // termination status #else std::string cmdline = executablePath + buffer; // int exitCode = system(cmdline.c_str()); #endif /* string name = m_executablePath.getName(); TPixel32 color; if(name == "saturate") color = TPixel32::Magenta; else if(name == "over") color = TPixel32::Green; else color = TPixel32::Red; for(int iy=0;iy<ras->getLy();iy++) { TPixel32 *pix = ras->pixels(iy); TPixel32 *endPix = pix + ras->getLx(); double x = tile.m_pos.x; double y = tile.m_pos.y + iy; while(pix<endPix) { if(x*x+y*y<900) *pix = color; else *pix = TPixel32(0,0,0,0); ++pix; x+=1.0; } } */ try { TRasterP ras = tile.getRaster(); TImageReader::load(outputTmpFile, ras); } catch (...) { } // butto i file temporanei creati std::map<std::string, TFilePath>::const_iterator fileIt; for (fileIt = tmpFiles.begin(); fileIt != tmpFiles.end(); ++fileIt) { if (TFileStatus(fileIt->second).doesExist() == true) try { TSystem::deleteFile(fileIt->second); } catch (...) { } } if (TFileStatus(outputTmpFile).doesExist() == true) try { TSystem::deleteFile(outputTmpFile); } catch (...) { } }
void Iwa_GradientWarpFx::doCompute(TTile &tile, double frame, const TRenderSettings &settings) { /*- ソース画像が刺さっていなければreturn -*/ if (!m_source.isConnected()) { tile.getRaster()->clear(); return; } /*- 参照画像が刺さっていなければ、ソース画像をそのまま返す -*/ if (!m_warper.isConnected()) { m_source->compute(tile, frame, settings); return; } /*- 計算パラメータを得る -*/ /*- 移動距離のピクセルサイズ -*/ /*--- 拡大縮小(移動回転しないで)のGeometryを反映させる ---*/ double k = sqrt(fabs(settings.m_affine.det())); double hLength = m_h_maxlen->getValue(frame) * k; double vLength = m_v_maxlen->getValue(frame) * k; double scale = m_scale->getValue(frame); /*- ワープ距離が0なら、ソース画像をそのまま返す -*/ if (hLength == 0.0 && vLength == 0.0) { m_source->compute(tile, frame, settings); return; } int margin = static_cast<int>(ceil((abs(hLength) < abs(vLength)) ? abs(vLength) : abs(hLength))); /*- 素材計算範囲を計算 -*/ /*- 出力範囲 -*/ TRectD rectOut(tile.m_pos, TDimensionD( tile.getRaster()->getLx(), tile.getRaster()->getLy())); TRectD enlargedRect = rectOut.enlarge((double)margin); TDimensionI enlargedDim((int)enlargedRect.getLx(), (int)enlargedRect.getLy()); /*- ソース画像を正規化して格納 -*/ float4 *source_host; TRasterGR8P source_host_ras(enlargedDim.lx * sizeof(float4), enlargedDim.ly); source_host_ras->lock(); source_host = (float4 *)source_host_ras->getRawData(); { /*- タイルはこのフォーカス内だけ使用。正規化してsource_hostに取り込んだらもう使わない。 -*/ TTile sourceTile; m_source->allocateAndCompute( sourceTile, enlargedRect.getP00(), enlargedDim, tile.getRaster(), frame, settings); /*- タイルの画像を0〜1に正規化してホストメモリに読み込む -*/ TRaster32P ras32 = (TRaster32P)sourceTile.getRaster(); TRaster64P ras64 = (TRaster64P)sourceTile.getRaster(); if (ras32) setSourceRaster<TRaster32P, TPixel32>(ras32, source_host, enlargedDim); else if (ras64) setSourceRaster<TRaster64P, TPixel64>(ras64, source_host, enlargedDim); } /*- 参照画像を正規化して格納 -*/ float *warper_host; TRasterGR8P warper_host_ras(enlargedDim.lx * sizeof(float), enlargedDim.ly); warper_host_ras->lock(); warper_host = (float *)warper_host_ras->getRawData(); { /*- タイルはこのフォーカス内だけ使用。正規化してwarper_hostに取り込んだらもう使わない -*/ TTile warperTile; m_warper->allocateAndCompute( warperTile, enlargedRect.getP00(), enlargedDim, tile.getRaster(), frame, settings); /*- タイルの画像の輝度値を0〜1に正規化してホストメモリに読み込む -*/ TRaster32P ras32 = (TRaster32P)warperTile.getRaster(); TRaster64P ras64 = (TRaster64P)warperTile.getRaster(); if (ras32) setWarperRaster<TRaster32P, TPixel32>(ras32, warper_host, enlargedDim); else if (ras64) setWarperRaster<TRaster64P, TPixel64>(ras64, warper_host, enlargedDim); } /*- 変位値をScale倍して増やす -*/ hLength *= scale; vLength *= scale; TRasterGR8P result_host_ras; result_host_ras = TRasterGR8P(enlargedDim.lx * sizeof(float4), enlargedDim.ly); /*- 結果を収めるメモリ -*/ float4 *result_host; result_host_ras->lock(); result_host = (float4 *)result_host_ras->getRawData(); doCompute_CPU(tile, frame, settings, hLength, vLength, margin, enlargedDim, source_host, warper_host, result_host); /*- ポインタ入れ替え -*/ source_host = result_host; int2 yohaku = {(enlargedDim.lx - tile.getRaster()->getSize().lx) / 2, (enlargedDim.ly - tile.getRaster()->getSize().ly) / 2}; /*- ラスタのクリア -*/ tile.getRaster()->clear(); TRaster32P outRas32 = (TRaster32P)tile.getRaster(); TRaster64P outRas64 = (TRaster64P)tile.getRaster(); if (outRas32) setOutputRaster<TRaster32P, TPixel32>(source_host, outRas32, enlargedDim, yohaku); else if (outRas64) setOutputRaster<TRaster64P, TPixel64>(source_host, outRas64, enlargedDim, yohaku); /*- ソース画像のメモリ解放 -*/ source_host_ras->unlock(); /*- 参照画像のメモリ解放 -*/ warper_host_ras->unlock(); result_host_ras->unlock(); }
/*------------------------------------------------------------ 背景を露光値にして通常合成 ------------------------------------------------------------*/ void Iwa_MotionBlurCompFx::composeBackgroundExposure_CPU( float4 *out_tile_p, TDimensionI &enlargedDimIn, int marginRight, int marginTop, TTile &back_tile, TDimensionI &dimOut, float hardness) { /*- ホストのメモリ確保 -*/ TRasterGR8P background_host_ras(sizeof(float4) * dimOut.lx, dimOut.ly); background_host_ras->lock(); float4 *background_host = (float4 *)background_host_ras->getRawData(); bool bgIsPremultiplied; /*- 背景画像を0〜1に正規化してホストメモリに読み込む -*/ TRaster32P backRas32 = (TRaster32P)back_tile.getRaster(); TRaster64P backRas64 = (TRaster64P)back_tile.getRaster(); if (backRas32) bgIsPremultiplied = setSourceRaster<TRaster32P, TPixel32>( backRas32, background_host, dimOut); else if (backRas64) bgIsPremultiplied = setSourceRaster<TRaster64P, TPixel64>( backRas64, background_host, dimOut); float4 *bg_p = background_host; float4 *out_p; for (int j = 0; j < dimOut.ly; j++) { out_p = out_tile_p + ((marginTop + j) * enlargedDimIn.lx + marginRight); for (int i = 0; i < dimOut.lx; i++, bg_p++, out_p++) { /*- 上レイヤが完全に不透明ならcontinue -*/ if ((*out_p).w >= 1.0f) continue; /*- 下レイヤが完全に透明でもcontinue -*/ if ((*bg_p).w < 0.0001f) continue; float3 bgExposure = {(*bg_p).x, (*bg_p).y, (*bg_p).z}; /*- 通常のLevelなど、Premultiplyされている素材に対し、depremultiplyを行う DigiBookなどには行わない -*/ if (bgIsPremultiplied) { // demultiply bgExposure.x /= (*bg_p).w; bgExposure.y /= (*bg_p).w; bgExposure.z /= (*bg_p).w; } /*- ExposureをRGB値にする -*/ bgExposure.x = powf(10, (bgExposure.x - 0.5f) * hardness); bgExposure.y = powf(10, (bgExposure.y - 0.5f) * hardness); bgExposure.z = powf(10, (bgExposure.z - 0.5f) * hardness); // multiply bgExposure.x *= (*bg_p).w; bgExposure.y *= (*bg_p).w; bgExposure.z *= (*bg_p).w; /*- 手前とOver合成 -*/ (*out_p).x = (*out_p).x + bgExposure.x * (1.0f - (*out_p).w); (*out_p).y = (*out_p).y + bgExposure.y * (1.0f - (*out_p).w); (*out_p).z = (*out_p).z + bgExposure.z * (1.0f - (*out_p).w); /*- アルファ値もOver合成 -*/ (*out_p).w = (*out_p).w + (*bg_p).w * (1.0f - (*out_p).w); } } background_host_ras->unlock(); }
void FreeDistortBaseFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { if (!m_input.isConnected()) return; //Upon deactivation, this fx does nothing. if (m_deactivate->getValue()) { m_input->compute(tile, frame, ri); return; } //Get the source quad TPointD p00_b = m_p00_b->getValue(frame); TPointD p10_b = m_p10_b->getValue(frame); TPointD p01_b = m_p01_b->getValue(frame); TPointD p11_b = m_p11_b->getValue(frame); //Get destination quad TPointD p00_a = m_p00_a->getValue(frame); TPointD p10_a = m_p10_a->getValue(frame); TPointD p01_a = m_p01_a->getValue(frame); TPointD p11_a = m_p11_a->getValue(frame); if (m_isCastShadow) { //Shadows are mirrored tswap(p00_a, p01_a); tswap(p10_a, p11_a); } //Get requested tile's geometry TRasterP tileRas(tile.getRaster()); TRectD tileRect(convert(tileRas->getBounds()) + tile.m_pos); //Call transform to get the minimal rectOnInput TRectD inRect; TRenderSettings riNew; TRectD inBBox; safeTransform(frame, 0, tileRect, ri, inRect, riNew, inBBox); //Intersect with the bbox inRect *= inBBox; if (myIsEmpty(inRect)) return; double scale = ri.m_affine.a11; double downBlur = m_downBlur->getValue(frame) * scale; double upBlur = m_upBlur->getValue(frame) * scale; int brad = tceil(tmax(downBlur, upBlur)); inRect = inRect.enlarge(brad); TDimension inRectSize(tceil(inRect.getLx()), tceil(inRect.getLy())); TTile inTile; m_input->allocateAndCompute(inTile, inRect.getP00(), inRectSize, tileRas, frame, riNew); TPointD inTilePosRi = inTile.m_pos; //Update quads by the scale factors p00_b = riNew.m_affine * p00_b; p10_b = riNew.m_affine * p10_b; p01_b = riNew.m_affine * p01_b; p11_b = riNew.m_affine * p11_b; p00_a = ri.m_affine * p00_a; p10_a = ri.m_affine * p10_a; p01_a = ri.m_affine * p01_a; p11_a = ri.m_affine * p11_a; PerspectiveDistorter perpDistorter( p00_b - inTile.m_pos, p10_b - inTile.m_pos, p01_b - inTile.m_pos, p11_b - inTile.m_pos, p00_a, p10_a, p01_a, p11_a); BilinearDistorter bilDistorter( p00_b - inTile.m_pos, p10_b - inTile.m_pos, p01_b - inTile.m_pos, p11_b - inTile.m_pos, p00_a, p10_a, p01_a, p11_a); TQuadDistorter *distorter; if (m_distortType->getValue() == PERSPECTIVE) distorter = &perpDistorter; else if (m_distortType->getValue() == BILINEAR) distorter = &bilDistorter; else assert(0); if (m_isCastShadow) { TRaster32P ras32 = inTile.getRaster(); TRaster64P ras64 = inTile.getRaster(); if (ras32) { if (m_fade->getValue(frame) > 0) doFade(ras32, m_color->getValue(frame), m_fade->getValue(frame) / 100.0); if (brad > 0) doBlur(ras32, upBlur, downBlur, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0, inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y); else if (m_upTransp->getValue(frame) > 0 || m_downTransp->getValue(frame) > 0) doTransparency(ras32, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0, inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y); } else if (ras64) { if (m_fade->getValue(frame) > 0) doFade(ras64, toPixel64(m_color->getValue(frame)), m_fade->getValue(frame) / 100.0); if (brad > 0) doBlur(ras64, upBlur, downBlur, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0, inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y); else if (m_upTransp->getValue(frame) > 0 || m_downTransp->getValue(frame) > 0) doTransparency(ras64, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0, inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y); } else assert(false); } distort(tileRas, inTile.getRaster(), *distorter, convert(tile.m_pos), TRop::Bilinear); }